Quarkus: Posodobitev aplikacije z uporabo Helloworld kot primera iz JBoss EAP Quickstart

Pozdravljeni vsi na tem blogu, tukaj je četrta objava v seriji Quarkus!

Quarkus: Posodobitev aplikacije z uporabo Helloworld kot primera iz JBoss EAP Quickstart

Prejšnja objava govoril o tem, kako Quarkus združuje MicroProfile in Spring. Naj vas spomnimo, da quarkus je postavljen kot »ultra hitra subatomska Java«, imenovana »Kubernetes usmerjen Java stack, prilagojen za GraalVM in OpenJDK HotSpot ter sestavljen iz najboljših knjižnic in standardov.« Danes bomo na primeru pokazali, kako posodobiti obstoječe aplikacije Java z uporabo zmogljivosti Quarkusa aplikacije helloworld iz repozitorija za hitri začetek Red Hat JBoss Enterprise Application Platform (JBoss EAP), ki uporablja tehnologiji CDI in Servlet 3, ki ju podpira Quarkus.

Tukaj je pomembno omeniti, da tako Quarkus kot JBoss EAP poudarjata uporabo orodij, ki čim bolj temeljijo na standardih. Nimate aplikacije, ki se izvaja na JBoss EAP? Ni problema, enostavno ga je mogoče preseliti z vašega trenutnega aplikacijskega strežnika na JBoss EAP z uporabo Komplet orodij za selitev aplikacij Red Hat. Po tem bo končna in delujoča različica posodobljene kode na voljo v repozitoriju github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus, v modulu Pozdravljen, svet.

Pri pisanju te objave smo uporabili Quarkus priročnikiv bistvu Ustvarjanje vaše prve aplikacije in stavba a Izvorna izvršljiva datoteka.

Vzemimo kodo

Najprej ustvarimo lokalni klon repozitorija Hitri začetki 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/

Poglejmo, kako deluje izvirni helloworld

Pravzaprav je bistvo te aplikacije jasno iz imena, vendar bomo njeno kodo posodobili strogo znanstveno. Zato si najprej poglejmo to aplikacijo v izvirni obliki.

Uvajanje helloworld

1. Odprite terminal in pojdite v koren mape JBoss EAP (lahko jo prenesete tukaj), to je v mapo EAP_HOME.

2. Zaženite strežnik JBoss EAP s privzetim profilom:

$ EAP_HOME/bin/standalone.sh

Opomba: V sistemu Windows se za zagon uporablja skript EAP_HOMEbinstandalone.bat.

Po nekaj sekundah bi se moralo v dnevniku prikazati nekaj takega:

[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. Odprite v brskalniku 127.0.0.1:8080 in vidimo tole:

Quarkus: Posodobitev aplikacije z uporabo Helloworld kot primera iz JBoss EAP Quickstart

riž. 1. Domača stran JBoss EAP.

4. Sledite navodilom v priročniku Zgradite in uvedite Quickstart: razširite helloworld in izvedite (iz korenske mape projekta) naslednji ukaz:

$ mvn clean install wildfly:deploy

Po uspešni izvedbi tega ukaza bomo v dnevniku videli nekaj takega:

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

Tako je prva uvedba aplikacije helloworld na JBoss EAP trajala nekaj več kot 8 sekund.

Testiranje helloworld

Delujte strogo v skladu z navodili Dostop do aplikacije, odprite v brskalniku 127.0.0.1:8080/helloworld in vidimo tole:

Quarkus: Posodobitev aplikacije z uporabo Helloworld kot primera iz JBoss EAP Quickstart

riž. 2. Original Hello World iz JBoss EAP.

Izvajanje sprememb

Spremenite vhodni parameter createHelloMessage(ime niza) iz World v Marco:

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

Ponovno zaženite naslednji ukaz:

$ mvn clean install wildfly:deploy

Nato osvežimo stran v brskalniku in vidimo, da se je besedilo spremenilo:

Quarkus: Posodobitev aplikacije z uporabo Helloworld kot primera iz JBoss EAP Quickstart

riž. 3. Pozdravljen Marco v JBoss EAP.

Povrnite uvedbo helloworld in zaustavite JBoss EAP

To ni obvezno, vendar če želite preklicati uvajanje, lahko to storite z naslednjim ukazom:

$ mvn clean install wildfly:undeploy

Če želite zaustaviti svoj primerek JBoss EAP, preprosto pritisnite Ctrl+C v terminalskem oknu.

Nadgradnja helloworld

Zdaj pa posodobimo originalno aplikacijo helloworld.

Ustvari novo vejo

Po končanem projektu hitrega zagona ustvarimo novo delujočo vejo:

$ git checkout -b quarkus 7.2.0.GA

Spreminjanje datoteke pom.xml

Aplikacijo bomo začeli spreminjati iz datoteke pom.xml. Če želite dovoliti Quarkusu, da vanj vstavi bloke XML, zaženite naslednji ukaz v mapi helloworld:

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

Pri pisanju tega članka je bila uporabljena različica 0.23.2. Quarkus pogosto izdaja nove različice, katera različica je najnovejša, lahko izveste na spletni strani github.com/quarkusio/quarkus/releases/latest.

Zgornji ukaz bo v pom.xml vstavil naslednje elemente:

  • Lastnost , ki določa različico Quarkusa za uporabo.
  • blok za uvoz Quarkus BOM (seznam materialov), da ne bi dodali različice za vsako Quarkus odvisnost.
  • Vtičnik quarkus-maven-plugin je odgovoren za pakiranje aplikacije in zagotavljanje razvojnega načina.
  • Izvorni profil za ustvarjanje izvršljivih datotek aplikacije.

Poleg tega ročno izvedemo naslednje spremembe v pom.xml:

  1. Iz bloka vzamemo oznako in jo postavimo nad oznako . Ker bomo v naslednjem koraku izbrisali blok , moramo shraniti .
  2. Blok odstranimo, ker pri delu s Quarkusom ta aplikacija ne potrebuje več nadrejenega poma iz JBossa.
  3. Dodajte oznako in jo postavite pod oznako . Določite lahko želeno številko različice.
  4. Oznako odstranimo, ker ta aplikacija ni več WAR, ampak navaden JAR.
  5. Spreminjamo naslednje odvisnosti:
    1. Odvisnost javax.enterprise:cdi-api spremenimo v io.quarkus:quarkus-arc, pri čemer odstranimo provided, saj (v skladu z dokumenti) ta razširitev Quarkus zagotavlja vstavljanje odvisnosti CDI.
    2. Spremenimo odvisnost org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec v io.quarkus:quarkus-undertow, pri čemer odstranimo provided, saj je (v skladu z dokumenti) ta razširitev Quarkus zagotavlja podporo za servlet 'ov.
    3. Odstranimo odvisnost org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec, ker prihaja z odvisnostmi, ki smo jih pravkar spremenili.

Različica datoteke pom.xml z vsemi spremembami se nahaja na github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml.

Upoštevajte, da zgornji ukaz mvn io.quarkus:quarkus-maven-plugin:0.23.2:create ne samo spremeni datoteko pom.xml, ampak projektu doda tudi številne komponente, in sicer naslednje datoteke in mape:

  • Datoteki mvnw in mvnw.cmd ter mapa .mvn: Maven Wrapper vam omogoča zagon projektov Maven dane različice Maven brez namestitve te različice.
  • Mapa Docker (v imeniku src/main/): vsebuje primere datotek Docker za izvorni način in način jvm (skupaj z datoteko .dockerignore).
  • Mapa Viri (v imeniku src/main/): vsebuje prazno datoteko application.properties in vzorčno začetno stran Quarkus index.html (za več podrobnosti glejte Zagon posodobljenega helloworld).

Zaženite helloworld
Za testiranje aplikacije uporabljamo quarkus:dev, ki zažene Quarkus v razvojnem načinu (za več podrobnosti glejte ta razdelek v priročniku Razvojni način).

Opomba: Ta korak bo pričakovano povzročil napako, ker še nismo naredili vseh potrebnih sprememb.

Zdaj pa zaženimo ukaz, da vidimo, kako deluje:

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

Torej, ne deluje ... Zakaj?

UnsatisfiedResolutionException kaže na razred HelloService, ki je član razreda HelloWorldServlet (član java: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). Težava je v tem, da HelloWorldServlet potrebuje vbrizgan primerek HelloService in ga ni mogoče najti (čeprav sta oba razreda v istem paketu).

Čas je za vrnitev dokumentacijo in preberite, kako deluje v Quarkusu Vbrizgajte, in zato Konteksti in vstavljanje odvisnosti (CDI). Zato odprite vodnik Konteksti in vstavljanje odvisnosti in v razdelku Odkritje fižola beremo: "Razred gradnika, ki nima opombe, ki definira gradnik, ni preiskan."

Poglejmo razred HelloService – v resnici nima takšne opombe. Zato ga je treba dodati, da lahko Quarkus išče in najde fižol. In ker je to objekt brez stanja, lahko preprosto dodamo opombo @ApplicationScoped, kot je ta:

@ApplicationScoped
public class HelloService {

Opomba: tukaj vas lahko razvojno okolje prosi, da dodate zahtevani paket (glejte spodnjo vrstico) in to boste morali storiti ročno, takole:

import javax.enterprise.context.ApplicationScoped;

Če ste v dvomih, kateri obseg naj se uporabi v primeru, ko za izvorni gradnik sploh ni določen, preberite dokumentacijo JSR 365: Konteksti in vbrizgavanje odvisnosti za Javo 2.0—privzeti obseg.

Zdaj ponovno poskusimo zagnati aplikacijo z ukazom ./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]

Zdaj gre vse brez napak.

Lansiranje posodobljenega helloworld
Kot piše v dnevniku, ga odprite v brskalniku 0.0.0.0:8080 (privzeta začetna stran Quarkus) in vidimo to:

Quarkus: Posodobitev aplikacije z uporabo Helloworld kot primera iz JBoss EAP Quickstart

riž. 4. Začetna stran Quarkus dev.

Opomba WebServlet za to aplikacijo vsebuje naslednjo definicijo konteksta:

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

Zato gremo v brskalnik na 0.0.0.0:8080/HelloWorld in vidimo naslednje:

Quarkus: Posodobitev aplikacije z uporabo Helloworld kot primera iz JBoss EAP Quickstart

riž. 5: Stran za razvijalce Quarkus za aplikacijo Hello World.

No, vse deluje.

Zdaj pa spremenimo kodo. Upoštevajte, da se ukaz ./mvnw compile quarkus:dev še vedno izvaja in ga ne nameravamo ustaviti. Zdaj pa poskusimo uporabiti iste - zelo trivialne - spremembe v sami kodi in poglejmo, kako Quarkus olajša življenje razvijalcem:

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

Shranite datoteko in nato osvežite spletno stran, da vidite Hello Marco, kot je prikazano na spodnjem posnetku zaslona:

Quarkus: Posodobitev aplikacije z uporabo Helloworld kot primera iz JBoss EAP Quickstart

riž. 6. Stran Hello Marco v Quarkus dev.

Zdaj pa preverimo izhod v terminalu:

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

Osvežitev strani je sprožila zaznavo sprememb v izvorni kodi, Quarkus pa je samodejno izvedel proceduro stop-start. In vse to je bilo dokončano v samo 0.371 sekunde (tukaj je tista "ultra hitra subatomska Java").

Vgradnja helloworld v paket JAR
Zdaj, ko koda deluje, kot bi morala, jo zapakirajmo z naslednjim ukazom:

$ ./mvnw clean package

Ta ukaz ustvari dve datoteki JAR v mapi /target: datoteko helloworld-.jar, ki je standardni artefakt, ki ga je skupina Maven sestavila skupaj z razredi in viri projekta. In datoteka helloworld-runner.jar, ki je izvršljiva datoteka JAR.

Upoštevajte, da to ni uber-jar, saj so vse odvisnosti preprosto prekopirane v mapo /target/lib (niso pakirane v datoteko JAR). Če želite torej zagnati ta JAR iz druge mape ali na drugem gostitelju, morate tam kopirati samo datoteko JAR in mapo /lib, glede na to, da element Class-Path v datoteki MANIFEST.MF v paketu JAR vsebuje ekspliciten seznam datotek JAR iz map lib
Če želite izvedeti, kako ustvariti aplikacije uber-jar, si oglejte vadnico Uber-Jar Creation.

Zaženite helloworld, pakiran v JAR

Zdaj lahko zaženemo naš JAR s standardnim ukazom 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]

Ko vse to storite, pojdite v brskalnik na 0.0.0.0:8080 in preverite, ali vse deluje kot mora.

Prevajanje helloworld v izvorno izvršljivo datoteko

Torej naš helloworld deluje kot samostojna aplikacija Java z uporabo odvisnosti Quarkus. Lahko pa greste dlje in jo spremenite v izvorno izvršljivo datoteko.

Namestitev GraalVM
Najprej morate za to namestiti potrebna orodja:

1. Prenesite GraalVM 19.2.0.1 iz github.com/oracle/graal/releases/tag/vm-19.2.0.1.

2. Razširite preneseni arhiv:

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

3. Pojdite v mapo untar.

4. Zaženite spodnji ukaz za prenos in dodajanje izvorne slike:

$ ./bin/gu install native-image

5. Registrirajte mapo, ustvarjeno v koraku 2, v spremenljivko okolja GRAALVM_HOME:

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

Za več informacij in navodila za namestitev v drugih operacijskih sistemih glejte priročnik Gradnja izvorne izvršljive datoteke – predpogoji.

Vgradnja helloworld v izvorno izvršljivo datoteko
Branje priročnika Gradnja izvorne izvedljive datoteke—izdelava izvorne izvedljive datoteke: »Zdaj pa ustvarimo izvorno izvršljivo datoteko za našo aplikacijo, da skrajšamo čas zagona in velikost diska. Izvedljiva datoteka bo vsebovala vse, kar je potrebno za zagon aplikacije, vključno z JVM (oziroma njegovo okrnjeno različico, ki vsebuje samo tisto, kar je potrebno za zagon aplikacije) in samo našo aplikacijo.«

Če želite ustvariti izvorno izvršljivo datoteko, morate omogočiti izvorni profil Maven:

$ ./mvnw package -Pnative

Naša izdelava je trajala eno minuto in 10 sekund, končna datoteka helloworld—runner f pa je bila ustvarjena v mapi /target.

Zaženite izvirno izvršljivo datoteko helloworld

V prejšnjem koraku smo prejeli izvršljivo datoteko /target/helloworld—runner. Zdaj pa ga zaženimo:

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

Ponovno ga odprite v brskalniku 0.0.0.0:8080 in preverite, ali vse deluje kot mora.

Se nadaljuje!

Menimo, da bi bilo treba metodo posodobitve aplikacij Java z uporabo zmogljivosti Quarkus, obravnavano v tej objavi (čeprav z uporabo preprostega primera), aktivno uporabljati v resničnem življenju. Pri tem boste verjetno naleteli na številne težave, ki jih bomo delno obravnavali v naslednjem prispevku, kjer bomo govorili o tem, kako izmeriti porabo pomnilnika za oceno izboljšav zmogljivosti, ki je pomemben del celotnega procesa posodobitve aplikacije.

Vir: www.habr.com

Dodaj komentar