Il est venu le temps pour un nouvel article. J’ai eu l’occasion de m’intéresser récemment au framework Quarkus qui est une implémentation J2EE + Microprofile orienté micro service.

Ce framework qui à la vocation d’être hyper rapide (subatomic supersonic java …) permet la création d’extensions en déplaçant au maximum la logique dans le build, ce qui permet un boot ultra rapide. Pour commencer à écrire des extensions, la documentation originale est très bien faite : https://quarkus.io/guides/writing-extensions

La partie peu documentée qui m’a intéressée est la suivante : comment créer des Bean virtuel (interface injectable sans implémentation explicite) à l’aide d’une extension. ce type de bean est connu sous le nom de synthetic bean dans la littérature.

Premièrement, notons que Quarkus n’utilise pas Weld l’implémentation bien connue de CDI, mais Arc, sa propre implémentation (orientée build time, donc).

Je vous propose d’étudier un plugin tout simple, permettant de faire du RPC au dessus de Map Hazelcast (Rcast): https://github.com/rmanibus/rcast-project

le but est de pouvoir injecter les interfaces annotée @RegisterRcast sans fournir d’implémentation réelle. Sous le capot, nous fournirons simplement un proxy sur l’interface permettant de faire l’appel RPC.

Ainsi l’interface suivante :

Pourra être utilisée de la sorte :

Dans ce cas de figure il faudra bien sur qu’une implémentation existe sur l’application cible (« the app » ). Mais dans notre application, nous n’aurons besoin que de l’interface.

Nous utiliserons le qualifier @Rcast afin d’indiquer que nous souhaitons utiliser le service proxifié, cela permet d’indiquer clairement notre intension. Sur le service cible par exemple, cela évitera d’injecter le proxy lorsque l’on souhaite obtenir l’implémentation directement.

Je vous laisse lire la documentation de quarkus pour la création de la coquille du projet. une fois cela fait, vous devriez avoir deux modules dans votre projet « runtime » et « deployment ». Le module Deployment contiendra l’ensemble de notre logique qui sera exécutée lors du build.

Le BeanCreator

Nous allons d’abord définir la classe servant de modèle pour nos synthetic beans. Celle ci doit se trouver dans le module « deployment » de votre projet et implémenter l’interface BeanCreator :

Notons que je récupère ici un bean CDI (RcastProvider) en appelant le beanManager. pour cela, si je n’injecte nul part RcastProvider dans mon application, il faudra qu’il soit annoté par @Unremovable affin qu’Arc ne le supprime pas lors de la création du contexte.

Le Bean Processor

Nous avons besoin d’une classe Processor dans notre module « deployment ». Cette classe contiendra les étapes (@BuildStep) nécessaires à la construction de nos Beans virtuels.

D’abord, nous allons nous servir de l’index jandex afin de lister les interfaces annotées par @RegisterRcast.

Nous allons donc créer la méthode suivante dans notre class Processor:

Nous pouvons maintenant utiliser notre méthode et notre modèle au sein d’une BuildStep (méthode annotée au sein de la classe Processor, servant d’étape de construction. ces méthodes sont exécutées automatiquement par quarkus).

Vous pouvez maintenant dès à présent injecter l’interface que nous avons créé au début de ce projet en ajoutant l’extension en dépendance de votre projet.