Comment développer des microservices avec OpenAPI et Thorntail ?

microservices-thorntail-openapi

Comment développer des microservices avec OpenAPI et Thorntail ?

Je vous propose aujourd’hui de découvrir comment développer des microservices avec OpenAPI et Thorntail.  Je focalise ainsi mon article sur la définition et l’implémentation des microservices :

  • Tout d’abord, j’y aborde les spécifications des APIs qui, dans une architecture microservices, revêtent une importance de premier plan.
  • Ensuite, j’illustre l’implémentation en Java avec le framework Thorntail de ces APIs.

Les sources illustrant cet article sont disponibles, sous licence open source MIT, dans le dépôt GitHub.

Pour rappel, dans le précédent article de cette série, ma collègue avait exposé comment s’orienter vers une architecture microservices par une analyse fonctionnelle faisant émerger une découpe en domaines des entités métier et des interfaces.

Développer des microservices avec OpenAPI : les bonnes pratiques de conception des APIs

Replongeons dans l’exemple de l’agence immobilière. L’analyse fonctionnelle a identifié les processus, les domaines et les entités avec leurs attributs et leurs méthodes. Plus particulièrement, il est possible de modéliser comme suit, les composants qui émergent lorsque l’attention est portée sur le processus de mise en location.

modelisation-microservices-exemple

En poursuivant l’exemple de l’acteur de l’immobilier initié dans l’article précédent et en respectant le formalisme OpenAPI (https://www.openapis.org/), j’obtiens  :


openAPI

OpenAPI

openAPI

OpenAPI

OpenAPI

OpenAPI

Développer des microservices avec Thorntail

Thorntail est un framework Java permettant de développer des applications d’entreprise telles que des microservices en s’affranchissant d’un serveur application. Seules les fonctionnalités souhaitées, appelées fractions, du serveur d’application sont embarquées dans l’application finale qui s’exécutent de façon autonome.

Créer le projet avec Thorntail

Le projet peut être généré en ligne : http://thorntail.io/generator. Il suffit de choisir les fractions désirées et le tour est joué. J’ai choisi MicroProfile OpenAPI naturellement ainsi que MicroProfile Health afin de disposer de sondes toujours utiles dans un environnement microservices.

Un rapide coup d’œil au fichier pom.xml montre la présence des fractions choisies :

fichier-pomxml-thorntail

Si Thorntail aide à la mise en place des sondes, leur logique doit être définie. Une annotation (@Readiness ou @Liveness) et une interface à implémenter (HealthCheck) suffisent pour chaque sonde. Une implémentation très simple suffit pour moment :

interface-healthcheck

Il est déjà temps de vérifier que tout fonctionne comme espéré. Puisqu’un microservice Thorntail ne requiert pas de serveur d’application, son lancement peut se faire sous la forme d’un simple jar.


mvn clean package

java -jar ./target/immo-tenants-management-thorntail.jar


Le démarrage montre les fractions activées, celles déclarées et leurs dépendances implicites :

fractions-actives-thorntail

Et le lancement se termine par :


INFO  [org.wildfly.swarm] (main) THORN99999: Thorntail is Ready


Les sondes permettent de tester que tout va bien : http://localhost:8080/health.

test-sondes

Implémenter l’API avec JAX-RS

Il est désormais temps d’implémenter l’API. Comme je le ferais dans un contexte JEE, j’utilise JAX-RS. Ce travail est même simplifié puisqu’il est guidé par la définition précédente API de l’API précédente.

https://github.com/its4u/immo-tenants-management-thorntail/blob/master/src/main/java/com/its4u/immo/tenants/mgmt/rest/TenantResource.java

Note : on peut également inclure le fichier yml openAPI dans META-INF et ne pas annoter les méthodes…

Enfin vient le développement de la logique métier propre à chaque fonction et des considérations techniques de pagination, de persistance.

Tester l’implémentation de l’API

Une API étant un contrat, des tests unitaires assurant son bon fonctionnement et la non-régression sont les bienvenus.

Ici, je propose d’utiliser une combinaison de JUnit, Arquillian et RestAssured pour obtenir un environnement de tests unitaires le plus représentatif possible d’un déploiement. Arquillian simule le packaging du microservices, JUnit exécute les tests dans ce contexte simulé et RestAssured s’attache à valider l’API.

test-implementation-api

Exécuter le microservice et tester l’API avec Swagger UI

Afin de tester l’API, je vous propose d’utiliser l’application web Swagger. Il suffit de l’ajouter au projet sous la forme d’une dépendance que j’ai choisi d’isoler dans un profil Maven spécifique afin de ne pas inclure cette partie dans le binaire de production.


<dependency>

<groupId>io.thorntail</groupId>

<artifactId>swagger-webapp</artifactId>

</dependency>


Le projet peut être lancé de deux façons :


mvn clean package -Pswagger

java -jar ./target/immo-tenants-management-thorntail.jar


Ou :


mvn thorntail:run


L’application Swagger UI est disponible sur le path swagger-ui, tandis que la définition de notre API est exposée sur le path openapi. Ainsi l’on peut charger directement Swagger UI avec la définition de notre API avec le lien suivant : http://localhost:8080/swagger-ui

Swagger UI -microservice

En cliquant sur chaque chemin (ex : POST /applications-forms), on affiche une description de ses paramètres d’entrée et sortie. Une option « Try it out » permet de tester directement l’API depuis cette interface :

En cliquant sur « Execute » on voit apparaître le résultat :

microservices-thorntail-openapi-3

Conclusion : Thorntail facilite la création de microservices

Pour conclure, l’utilisation de Thorntail, en plus de procurer des facilités de travail pour les développeurs JEE, fournit un grand nombre de fractions (openapi, health, ou encore opentracing et fault-tolerance non exploités ici) permettant le développement d’un micro-service production-ready de manière très productive. La place centrale d’OpenAPI à la fois lors des spécifications et des tests, couplée à des tests unitaires, permet de vérifier rapidement la conformité et la robustesse des développements. Enfin, le packaging sous forme d’un .jar autonome permet de conteneuriser très facilement les applications, offrant alors des possibilités de déploiement très variées, d’un simple conteneur Docker à des pods Openshift auto-scalables.