Quarkus Extension Synthetic Build Item
Dans le précédent post sur le buildItem AdditionalBeanBuildItem, nous avons vu comment référencer un bean au gestionnaire de dépendance ARC.
Cela est très pratique, mais dans certains cas, nous voulons pouvoir que le gestionnaire injecte une instance spécifique d’un bean déjà configuré. L’AdditionalBeanBuildItem
ne prenant qu’une classe de bean
en paramètre, il ne peut pas être utilisé pour cela. C’est ici qu’intervient le SyntheticBeanBuildItem
Cas d’usage.
Imaginons que votre extension souhaite fournir une configuration sous forme d’un bean injectable pour aller communiquer avec une API tierce. Il va falloir dire à Quarkus quelle instance de bean injecter et avec quelles valeurs.
SyntheticBeanBuildItem
Le nom de ce buildItem n’est pas très parlant et j’ai mis pas mal de temps à comprendre à quoi il pouvait bien servir. En résumé, il s’agit d’un AdditionalBeanBuildItem
prenant une instance de classe au lieu d’une classe en paramètre. Cela le rend très puissant. Pour produire une instance de classe, il va tout d’abord falloir fournir cette instance sous la forme d’un Recorder
.
Recorder
Commençons par créer notre Bean de configuration d’API dans le module runtime
de notre extension :
|
|
Notre bean doit être “CDI compatible”. Pour cela, il doit comporter un constructeur par défaut ainsi que des accesseurs. Dans notre cas, nous utilisons un constructeur par défaut privé pour que la classe ne puisse pas être utilisée d’une manière non prévue. Le plugin maven quarkus vérifie la présence des Bean injectable lors de la phase de package. Sans ce constructeur par défaut le build de notre projet plante avec une erreur
Unsatisfied dependency
. Nous définissons notre bean en scope @ApplicationScoped
pour que la même instance soit toujours injectée.
Créons maintenant le recorder pour notre classe Config :
Lorsque qu’un recorder est déclaré, Quarkus va exécuter le recorder lors de la phase de build et enregistrer le bytecode produit par ce recorder. Lors de la phase de runtime, quarkus fournira se bytecode directement au lieu d’avoir à le recalculer dynamiquement. Cela permet d’accélérer grandement le temps de démarrage. Dans notre exemple, le recorder retourne un object RuntimeValue<Config>
contenant l’instance de notre configuration. Ce RuntimeValue
sera consommer par notre SyntheticBeanBuildItem.
BuildStep
|
|
Pour configurer notre syntheticBuildItem nous utilisons une méthode annotée avec @Record(ExecutionTime.RUNTIME_INIT)
. Ici, le ExecutionTime.STATIC_INIT
ne fonctionnera pas, car notre recorder ne sera pas encore disponible. Ensuite, nous récupérons notre URL d’API via un DevServicesResultBuildItem
dont nous parlerons dans un prochain article. Une fois l’url de l’API récupérée, nous construisons notre SyntheticBeanBuildItem
avec notre recorder. La méthode unremovable
s’assure que notre instance de bean ne sera pas supprimer par Quarkus lors de la compilation de notre extension même si ce bean n’est pas utilisé. Sans cela, notre bean ne sera pas accessible dans le module maven important notre extension. Comme nous avons utilisé @Record(ExecutionTime.RUNTIME_INIT)
, nous informons Quarkus que notre instance de bean sera disponible lors de la phase RuntimeInit
grâce à la méthode setRuntimeInit
. Enfin, nous passons l’instance de notre bean de config à la méthode runtimeValue
pour finir d’initialiser notre SyntheticBeanBuildItem
.
Si vous n’avez pas le contrôle sur la classe du bean produit, vous pouvez ajouter un qualifier manquant via la méthode .addQualifier(ApplicationScoped.class)
Injection du Bean
Dans un projet important notre extension :
Nous pouvons maintenant injecter notre Bean de configuration pour l’utiliser :
## Conclusion
Un SyntheticBeanBuildItem
est le pendant dynamique de l’AdditionalBeanBuildItem
. Il utilise un Recorder
pour enregistrer le bytecode produit par notre instance lors de la phase de Build de quarkus. Ce bytecode sera fournis tel quel lors de l’exécution de l’application afin d’accélérer son démarrage.