Introduzione
Nel primo appuntamento con Vert.x [1] abbiamo visto quali sono i mattoni e le funzionalità che il toolkit mette a disposizione del programmatore per costruire applicazioni. Abbiamo visto che, oltre alla parte core, esistono numerose estensioni: ci sono, ad esempio, quelle che permettono di gestire accesso ai dati (DB relazionali e non), sviluppo web (client e server), sviluppo orientato ai microservizi (Service Discovery, Service Config etc.) e ce ne sono altre più specifiche che permettono, in definitiva, di coprire ogni aspetto di programmazione.
In questo articolo vedremo come creare un progetto e introdurremo la base per la navigazione web che in Vert.x si base sul concetto di routing. Poco dopo la pubblicazione del’articolo precedente è stata rilasciata la versione 3.5.0 di Vert.x, che quindi andremo a utilizzare per i nostro progetto. Vedremo magari in un articolo apposito quali novità abbia introdotto questa versione.
Per cominciare
Come detto in precedenza, per sviluppare in Vert.x non è necessario usare uno specifico linguaggio, essendo il toolkit completamente poliglotta. Per semplicità (mia), nel corso della serie useremo Java nella sua ultima versione.
Per comodità, ci avvarremo di un IDE; premesso che tutto il codice potrebbe anche essere sviluppato tramite blocco note… perché non utilizzare tutti facilitatori che un IDE mette a disposizione per renderci la vita più facile? Andrà bene qualsisasi IDE che supporti un progetto Maven.
Strutturiamo il progetto
La struttura delle directory ricalca quella di un progetto maven; vedremo poi le directory aggiunte che permettono a Vert.x di grestire ad esempio le configurazioni.
Ora, ci sono due modi per generare un progetto con Vert.x: il primo è mettersi di buon impegno e creare la struttura delle directory, il file pom.xml e sistemare tutte le configurazioni per eseguire il build del progetto e generare così un JAR eseguibile; il secondo consiste nell’utilizzare un plugin di maven dedicato a Vert.x che fa tutto questo per noi.
Passi metodo 1
Vediamo i passi del primo metodo.
Anzitutto si crea la struttura della directory.
Poi si crea il file pom.xml.
Si aggiungono le dipendenze
E infine si fanno build e run del progetto
Tutto molto semplice. Il problema si presente se dobbiamo creare più progetti, quando ad esempio stiamo sviluppando un’applicazione a microservizi: in tal caso siamo costretti a fare una serie di copia e incolla oppure possiamo far generare il progetto dal nostro IDE.
Passi metodo 2
Per semplificare le cose, utilizzeremo maven-vertx-plugin [5] che, oltre a permettere la creazione del progetto inteso come struttura, permette in maniera semplice anche di gestire la generazione del fat-jar e la gestione dell’avvio e dello stop dell’applicazione.
Per iniziare, generiamo lo scheletro della nostra applicazione. In generale vorrei andare oltre al solito Hello Word e gettare anche le basi per i futuri articoli: quindi già da oggi andremo a creare la nostra applicazione che permetterà di gestire la nostra lista delle cose da fare.
Apriamo quindi la nostra console preferita e digitiamo il seguente comando maven
Alla fine dell’esecuzione del comando, abbiamo il nostro scheletro pronto per essere esteso. Da notare che, nel nostro caso, abbiamo anche incluso automaticamente le dipendenze per la parte web di Vert.x senza dover editare il nostro pom.xml. Avremmo potuto aggiungere anche altri moduli.
Di seguito, possiamo vedere il nostro pom.xml che è stato generato in automatico. Attualmente il plug-in utilizza ancora Vert.x 3.4.2 e Java 8.
Ma, per essere pronti a lavorare con le ultime versioni disponibili di Java e Vert.x, basta cambiare le properties nelle seguenti:
Ora, lanciando il comando mvn clean install, vediamo che la nostra applicazione verrà compilata e verrà generato il file todolist-project-1.0-SNAPSHOT.jar all’interno della directory target. Possiamo quindi lanciare la nostra applicazione con il comando java -jar todolist-project-1.0-SNAPSHOT.jar.
I lettori possono trovare il repository nella versione base come master sul mio spazio github [6]: ogni nuova feature sarà creata su un branch dedicato; poi, a mano a mano che completeremo le funzionalità, andremo a reintegrare il tutto sul master.
La versione iniziale di pom.xml
Di seguito, vediamo come si presenta il nostro pom.xml nella versione iniziale:
Ora che abbiamo tutto pronto, possiamo cominciare a mettere il codice nel progetto. Volendo esplorare tutte le caratteristiche del toolkit, la mia idea è di strutturare il progetto con tre verticles: uno dedicato alla parte web, uno per l’accesso al datastore e quello base che serve alla configurazione dell’applicazione e fare il deploy dei verticles necessari.
Verticles e server web
Cominciamo a creare due package datastore e web e, nel secondo, creiamo il nostro verticle che si occuperà della gestione dell’API REST e della parte statica.
Come possiamo vedere dalla documentazione e dallo scheletro creato, ogni classe che vogliamo sia un verticle estende dalla classe astratta AbstractVerticle di cui faremo l’override del metodo start() e all’occorrenza del metodo stop().
Scaricando il progetto possiamo vedere nella classe Todo il deploy del verticle WebVerticle:
Nelle prossime puntate vedremo come far comunicare tra loro i verticle.
Definiamo il server
Nel WebVerticle definiamo la parte web. Per prima cosa creiamo il router che stabilirà, in base alle rotte che andremo a definire, come si comporterà la nostra applicazione.
Per la parte statica utilizzeremo per il nostro handler di risposta la classe StaticHandler che il toolkit mette direttamente a nostra disposizione.
Basta definire una directory all’interno della cartella resources dove andare a mettere le nostre pagine HTML. Per default, il nostro server risponderà con la pagina index.html.
router.route(“/”).handler(StaticHandler.create(“web”));
Per la parte di API REST andiamo a definire le “rotte” che permettono di creare un semplice CRUD per la lista dei TODO:
- GET /api/todo
- GET /api/todo/:id
- POST /api/todo
- PUT /api/todo/:id
- DELETE /api/todo/:id
Con la riga
router.route("/api/todo*").handler(BodyHandler.create());
configuriamo il nostro server in maniera tale da accettare il body delle richieste per le chiamate che hanno come path base “/api/todo. Questo permette di leggere il body delle nostre chiamate e poter così recuperare parametri e così via.
Per finire definiamo il nostro server e lo mettiamo in ascolto sulla porta 9000.
Model e Handler
Prima di vedere l’implementazione dei metodi che permettono di generare una risposta alle nostre chiamate, andiamo a definire il nostro Data Model che utilizzeremo anche per le prossime puntate. Lo potete trovare nella classe TodoModel.java. Ho creato anche la classe UserModel.java per una possibile idea di sviluppo.
Per alcune cose, tipo i metodi equals, hasCode e ToString, mi sono affidato al mio IDE per la generazione del codice.
L’implementazione degli handler risulta molto semplice grazie al toolkit che permette in maniera agevole e veloce di leggere parametri e oggetti Json e mapparli su bean.
Per l’implementazione completa dei metodi vi rimando al codice su GitHub (branch web). Qui di seguito possiamo vedere i metodi che restituiscono tutti i nostri TODO e il metodo per creare una nuova TODO.
Lanciamo l’applicazione
Ora che abbiamo completato tutto il codice, lanciamo la nostra applicazione con il comando mvn clean vertx:run e utilizziamo un client qualsiasi, da curl a postman per provare la nostra API REST. Qui sotto potete vedere la chiamata per la creazione di una nuova todo usando curl.
Di seguito, vediamo una una GET per recuperare la lista delle nostre cose da fare.
Conclusioni
Abbiamo visto con questo secondo articolo come definire un web server e implementare una pagina statica per la visualizzazione delle nostre cose da fare, che in verità andrà ancora fatta. In più abbiamo visto come, tramite il nostro toolkit, sia molto semplice creare API REST e leggere parametri e body request.
Come compitom creiamo il nostro ambiente di test per verificare le nostre API in maniera automatica e prepariamo la pagina HTML statica pronta per visualizzare la nostra lista e poterle modificare.
Nel prossimo appuntamento vedremo come agganciare un datastore e come far dialogare due verticles utilizzando messaggi e lasciando tutto asincrono.