Tutoriel Vert.x

Préparation

Commencez par télécharger et décompresser l’archive contenant le code dont nous aurons besoin pour la session d’aujourd’hui.

Téléchargez code de base

Ouvrez le dossier dans VSCode. Vous devriez avoir la structure suivante :

  • les sources de notre serveur sont dans le dossier src;
  • un fichier docker-compose.yml qui décrit les conteneurs à lancer pour les capteurs et le frontend;
  • des fichiers de configuration pour la gestion des bibliothèques externes sont dans le dossier gradle et les fichiers gradlew, gradlew.bat, settings.gradle;
  • un fichier readme.md avec des instructions sommaires pour lancer le projet.

Pour compiler et lancer le projet, ouvrez un terminal dans VSCode et utilisez ./gradlew.bat run (windows) ou ./gradlew run (macOS / linux). L’outil va télécharger automatiquement les bibliothèques utilisées par le projet, compiler les sources et lancer le serveur.

Le terminal devrait se stabiliser sur un message similaire au screenshot.

Vous devriez alors pouvoir aller ici et voir le message Hello world!.

Tour du code

Le code de ce projet est structuré comme suit :

  • VertxServer.java contient toute la logique d’initialisation du serveur et de configuration des routes;
  • DisplayRequestHandler.java et UDPHandler.java contiennent deux exemples de handlers.

La configuration du serveur

Ouvrez VertexServer.java, c’est dans la méthode start() que nous placerons tout le code qui va indiquer quelles méthodes Java appeler lorsqu’une requête arrive sur notre serveur.

public void start() {
    // create a router that we will use to route HTTP requests to different handlers
    Router router = Router.router(vertx);
    
    // register a handler that process payload of HTTP requests for us
    router.route().handler(BodyHandler.create());
    
    // we register handlers here
    DisplayRequestHandler myHandler = new DisplayRequestHandler();
    
    // this will catch all call to localhost:8080/hello whatever the HTTP method is
    router.route("/hello").handler(myHandler);
    
    // this will catch GET / POST requests to localhost:8080/hello/<something>
    router.get("/hello/:name").handler(myHandler);
    router.post("/hello/:name").handler(myHandler);
    

    // we start the HTTP server
    vertx.createHttpServer().requestHandler(router).listen(8080);
}

Dans cet exemple, nous enregistrons un même handler pour trois routes différentes :

  • /hello pour toutes les méthodes HTTP;
  • /hello/:name pour le GET et le POST.

Dans un premier temps essayer ces routes et observez le terminal, vous devriez voir des messages donnant des informations sur la requête entrante.

Astuce

Lorsque vous accéder à une page web votre navigateur envoi une requête GET.

Pour tester notre route avec la méthode POST vous pouvez utiliser curl depuis la ligne de commande curl -X POST http://localhost:8080/hello/Melanie.

Ou bien cliquer sur le bouton suivant :

La suite de la méthode start() initialise un second serveur qui écoute sur le port 12345 et traite uniquement des paquets UDP en utilisant le handler UDPHandler.

// create a UDP socket
DatagramSocket socket = vertx.createDatagramSocket();
// register a handler for this server
socket.handler(new UDPHandler());

// start the server to listen on all interfaces on port 12345
socket.listen(12345, "0.0.0.0");

Les handlers

DisplayHandler.java

Regardez maintenant DisplayHandler.java. Notez que la classe implémente l’interface Handler<RoutingContext> et redéfinie la méthode handle(RoutingContext). C’est cette méthode qui est appelée par le serveur lorsque qu’une requête avec la bonne route arrive.

L’objet RoutingContext que nous recevons en paramètre contient toutes les informations sur la requête et possèdes des méthodes pour envoyer la réponse que l’on souhaite.

Astuce

Vous trouverez toutes les méthodes que vous pouvez utiliser sur un RoutingContext ici. Les méthodes que vous utiliserez le plus sont String pathParam(String), String queryParam(String), RequestBody body(), HttpServerRequest request(), HttpServerResponse response() ainsi que les méthodes end(String) et json(Object).

Exercice 1

Modifiez la méthode handle() de DisplayHandler.java de façon à ce que le message affiché par le navigateur soit Hello toto! depuis ce lien mais toujours Hello world! depuis ce lien.

Exercice 2

Faites une nouvelle route qui réponde aux requêtes GET /hello/<nom>/<prenom> et affiche Bonjour <nom> <prenom> dans le navigateur.

Exercice 3

Adaptez DisplayHandler.java de l’exercice 1 pour retourner un objet JSON comme suit :

{
    "msg": "Hello World!",
    "name": "John"
}

Si aucun nom n’est passé en paramètre vous devrez répondre :

{
    "msg": "Hello World!",
    "name": "anonymous"
}

Vous utiliserez un JsonObject, qui se comporte comme un dictionnaire python, pour créer votre réponse.


UDPHandler.java

Regardez maintenant UDPHandler.java. Notez qu’il implémente toujours l’interface Handler mais que le type traité à changé. C’est maintenant Handler<DatagramPacket>, un DatagramPacket est un paquet UDP.

Le traitement du paquet est ici très simple, nous récupérons le contenu du paquet avec la méthode data(), récupérons sa représentation sous forme de chaîne de caractères avec `toString() et l’affichons dans le terminal.

@Override
public void handle(DatagramPacket packet) {
    String payload = packet.data().toString();
    System.out.println("Incoming UDP data: " + payload);
}

Comme ce handler gère les paquets UDP nous ne pouvons pas directement le tester depuis le navigateur. Nous verrons dans la suite du TP que vous avez à disposition un capteur simulé qui envoie régulièrement des paquets UDP à notre serveur.