Quarkus: Application Modernization Using Helloworld som et eksempel fra JBoss EAP Quickstart

Hei alle sammen på denne bloggen, her er det fjerde innlegget i Quarkus-serien!

Quarkus: Application Modernization Using Helloworld som et eksempel fra JBoss EAP Quickstart

Forrige innlegg handlet om hvordan Quarkus kombinerer MicroProfile og Spring. La oss minne deg på det quarkus er posisjonert som "ultra-rask subatomisk Java", aka "Kubernetes-orientert Java-stack, skreddersydd for GraalVM og OpenJDK HotSpot og satt sammen fra de beste bibliotekene og standardene." I dag vil vi vise hvordan du moderniserer eksisterende Java-applikasjoner ved å bruke egenskapene til Quarkus, ved å bruke eksemplet helloworld-applikasjoner fra Red Hat JBoss Enterprise Application Platform (JBoss EAP) hurtigstartdepot, som bruker CDI- og Servlet 3-teknologier støttet av Quarkus.

Det er viktig å merke seg her at både Quarkus og JBoss EAP legger vekt på å bruke verktøy som er så standardbaserte som mulig. Har du ikke en applikasjon som kjører på JBoss EAP? Ikke noe problem, det kan enkelt migreres fra din nåværende applikasjonsserver til JBoss EAP ved hjelp av Red Hat Application Migration Toolkit. Deretter vil den endelige og fungerende versjonen av den moderniserte koden være tilgjengelig i depotet github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus, i modulen Hei Verden.

Når vi skrev dette innlegget brukte vi Quarkus-opplæringer, i utgangspunktet Opprett din første applikasjon og bygge a Innfødt kjørbar.

La oss hente koden

Først av alt, la oss lage en lokal klone av depotet JBoss EAP hurtigstarter:

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

La oss se hvordan den originale helloworld fungerer

Egentlig er essensen av denne applikasjonen tydelig fra navnet, men vi vil modernisere koden strengt vitenskapelig. La oss derfor først se på denne applikasjonen i sin opprinnelige form.

Distribuerer helloworld

1. Åpne en terminal og gå til roten til JBoss EAP-mappen (du kan laste den ned her), det vil si til EAP_HOME-mappen.

2. Start JBoss EAP-serveren med standardprofilen:

$ EAP_HOME/bin/standalone.sh

Merk: På Windows brukes EAP_HOMEbinstandalone.bat-skriptet til å starte det.

Etter et par sekunder bør noe slikt dukke opp i loggen:

[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. Åpne i en nettleser 127.0.0.1:8080 og vi ser dette:

Quarkus: Application Modernization Using Helloworld som et eksempel fra JBoss EAP Quickstart

Ris. 1. JBoss EAP-hjemmeside.

4. Følg instruksjonene i håndboken Bygg og distribuer hurtigstart: utvid helloworld og kjør (fra prosjektets rotmapp) følgende kommando:

$ mvn clean install wildfly:deploy

Etter å ha utført denne kommandoen, vil vi se noe sånt som følgende i loggen:

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

Så den første distribusjonen av helloworld-applikasjonen på JBoss EAP tok litt over 8 sekunder.

Tester helloworld

Handler strengt i henhold til instruksjonene Få tilgang til applikasjonen, åpne i nettleseren 127.0.0.1:8080/helloworld og vi ser dette:

Quarkus: Application Modernization Using Helloworld som et eksempel fra JBoss EAP Quickstart

Ris. 2. Original Hello World fra JBoss EAP.

Gjør endringer

Endre inndataparameteren createHelloMessage(String name) fra World til Marco:

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

Kjør følgende kommando igjen:

$ mvn clean install wildfly:deploy

Så oppdaterer vi siden i nettleseren og ser at teksten er endret:

Quarkus: Application Modernization Using Helloworld som et eksempel fra JBoss EAP Quickstart

Ris. 3. Hei Marco i JBoss EAP.

Rull tilbake helloworld-distribusjonen og slå av JBoss EAP

Dette er valgfritt, men hvis du vil avbryte distribusjonen, kan du gjøre det med følgende kommando:

$ mvn clean install wildfly:undeploy

For å slå av JBoss EAP-forekomsten, trykk ganske enkelt Ctrl+C i terminalvinduet.

Oppgraderer helloworld

La oss nå modernisere den originale helloworld-applikasjonen.

Opprett en ny filial

Vi oppretter en ny arbeidsgren etter at hurtigstartprosjektet er fullført:

$ git checkout -b quarkus 7.2.0.GA

Endre pom.xml-filen

Vi vil begynne å endre applikasjonen fra pom.xml-filen. For å tillate Quarkus å sette inn XML-blokker i den, kjør følgende kommando i helloworld-mappen:

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

Ved skriving av denne artikkelen ble versjon 0.23.2 brukt. Quarkus slipper ofte nye versjoner, du kan finne ut hvilken versjon som er den nyeste på nettsiden github.com/quarkusio/quarkus/releases/latest.

Kommandoen ovenfor vil sette inn følgende elementer i pom.xml:

  • Egenskapen , som spesifiserer versjonen av Quarkus som skal brukes.
  • -blokk for import av Quarkus BOM (stykkliste), for ikke å legge til en versjon for hver Quarkus-avhengighet.
  • Quarkus-maven-pluginet er ansvarlig for å pakke applikasjonen og gi utviklingsmodus.
  • Den opprinnelige profilen for å lage kjørbare programmer.

I tillegg gjør vi manuelt følgende endringer i pom.xml:

  1. Vi tar ut -taggen fra -blokken og plasserer den over -taggen. Siden vi i neste trinn vil slette -blokken, må vi lagre .
  2. Vi fjerner -blokken fordi når du arbeider med Quarkus, vil ikke denne applikasjonen lenger trenge den overordnede pom fra JBoss.
  3. Legg til en -tag og plasser den under -taggen. Du kan angi hvilket versjonsnummer du ønsker.
  4. Vi fjerner -taggen, siden denne applikasjonen ikke lenger er en WAR, men en vanlig JAR.
  5. Vi endrer følgende avhengigheter:
    1. Vi endrer javax.enterprise:cdi-api-avhengigheten til io.quarkus:quarkus-arc, og fjerner provided, siden (ifølge dokumentene) denne Quarkus-utvidelsen gir injeksjon av CDI-avhengigheter.
    2. Vi endrer avhengigheten org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec til io.quarkus:quarkus-undertow, og fjerner levert, siden (ifølge dokumentene) denne Quarkus-utvidelsen gir servlet-støtte 'ov.
    3. Vi fjerner org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec-avhengigheten siden den kommer med avhengighetene vi nettopp har endret.

Versjonen av pom.xml-filen med alle endringene er plassert på github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml.

Merk at mvn io.quarkus:quarkus-maven-plugin:0.23.2:create-kommandoen ovenfor ikke bare endrer pom.xml-filen, men legger også til en rekke komponenter til prosjektet, nemlig følgende filer og mapper:

  • Filen mvnw og mvnw.cmd og .mvn-mappen: Maven Wrapper lar deg kjøre Maven-prosjekter av en gitt Maven-versjon uten å installere den versjonen.
  • Docker-mappen (i src/main/-katalogen): Denne inneholder eksempler på Docker-filer for opprinnelige og jvm-moduser (sammen med .dockerignore-filen).
  • Resources-mappen (i src/main/-katalogen): Denne inneholder en tom application.properties-fil og et eksempel på Quarkus index.html-startside (se Kjør den moderniserte helloworld for flere detaljer).

Start helloworld
For å teste applikasjonen bruker vi quarkus:dev, som starter Quarkus i utviklingsmodus (for flere detaljer, se denne delen i håndboken Utviklingsmodus).

Merk: Dette trinnet vil forventes å resultere i en feil, siden vi ennå ikke har gjort alle nødvendige endringer.

La oss nå kjøre kommandoen for å se hvordan den fungerer:

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

Så, det fungerer ikke... Hvorfor?

UnsatisfiedResolutionException peker på HelloService-klassen, som er medlem av HelloWorldServlet-klassen (java-medlem: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). Problemet er at HelloWorldServlet trenger en injisert forekomst av HelloService, og den kan ikke bli funnet (selv om begge disse klassene er i samme pakke).

Det er på tide å gå tilbake til dokumentasjon og les hvordan det fungerer i Quarkus injisere, og derfor Kontekster og avhengighetsinjeksjon (CDI). Åpne derfor Contexts and Dependency Injection guide og i delen Bean Discovery vi leser: "En bønneklasse som ikke har en bønnedefinerende merknad søkes ikke i."

La oss se på HelloService-klassen - den har egentlig ikke en slik merknad. Derfor må den legges til slik at Quarkus kan søke og finne bønnen. Og siden dette er et statsløst objekt, kan vi enkelt legge til @ApplicationScoped-kommentaren slik:

@ApplicationScoped
public class HelloService {

Merk: her kan utviklingsmiljøet be deg om å legge til den nødvendige pakken (se linjen nedenfor), og du må gjøre dette manuelt, slik:

import javax.enterprise.context.ApplicationScoped;

Hvis du er i tvil om hvilket skop som skal brukes i tilfelle når det ikke er spesifisert for kildebønnen i det hele tatt, les dokumentasjonen JSR 365: Contexts and Dependency Injection for Java 2.0 – Standard omfang.

Nå prøver vi igjen å starte programmet med kommandoen ./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]

Nå går alt uten feil.

Lansering av den moderniserte helloworld
Som skrevet i loggen, åpne den i nettleseren 0.0.0.0:8080 (standard Quarkus-startside) og vi ser dette:

Quarkus: Application Modernization Using Helloworld som et eksempel fra JBoss EAP Quickstart

Ris. 4. Quarkus dev startside.

WebServlet-kommentaren for denne applikasjonen inneholder følgende kontekstdefinisjon:

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

Derfor går vi i nettleseren til 0.0.0.0:8080/HelloWorld og vi ser følgende:

Quarkus: Application Modernization Using Helloworld som et eksempel fra JBoss EAP Quickstart

Ris. 5: Quarkus-utviklersiden for Hello World-applikasjonen.

Vel, alt fungerer.

La oss nå gjøre endringer i koden. Legg merke til at ./mvnw compile quarkus:dev-kommandoen fortsatt kjører og vi har ingen intensjon om å stoppe den. La oss nå prøve å bruke de samme - veldig trivielle - endringene på selve koden og se hvordan Quarkus gjør livet enklere for utvikleren:

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

Lagre filen og oppdater deretter nettsiden for å se Hallo Marco, som vist på skjermbildet nedenfor:

Quarkus: Application Modernization Using Helloworld som et eksempel fra JBoss EAP Quickstart

Ris. 6. Hei Marco-siden i Quarkus dev.

La oss nå sjekke utgangen i terminalen:

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

Sideoppdateringen utløste oppdagelsen av endringer i kildekoden, og Quarkus utførte automatisk en stopp-start-prosedyre. Og alt dette ble fullført på bare 0.371 sekunder (her er det den "ultraraske subatomære Java").

Bygg helloworld til en JAR-pakke
Nå som koden fungerer som den skal, la oss pakke den med følgende kommando:

$ ./mvnw clean package

Denne kommandoen oppretter to JAR-filer i /target-mappen: helloworld-.jar-filen, som er en standardartefakt satt sammen av Maven-teamet sammen med prosjektets klasser og ressurser. Og helloworld-runner.jar-filen, som er en kjørbar JAR.

Vær oppmerksom på at dette ikke er en uber-jar, siden alle avhengigheter ganske enkelt kopieres til /target/lib-mappen (ikke pakket inn i en JAR-fil). Derfor, for å kjøre denne JAR fra en annen mappe eller på en annen vert, må du kopiere både selve JAR-filen og /lib-mappen dit, gitt at Class-Path-elementet i MANIFEST.MF-filen i JAR-pakken inneholder en eksplisitt liste over JAR-er fra lib-mapper
For å lære hvordan du lager uber-jar-applikasjoner, se veiledningen Uber-Jar Creation.

Lanser helloworld pakket i JAR

Nå kan vi kjøre JAR ved å bruke standard java-kommandoen:

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

Etter at alt dette er gjort, gå til nettleseren din på 0.0.0.0:8080 og sjekk at alt fungerer som det skal.

Kompilere helloworld til en opprinnelig kjørbar fil

Så vår helloworld kjører som en frittstående Java-applikasjon som bruker Quarkus-avhengigheter. Men du kan gå videre og gjøre den om til en opprinnelig kjørbar fil.

Installerer GraalVM
Først av alt, for dette må du installere de nødvendige verktøyene:

1. Last ned GraalVM 19.2.0.1 fra github.com/oracle/graal/releases/tag/vm-19.2.0.1.

2. Utvid det nedlastede arkivet:

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

3. Gå til untar-mappen.

4. Kjør kommandoen nedenfor for å laste ned og legge til det opprinnelige bildet:

$ ./bin/gu install native-image

5. Registrer mappen opprettet i trinn 2 til GRAALVM_HOME miljøvariabelen:

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

For mer informasjon og installasjonsinstruksjoner om andre operativsystemer, se håndboken Bygge en innfødt kjørbar – forutsetninger.

Bygg helloworld til en opprinnelig kjørbar fil
Leser manualen Bygge en innebygd kjørbar – Produsere en innebygd kjørbar: «La oss nå lage en innebygd kjørbar fil for applikasjonen vår for å redusere lanseringstiden og diskstørrelsen. Den kjørbare filen vil ha alt som er nødvendig for å kjøre applikasjonen, inkludert JVM (eller rettere sagt, en avkortet versjon av den, som bare inneholder det som kreves for å kjøre applikasjonen) og selve applikasjonen vår."

For å lage en innebygd kjørbar fil, må du aktivere den opprinnelige Maven-profilen:

$ ./mvnw package -Pnative

Byggingen vår tok ett minutt og 10 sekunder, og den siste helloworld-runner f-filen ble opprettet i /target-mappen.

Kjør den opprinnelige kjørbare helloworld

I forrige trinn mottok vi den kjørbare filen /target/helloworld—runner. La oss nå kjøre det:

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

Åpne den i nettleseren igjen 0.0.0.0:8080 og sjekk at alt fungerer som det skal.

Fortsettelse følger!

Vi mener at metoden for å modernisere Java-applikasjoner ved å bruke Quarkus-funksjoner diskutert i dette innlegget (om enn ved å bruke et enkelt eksempel) bør brukes aktivt i det virkelige liv. Når du gjør det, vil du sannsynligvis støte på en rekke problemer, som vi delvis vil ta opp i neste innlegg, hvor vi vil snakke om hvordan du kan måle minneforbruk for å vurdere ytelsesforbedringer, en viktig del av hele applikasjonsmoderniseringsprosessen.

Kilde: www.habr.com

Legg til en kommentar