Quarkus: Modernizace aplikací s využitím Helloworld jako příkladu z JBoss EAP Quickstart

Ahoj všichni na tomto blogu, tady je čtvrtý příspěvek v sérii Quarkus!

Quarkus: Modernizace aplikací s využitím Helloworld jako příkladu z JBoss EAP Quickstart

Předchozí příspěvek bylo o tom, jak Quarkus kombinuje MicroProfile a Spring. Připomeňme si to kvarkus je umístěn jako „ultrarychlá subatomická Java“, neboli „Java stack orientovaný na Kubernetes, přizpůsobený pro GraalVM a OpenJDK HotSpot a sestavený z nejlepších knihoven a standardů“. Dnes si na příkladu ukážeme, jak modernizovat stávající Java aplikace pomocí schopností Quarkusu aplikace helloworld z úložiště Red Hat JBoss Enterprise Application Platform (JBoss EAP) Quickstart, který využívá technologie CDI a Servlet 3 podporované Quarkusem.

Zde je důležité poznamenat, že Quarkus i JBoss EAP kladou důraz na používání nástrojů, které jsou co nejvíce založené na standardech. Nemáte na JBoss EAP spuštěnou aplikaci? Žádný problém, lze jej snadno migrovat z vašeho aktuálního aplikačního serveru na JBoss EAP pomocí Red Hat Application Migration Toolkit. Poté bude konečná a pracovní verze modernizovaného kódu k dispozici v úložišti github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus, v modulu Ahoj světe.

Při psaní tohoto příspěvku jsme použili Quarkus tutoriály, většinou Vytvoření vaší první aplikace a budova a Nativní spustitelný soubor.

Pojďme získat kód

Nejprve si vytvoříme lokální klon úložiště Rychlé starty 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/

Pojďme se podívat, jak funguje původní helloworld

Ve skutečnosti je podstata této aplikace zřejmá z názvu, ale její kód zmodernizujeme přísně vědecky. Nejprve se proto podívejme na tuto aplikaci v její původní podobě.

Nasazení helloworldu

1. Otevřete terminál a přejděte do kořenového adresáře složky JBoss EAP (můžete si ji stáhnout zde), tedy do složky EAP_HOME.

2. Spusťte server JBoss EAP s výchozím profilem:

$ EAP_HOME/bin/standalone.sh

Poznámka: Ve Windows se ke spuštění používá skript EAP_HOMEbinstandalone.bat.

Po několika sekundách by se v protokolu mělo objevit něco takového:

[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. Otevřete v prohlížeči 127.0.0.1:8080 a vidíme toto:

Quarkus: Modernizace aplikací s využitím Helloworld jako příkladu z JBoss EAP Quickstart

Rýže. 1. Domovská stránka JBoss EAP.

4. Postupujte podle pokynů v návodu Sestavte a nasaďte Rychlý start: rozbalte helloworld a spusťte (z kořenové složky projektu) následující příkaz:

$ mvn clean install wildfly:deploy

Po úspěšném provedení tohoto příkazu uvidíme v protokolu něco jako následující:

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

První nasazení aplikace helloworld na JBoss EAP tedy trvalo něco málo přes 8 sekund.

Testování helloworld

Jednat přísně podle pokynů Přístup k aplikaci, otevřete v prohlížeči 127.0.0.1:8080/helloworld a vidíme toto:

Quarkus: Modernizace aplikací s využitím Helloworld jako příkladu z JBoss EAP Quickstart

Rýže. 2. Originální Hello World od JBoss EAP.

Provádění změn

Změňte vstupní parametr createHelloMessage (název řetězce) z World na Marco:

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

Spusťte znovu následující příkaz:

$ mvn clean install wildfly:deploy

Poté obnovíme stránku v prohlížeči a uvidíme, že se text změnil:

Quarkus: Modernizace aplikací s využitím Helloworld jako příkladu z JBoss EAP Quickstart

Rýže. 3. Ahoj Marco v JBoss EAP.

Vraťte zpět nasazení helloworld a vypněte JBoss EAP

Toto je volitelné, ale pokud chcete nasazení zrušit, můžete tak učinit pomocí následujícího příkazu:

$ mvn clean install wildfly:undeploy

Pro vypnutí instance JBoss EAP jednoduše stiskněte Ctrl+C v okně terminálu.

Aktualizace helloworld

Nyní zmodernizujme původní aplikaci helloworld.

Vytvořte novou větev

Po dokončení projektu rychlého startu vytvoříme novou pracovní větev:

$ git checkout -b quarkus 7.2.0.GA

Změna souboru pom.xml

Aplikaci začneme měnit ze souboru pom.xml. Chcete-li, aby do něj Quarkus mohl vkládat bloky XML, spusťte ve složce helloworld následující příkaz:

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

Při psaní tohoto článku byla použita verze 0.23.2. Quarkus často vydává nové verze, na webu zjistíte, která verze je nejnovější github.com/quarkusio/quarkus/releases/latest.

Výše uvedený příkaz vloží do pom.xml následující prvky:

  • Vlastnictví , který určuje verzi Quarkusu, která se má použít.
  • Blok importovat kusovník Quarkus (kusovník), aby se nepřidávala verze pro každou závislost Quarkus.
  • quarkus-maven-plugin je zodpovědný za zabalení aplikace a poskytování vývojového režimu.
  • Nativní profil pro vytváření spustitelných souborů aplikace.

Kromě toho ručně provádíme následující změny v pom.xml:

  1. Vytažení štítku z bloku a umístěte jej nad značku . Protože v dalším kroku blok odstraníme , pak musíte uložit .
  2. Odstranění bloku protože při spuštění s Quarkusem tato aplikace již nebude potřebovat nadřazený pom od JBoss.
  3. Přidejte značku a umístěte jej pod značku . Můžete zadat požadované číslo verze.
  4. Odstranění štítku , protože tato aplikace již není VÁLKA, ale běžný JAR.
  5. Upravujeme následující závislosti:
    1. Změňte závislost javax.enterprise:cdi-api na io.quarkus:quarkus-arc a odstraňte pokud , protože (podle dokumentů) toto rozšíření Quarkus poskytuje injekci závislostí CDI.
    2. Změňte závislost org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec na io.quarkus:quarkus-undertow a odstraňte pokud , protože (podle dokumentů) toto rozšíření Quarkus poskytuje podporu pro servlety.
    3. Odstraňujeme závislost org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec, protože přichází se závislostmi, které jsme právě změnili.

Verze souboru pom.xml se všemi změnami se nachází na github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml.

Všimněte si, že výše uvedený příkaz mvn io.quarkus:quarkus-maven-plugin:0.23.2:create nejen změní soubor pom.xml, ale také přidá do projektu řadu komponent, konkrétně následující soubory a složky:

  • Soubory mvnw a mvnw.cmd a složka .mvn: Maven Wrapper vám umožňují spouštět projekty Maven dané verze Maven bez instalace této verze.
  • Složka Docker (v adresáři src/main/): Obsahuje ukázkové soubory Dockerfiles pro nativní režimy a režimy jvm (spolu se souborem .dockerignore).
  • Složka Resources (v adresáři src/main/): Obsahuje prázdný soubor application.properties a ukázkovou úvodní stránku Quarkus index.html (další podrobnosti viz Spuštění modernizovaného helloworld).

Spusťte helloworld
K otestování aplikace používáme quarkus:dev, který spouští Quarkus ve vývojovém režimu (více podrobností naleznete v této části návodu Režim vývoje).

Poznámka: Tento krok pravděpodobně povede k chybě, protože jsme ještě neprovedli všechny potřebné změny.

Nyní spusťte příkaz, abyste viděli, jak to funguje:

$ ./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

Takže to nejde... Proč?

Výjimka UnsatisfiedResolutionException ukazuje na třídu HelloService, která je členem třídy HelloWorldServlet (člen Java: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). Problém je v tom, že HelloWorldServlet potřebuje vloženou instanci HelloService a nelze ji najít (i když jsou obě tyto třídy ve stejném balíčku).

Je čas se vrátit dokumentace a přečtěte si, jak to funguje v Quarkusu Vstřik, a proto Kontexty a vstřikování závislostí (CDI). Otevřete proto průvodce Contexts and Dependency Injection a v sekci Bean Discovery čteme: „Třída fazole, která nemá anotaci definující fazole, není prohledávána.“

Podívejme se na třídu HelloService – takovou anotaci opravdu nemá. Proto se musí přidat, aby Quarkus mohl fazoli hledat a najít. A protože se jedná o bezstavový objekt, můžeme snadno přidat anotaci @ApplicationScoped takto:

@ApplicationScoped
public class HelloService {

Poznámka: zde vás může vývojové prostředí požádat o přidání požadovaného balíčku (viz řádek níže) a budete to muset udělat ručně, takto:

import javax.enterprise.context.ApplicationScoped;

Pokud máte pochybnosti o tom, jaký rozsah by měl být použit v případě, že pro zdrojový objekt není určen vůbec, přečtěte si dokumentaci JSR 365: Contexts and Dependency Injection for Java 2.0 – Výchozí rozsah.

Nyní se znovu pokusíme spustit aplikaci příkazem ./mvnw kompilovat 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]

Nyní vše probíhá bez chyb.

Spuštění modernizovaného helloworldu
Jak je napsáno v protokolu, otevřete jej v prohlížeči 0.0.0.0:8080 (výchozí úvodní stránka Quarkusu) a vidíme toto:

Quarkus: Modernizace aplikací s využitím Helloworld jako příkladu z JBoss EAP Quickstart

Rýže. 4. Úvodní stránka Quarkus dev.

Anotace WebServlet pro tuto aplikaci obsahuje následující kontextovou definici:

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

Proto přejdeme v prohlížeči na 0.0.0.0:8080/HelloWorld a vidíme následující:

Quarkus: Modernizace aplikací s využitím Helloworld jako příkladu z JBoss EAP Quickstart

Rýže. 5: Vývojová stránka Quarkus pro aplikaci Hello World.

No, všechno funguje.

Nyní provedeme změny v kódu. Všimněte si, že příkaz ./mvnw kompilace quarkus:dev stále běží a nemáme v úmyslu jej zastavit. Nyní se pokusíme aplikovat stejné - nejtriviálnější - změny na samotný kód a uvidíme, jak Quarkus usnadňuje život vývojářům:

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

Uložte soubor a poté obnovte webovou stránku, abyste viděli Hello Marco, jak je znázorněno na obrázku níže:

Quarkus: Modernizace aplikací s využitím Helloworld jako příkladu z JBoss EAP Quickstart

Rýže. 6. Stránka Hello Marco v Quarkus dev.

Nyní zkontrolujeme výstup v terminálu:

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

Obnovení stránky spustilo detekci změn ve zdrojovém kódu a Quarkus automaticky provedl proceduru stop-start. A to vše bylo dokončeno za pouhých 0.371 sekundy (tady to je ta „ultrarychlá subatomární Java“).

Sestavte helloworld do balíčku JAR
Nyní, když kód funguje, jak má, zabalíme jej pomocí následujícího příkazu:

$ ./mvnw clean package

Tento příkaz vytvoří dva soubory JAR ve složce /target: soubor helloworld-.jar, což je standardní artefakt sestavený týmem Maven spolu s třídami a prostředky projektu. A soubor helloworld-runner.jar, což je spustitelný JAR.

Upozorňujeme, že toto není uber-jar, protože všechny závislosti se jednoduše zkopírují do složky /target/lib (nezabaleny do souboru JAR). Proto, abyste mohli spustit tento JAR z jiné složky nebo na jiném hostiteli, musíte zkopírovat jak samotný soubor JAR, tak složku /lib tam, protože prvek Class-Path v souboru MANIFEST.MF v balíčku JAR obsahuje explicitní výpis JAR ze složek lib
Chcete-li se dozvědět, jak vytvářet aplikace uber-jar, přečtěte si prosím tutoriál Vytvoření Uber-Jar.

Spusťte helloworld zabalený v JAR

Nyní můžeme spustit náš JAR pomocí standardního příkazu java:

$ 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]

Po tom všem přejděte do svého prohlížeče na adrese 0.0.0.0:8080 a zkontrolujte, zda vše funguje jak má.

Kompilace helloworld do nativního spustitelného souboru

Náš helloworld tedy běží jako samostatná Java aplikace využívající závislostí Quarkus. Ale můžete jít dále a přeměnit jej na nativní spustitelný soubor.

Instalace GraalVM
Nejprve musíte nainstalovat potřebné nástroje:

1. Stáhněte si GraalVM 19.2.0.1 z github.com/oracle/graal/releases/tag/vm-19.2.0.1.

2. Rozbalte stažený archiv:

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

3. Přejděte do složky untar.

4. Spuštěním příkazu níže stáhněte a přidejte nativní obrázek:

$ ./bin/gu install native-image

5. Zaregistrujte složku vytvořenou v kroku 2 do proměnné prostředí GRAALVM_HOME:

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

Další informace a pokyny k instalaci na jiných operačních systémech naleznete v příručce Vytvoření nativního spustitelného souboru – předpoklady.

Vytvoření helloworld do nativního spustitelného souboru
Čtení manuálu Vytvoření nativního spustitelného souboru – vytvoření nativního spustitelného souboru: „Nyní vytvoříme nativní spustitelný soubor pro naši aplikaci, abychom zkrátili dobu spouštění a velikost disku. Spustitelný soubor bude mít vše potřebné ke spuštění aplikace, včetně JVM (nebo spíše jeho zkrácené verze obsahující pouze to, co je potřeba ke spuštění aplikace) a naší aplikace samotné.“

Chcete-li vytvořit nativní spustitelný soubor, musíte povolit nativní profil Maven:

$ ./mvnw package -Pnative

Naše sestavení trvalo jednu minutu a 10 sekund a ve složce /target byl vytvořen konečný soubor helloworld-runner f.

Spusťte nativní spustitelný soubor helloworld

V předchozím kroku jsme obdrželi spustitelný soubor /target/helloworld—runner. Teď to spustíme:

$ ./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]

Znovu jej otevřete v prohlížeči 0.0.0.0:8080 a zkontrolujte, zda vše funguje jak má.

Pokračujte!

Domníváme se, že metoda modernizace Java aplikací pomocí schopností Quarkus diskutovaná v tomto příspěvku (i když na jednoduchém příkladu) by měla být aktivně používána v reálném životě. Pravděpodobně při tom narazíte na řadu problémů, kterým se částečně budeme věnovat v dalším příspěvku, kde si povíme, jak měřit spotřebu paměti pro posouzení zlepšení výkonu, což je důležitá součást celého procesu modernizace aplikace.

Zdroj: www.habr.com

Přidat komentář