Quarkus: mises Ă  niveau d'applications utilisant l'exemple helloworld de JBoss EAP Quickstart

Bonjour Ă  tous sur ce blog, et avec vous le quatriĂšme post de la sĂ©rie Quarkus! (Soit dit en passant, inscrivez-vous et accĂ©dez Ă  notre webinaire « Ceci est Quarkus - Framework Java natif Kubernetes », qui se tiendra le 27 mai. Nous montrerons comment recommencer Ă  zĂ©ro ou transfĂ©rer des solutions prĂȘtes Ă  l'emploi) Le



post précédent était sur la façon dont Quarkus combine MicroProfile et Spring. Rappelons que Quarkus est positionné comme «Java subatomique ultrarapide», il s'agit de «pile Java orientée Kubernetes, affinée par GraalVM et OpenJDK HotSpot et compilée à partir des meilleures bibliothÚques et normes». Aujourd'hui, nous montrons comment mettre à niveau des applications Java existantes en utilisant les capacités de Quarkus à l'aide de l'application helloworld du référentiel de démarrage rapide Red Hat JBoss Enterprise Application Platform (JBoss EAP)en utilisant les technologies CDI et Servlet 3 prises en charge par Quarkus.

Il est important de noter ici que Quarkus et JBoss EAP se concentrent sur l'utilisation d'outils conçus selon les normes maximales. Vous n'avez pas d'application exĂ©cutĂ©e sur JBoss EAP? Ce n'est pas un problĂšme, il peut ĂȘtre facilement migrĂ© du serveur d'applications actuel vers JBoss EAP Ă  l'aide du Red Hat Application Migration Toolkit . AprĂšs cela, la version finale et fonctionnelle du code mis Ă  niveau sera disponible dans le rĂ©fĂ©rentiel github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus , dans le module helloworld .

Ce message a été écrit à l'aide de didacticiels Quarkus , principalement pour créer votre premiÚre application et créer un exécutable natif .

Nous obtenons un code


Tout d'abord, créez un clone local du référentiel de démarrage rapide JBoss EAP :

$ git clone https://github.com/jboss-developer/jboss-eap-quickstarts.git
Cloning into 'jboss-eap-quickstarts'...
remote: Enumerating objects: 148133, done.
remote: Total 148133 (delta 0), reused 0 (delta 0), pack-reused 148133
Receiving objects: 100% (148133/148133), 59.90 MiB | 7.62 MiB/s, done.
Resolving deltas: 100% (66476/66476), done.
$ cd jboss-eap-quickstarts/helloworld/

DĂ©couvrez comment fonctionne le helloworld d'origine


En fait, l'essence de cette application est claire du nom, mais nous allons mettre à jour son code strictement scientifique. Par conséquent, pour commencer, regardez cette application dans sa forme originale.

DĂ©veloppez helloworld

1. Ouvrez le terminal et accédez à la racine du dossier JBoss EAP (vous pouvez le télécharger ici ), c'est-à-dire dans le dossier EAP_HOME.

2. Démarrez le serveur JBoss EAP avec le profil par défaut:

$ EAP_HOME/bin/standalone.sh

Remarque: sous Windows, le script EAP_HOME \ bin \ standalone.bat est utilisé pour s'exécuter.

AprÚs quelques secondes, les éléments suivants devraient apparaßtre dans le journal:

[org.jboss.as] (Controller Boot Thread) WFLYSRV0025: JBoss EAP 7.2.0.GA (WildFly Core 6.0.11.Final-redhat-00001) started in 3315ms - Started 306 of 527 services (321 services are lazy, passive or on-demand)

3. Ouvrez le navigateur 127.0.0.1 : 8080 et voyez ceci:



Figure. 1. Page d'accueil de JBoss EAP.

4. Suivez les instructions du manuel Build and Deploy the Quickstart : deploy helloworld and execute (from the project root folder) the following command:

$ mvn clean install wildfly:deploy

AprÚs l'exécution réussie de cette commande dans le journal, nous verrons quelque chose comme ceci:

[INFO] ------------------------------------------------------------------------ 
[INFO] BUILD SUCCESS 
[INFO] ------------------------------------------------------------------------ 
[INFO] Total time: 8.224 s

Ainsi, le premier déploiement de l'application helloworld sur JBoss EAP a pris un peu plus de 8 secondes.

Nous testons helloworld

Agissant strictement selon le guide Accéder à l'application , ouvrez 127.0.0.1 : 8080 / helloworld dans un navigateur et voyez ceci:



Figure. 2. Bonjour tout le monde d'origine de JBoss EAP.

Marque change

Modifier le paramÚtre d'entrée createHelloMessage (String name) du monde à Marco:

writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");

Encore une fois, exécutez la commande suivante:

$ mvn clean install wildfly:deploy

Ensuite, nous actualisons la page dans le navigateur et voyons que le texte a changé:



Figure. 3. Bonjour Marco chez JBoss EAP.

Nous annulons le déploiement de helloworld et quittons JBoss EAP.

Ceci est facultatif, mais si vous souhaitez annuler le déploiement, vous pouvez le faire avec la commande suivante:

$ mvn clean install wildfly:undeploy

Pour arrĂȘter l'instance JBoss EAP, appuyez simplement sur Ctrl + C dans la fenĂȘtre du terminal.

Mise Ă  niveau de helloworld


Maintenant, mettons Ă  niveau l'application helloworld d'origine.

Créer une nouvelle branche

Créez une nouvelle branche de travail une fois le projet de démarrage rapide terminé:

$ git checkout -b quarkus 7.2.0.GA

Modification du fichier pom.xml

Nous allons commencer à modifier l'application à partir du fichier pom.xml. Pour que Quarkus puisse y insérer des blocs XML, exécutez la commande suivante dans le dossier helloworld:

$ mvn io.quarkus:quarkus-maven-plugin:0.23.2:create

Lors de la rédaction de cet article, la version 0.23.2 a été utilisée. Quarkus a souvent de nouvelles versions; vous pouvez découvrir quelle version est la plus récente sur github.com/quarkusio/quarkus/releases/latest .

La commande ci-dessus insérera les éléments suivants dans pom.xml:

  • La propriĂ©tĂ© <quarkus.version> qui spĂ©cifie la version de Quarkus Ă  utiliser.
  • Le bloc <dependencyManagement> pour importer la nomenclature Quarkus (nomenclature) afin de ne pas ajouter de version pour chaque dĂ©pendance Quarkus.
  • Le plugin quarkus-maven-plugin, qui est responsable de l'empaquetage de l'application et du mode de dĂ©veloppement.
  • Un profil natif pour crĂ©er des exĂ©cutables d'application.

De plus, nous apportons manuellement les modifications suivantes Ă  pom.xml:

  1. <groupId> <parent> <artifactId>. <parent>, <groupId>.
  2. <parent>, Quarkus pom JBoss.
  3. <version> <artifactId>. .
  4. <packaging>, WAR, JAR.
  5. :
    1. javax.enterprise:cdi-api io.quarkus:quarkus-arc, <scope>provided</scope>, ( ) Quarkus- injection CDI.
    2. Nous changeons la dépendance org.jboss.spec.javax.servlet: jboss-servlet-api_4.0_spec en io.quarkus: quarkus-Undertow, en supprimant <scope> fourni </scope>, car (selon les quais) cette extension Quarkus fournit un support de servlet 's.
    3. Nous supprimons la dépendance org.jboss.spec.javax.annotation: jboss-annotations-api_1.3_spec, car ils sont fournis avec les dépendances que nous venons de modifier.


La version du fichier pom.xml avec toutes les modifications se trouve sur github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml .

Veuillez noter que la commande mvn io.quarkus: quarkus-maven-plugin: 0.23.2: create ci-dessus modifie non seulement le fichier pom.xml, mais ajoute Ă©galement un certain nombre de composants au projet, Ă  savoir les fichiers et dossiers suivants:

  • mvnw and mvnw.cmd .mvn: Maven Wrapper Maven Maven .
  • docker ( src/main/): Dockerfile native jvm ( .dockerignore).
  • resources ( src/main/): application.properties Quarkus index.html ( . Run the modernized helloworld ).

Nous commençons helloworld
Pour tester l'application, nous utilisons quarkus: dev, qui démarre Quarkus en mode développement (pour plus de détails, voir cette section dans le manuel du mode développement ).

Remarque: cette étape devrait entraßner une erreur, car nous n'avons pas encore effectué toutes les modifications nécessaires.

Exécutez maintenant la commande pour vérifier son fonctionnement:

$ ./mvnw compile quarkus:dev
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< org.jboss.eap.quickstarts:helloworld >----------------
[INFO] Building Quickstart: helloworld quarkus
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ helloworld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ helloworld ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- quarkus-maven-plugin:0.23.2:dev (default-cli) @ helloworld ---
Listening for transport dt_socket at address: 5005
INFO  [io.qua.dep.QuarkusAugmentor] Beginning quarkus augmentation
INFO  [org.jbo.threads] JBoss Threads version 3.0.0.Final
ERROR [io.qua.dev.DevModeMain] Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
	[error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.jboss.as.quickstarts.helloworld.HelloService and qualifiers [@Default]
	- java member: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService
	- declared on CLASS bean [types=[javax.servlet.ServletConfig, java.io.Serializable, org.jboss.as.quickstarts.helloworld.HelloWorldServlet, javax.servlet.GenericServlet, javax.servlet.Servlet, java.lang.Object, javax.servlet.http.HttpServlet], qualifiers=[@Default, @Any], target=org.jboss.as.quickstarts.helloworld.HelloWorldServlet]
	at io.quarkus.arc.processor.BeanDeployment.processErrors(BeanDeployment.java:841)
	at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:214)
	at io.quarkus.arc.processor.BeanProcessor.initialize(BeanProcessor.java:106)
	at io.quarkus.arc.deployment.ArcProcessor.validate(ArcProcessor.java:249)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at io.quarkus.deployment.ExtensionLoader$1.execute(ExtensionLoader.java:780)
	at io.quarkus.builder.BuildContext.run(BuildContext.java:415)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1535)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1426)
	at java.lang.Thread.run(Thread.java:748)
	at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.jboss.as.quickstarts.helloworld.HelloService and qualifiers [@Default]
	- java member: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService
	- declared on CLASS bean [types=[javax.servlet.ServletConfig, java.io.Serializable, org.jboss.as.quickstarts.helloworld.HelloWorldServlet, javax.servlet.GenericServlet, javax.servlet.Servlet, java.lang.Object, javax.servlet.http.HttpServlet], qualifiers=[@Default, @Any], target=org.jboss.as.quickstarts.helloworld.HelloWorldServlet]
	at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:428)
	at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:371)
	at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:206)
	... 14 more

Donc ça ne marche pas ... Et pourquoi?

L'exception UnsatisfiedResolutionException pointe vers la classe HelloService, qui est membre de la classe HelloWorldServlet (membre java: org.jboss.as.quickstarts.helloworld.HelloWorldServlet # helloService). Le problĂšme est que HelloWorldServlet a besoin d'une instance injectĂ©e de HelloService, mais elle est introuvable (bien que ces deux classes soient dans le mĂȘme package).

Il est temps de revenir à la documentation et de lire le fonctionnement de QuarkusInjecteret donc Contexts and Dependency Injection (CDI). Par conséquent, nous ouvrons le guide Contexts and Dependency Injection et lisons dans la section Bean Discovery : «Une classe de bean qui n'a pas d'annotation définissant le bean n'est pas recherchée.»

Nous regardons la classe HelloService - elle n'a vraiment pas une telle annotation. Par consĂ©quent, il doit ĂȘtre ajoutĂ© pour que Quarkus puisse rechercher et trouver un bean. Et comme il s'agit d'un objet sans Ă©tat, nous pouvons bien ajouter l'annotation @ApplicationScoped comme suit:

@ApplicationScoped
public class HelloService {

Remarque: ici, l'environnement de dĂ©veloppement peut vous demander d'ajouter le package requis (voir la ligne ci-dessous), et cela devra ĂȘtre fait manuellement, comme ceci:

import javax.enterprise.context.ApplicationScoped;

En cas de doute sur l'étendue à utiliser lorsque le bean source n'est pas défini du tout, consultez la documentation JSR 365: Contexts and Dependency Injection for Java 2.0 - Default scope .

Maintenant, nous essayons de démarrer l'application avec la commande ./mvnw compile quarkus: dev:

$ ./mvnw compile quarkus:dev
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< org.jboss.eap.quickstarts:helloworld >----------------
[INFO] Building Quickstart: helloworld quarkus
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ helloworld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ helloworld ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /home/mrizzi/git/forked/jboss-eap-quickstarts/helloworld/target/classes
[INFO]
[INFO] --- quarkus-maven-plugin:0.23.2:dev (default-cli) @ helloworld ---
Listening for transport dt_socket at address: 5005
INFO  [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
INFO  [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 576ms
INFO  [io.quarkus] (main) Quarkus 0.23.2 started in 1.083s. Listening on: http://0.0.0.0:8080
INFO  [io.quarkus] (main) Profile dev activated. Live Coding activated.
INFO  [io.quarkus] (main) Installed features: [cdi]

Maintenant, tout se passe sans erreur.

Nous lançons le helloworld mis à niveau
Comme il est écrit dans le journal, ouvrez dans le navigateur 0.0.0.0 : 8080 (la page de démarrage par défaut de Quarkus) et voyez ceci:



Figure. 4. Page de démarrage de Quarkus dev.

L'annotation WebServlet pour cette application a la définition de contexte suivante:

@WebServlet("/HelloWorld")
public class HelloWorldServlet extends HttpServlet {

Par conséquent, nous allons à 0.0.0.0 : 8080 / HelloWorld dans le navigateur et voyons ce qui suit:



Figure. 5: La page de développement Quarkus pour l'application Hello World.

Eh bien, tout fonctionne.

Et maintenant, nous apportons des modifications au code. Notez que la commande ./mvnw compile quarkus: dev fonctionne toujours et nous n'allons pas l'arrĂȘter. Essayons maintenant d'appliquer les mĂȘmes modifications - triviales - au code lui-mĂȘme et voyons comment Quarkus facilite la vie du dĂ©veloppeur:

writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");

Enregistrez le fichier, puis actualisez la page Web pour voir Bonjour Marco, comme indiqué dans la capture d'écran ci-dessous:



Figure. 6. Page Bonjour Marco dans Quarkus dev.

VĂ©rifiez maintenant la sortie dans le terminal:

INFO  [io.qua.dev] (vert.x-worker-thread-3) Changed source files detected, recompiling [/home/mrizzi/git/forked/jboss-eap-quickstarts/helloworld/src/main/java/org/jboss/as/quickstarts/helloworld/HelloWorldServlet.java]
INFO  [io.quarkus] (vert.x-worker-thread-3) Quarkus stopped in 0.003s
INFO  [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) Beginning quarkus augmentation
INFO  [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) Quarkus augmentation completed in 232ms
INFO  [io.quarkus] (vert.x-worker-thread-3) Quarkus 0.23.2 started in 0.257s. Listening on: http://0.0.0.0:8080
INFO  [io.quarkus] (vert.x-worker-thread-3) Profile dev activated. Live Coding activated.
INFO  [io.quarkus] (vert.x-worker-thread-3) Installed features: [cdi]
INFO  [io.qua.dev] (vert.x-worker-thread-3) Hot replace total time: 0.371s

L'actualisation de la page a déclenché la détection de changements dans le code source et Quarkus a automatiquement exécuté la procédure «stop start». Et tout cela a été achevé en seulement 0,371 seconde (le voici, ce trÚs «Java subatomique ultrarapide»).

Nous construisons helloworld dans un package JAR
Maintenant que le code fonctionne comme il se doit, nous l'emballons avec la commande suivante:

$ ./mvnw clean package

Cette commande crée deux fichiers JAR dans le dossier / target: le fichier helloworld-.jar, qui est un artefact standard assemblé par l'équipe Maven avec les classes de projet et les ressources. Et le fichier helloworld est runner.jar, qui est un JAR exécutable.

Notez qu'il ne s'agit pas d'un uber-jar, car toutes les dépendances sont simplement copiées dans le dossier / target / lib (et non empaquetées dans un fichier JAR). Par conséquent, pour exécuter ce fichier JAR à partir d'un autre dossier ou sur un hÎte différent, vous devez y copier le fichier JAR et le dossier / lib, étant donné que l'élément Class-Path du fichier MANIFEST.MF du package JAR contient une liste explicite des fichiers JAR de dossiers lib.
Pour savoir comment créer des applications uber-jar, reportez-vous au didacticiel de création Uber-Jar .

Lancez helloworld, emballé dans un JAR

Vous pouvez maintenant exécuter notre JAR en utilisant la commande java standard:

$ java -jar ./target/helloworld-<version>-runner.jar
INFO  [io.quarkus] (main) Quarkus 0.23.2 started in 0.673s. Listening on: http://0.0.0.0:8080
INFO  [io.quarkus] (main) Profile prod activated.
INFO  [io.quarkus] (main) Installed features: [cdi]

AprÚs tout cela, allez dans le navigateur sur 0.0.0.0 : 8080 et vérifiez que tout fonctionne comme il se doit.

Mettre helloworld dans un exécutable natif

Donc, notre helloworld fonctionne comme une application Java autonome utilisant les dépendances Quarkus. Mais vous pouvez aller plus loin et le transformer en un fichier exécutable natif.

Installation de GraalVM
Tout d'abord, vous devez installer les outils nécessaires pour cela:

1. Téléchargez GraalVM 19.2.0.1 depuis github.com/oracle/graal/releases/tag/vm-19.2.0.1 .

2. Développez l'archive téléchargée:

$ tar xvzf graalvm-ce-linux-amd64-19.2.0.1.tar.gz

3. Accédez au dossier untar.

4. Exécutez la commande ci-dessous pour télécharger et ajouter une image native:

$ ./bin/gu install native-image

5. Nous enregistrons le dossier créé à l'étape 2 dans la variable d'environnement GRAALVM_HOME:

$ export GRAALVM_HOME={untar-folder}/graalvm-ce-19.2.0.1)

Pour plus d'informations et des instructions d'installation sur d'autres systÚmes d'exploitation, voir Création d'un exécutable natif - Prérequis .

Construisez helloworld en un exécutable natif.
Lisez le manuel Construire un exĂ©cutable natif - Produire un exĂ©cutable natif : «CrĂ©ez maintenant un exĂ©cutable natif pour notre application afin de rĂ©duire le temps de dĂ©marrage et la taille du disque. Le fichier exĂ©cutable aura tout le nĂ©cessaire pour exĂ©cuter l'application, y compris la machine JVM (ou plutĂŽt, sa version tronquĂ©e, contenant uniquement ce qui est nĂ©cessaire pour exĂ©cuter l'application) et notre application elle-mĂȘme. »

Pour créer un exécutable natif, vous devez activer le profil natif Maven:

$ ./mvnw package -Pnative

Notre assemblage a pris une minute et 10 secondes, et le fichier final helloworld - runner f a été créé dans le dossier / target.

Nous démarrons le fichier exécutable natif helloworld

Dans l'étape précédente, nous avons obtenu le fichier exécutable / target / helloworld - runner. Maintenant, lancez-le:

$ ./target/helloworld-<version>-runner
INFO  [io.quarkus] (main) Quarkus 0.23.2 started in 0.006s. Listening on: http://0.0.0.0:8080
INFO  [io.quarkus] (main) Profile prod activated.
INFO  [io.quarkus] (main) Installed features: [cdi]

Encore une fois, ouvrez le navigateur 0.0.0.0 : 8080 et vérifiez que tout fonctionne comme il se doit.

À suivre!

Nous pensons que la mĂ©thode de modernisation des applications Java utilisant les capacitĂ©s de Quarkus examinĂ©e dans cet article (bien qu'avec l'exemple le plus simple) devrait ĂȘtre activement appliquĂ©e dans la vie rĂ©elle. Dans ce cas, vous ĂȘtes susceptible de rencontrer un certain nombre de problĂšmes, dont la solution sera examinĂ©e en partie dans le prochain article, qui se concentrera sur la façon de mesurer la consommation de mĂ©moire afin d'Ă©valuer les amĂ©liorations de performances, une partie importante de l'ensemble du processus de modernisation des applications.

All Articles