Quarkus: modernizacija aplikacije na primjeru helloworld iz JBoss EAP Quickstart

Pozdrav svima na ovom blogu, evo četvrtog posta iz Quarkus serije!

Quarkus: modernizacija aplikacije na primjeru helloworld iz JBoss EAP Quickstart

Prethodni post govorilo o tome kako Quarkus kombinuje MicroProfile i Spring. Podsjetimo to quarkus je pozicioniran kao “ultra-brza subatomska Java”, aka “Kubernetes orijentisan Java stog, skrojen za GraalVM i OpenJDK HotSpot i sastavljen iz najboljih biblioteka i standarda.” Danas ćemo pokazati kako modernizirati postojeće Java aplikacije koristeći mogućnosti Quarkusa, koristeći primjer helloworld aplikacije iz Red Hat JBoss Enterprise Application Platform (JBoss EAP) Quickstart repozitorija, koji koristi CDI i Servlet 3 tehnologije koje podržava Quarkus.

Ovdje je važno napomenuti da i Quarkus i JBoss EAP naglašavaju korištenje alata koji su što je više moguće zasnovani na standardima. Nemate pokrenutu aplikaciju na JBoss EAP-u? Nema problema, lako se može migrirati sa vašeg trenutnog servera aplikacija na JBoss EAP koristeći Red Hat paket alata za migraciju aplikacija. Nakon čega će konačna i radna verzija moderniziranog koda biti dostupna u spremištu github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus, u modulu helloworld.

Prilikom pisanja ovog posta koristili smo se Quarkus manualsu osnovi Kreiranje vaše prve aplikacije i zgrada a Native Executable.

Uzmimo kod

Prije svega, napravimo lokalni klon spremišta JBoss EAP brzi startovi:

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

Hajde da vidimo kako originalni helloworld radi

Zapravo, suština ove aplikacije je jasna iz naziva, ali ćemo njen kod modernizovati strogo naučno. Stoga, prvo, pogledajmo ovu aplikaciju u izvornom obliku.

Postavljanje helloworld

1. Otvorite terminal i idite na korijen JBoss EAP foldera (možete ga preuzeti ovdje), odnosno u folder EAP_HOME.

2. Pokrenite JBoss EAP server sa podrazumevanim profilom:

$ EAP_HOME/bin/standalone.sh

Napomena: Na Windows-u se za pokretanje koristi skripta EAP_HOMEbinstandalone.bat.

Nakon nekoliko sekundi, u zapisniku bi se trebalo pojaviti nešto poput ovoga:

[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. Otvorite u pretraživaču 127.0.0.1:8080 i vidimo ovo:

Quarkus: modernizacija aplikacije na primjeru helloworld iz JBoss EAP Quickstart

Rice. 1. JBoss EAP početna stranica.

4. Slijedite upute u priručniku Napravite i implementirajte Quickstart: proširite helloworld i pokrenite (iz korijenskog foldera projekta) sljedeću naredbu:

$ mvn clean install wildfly:deploy

Nakon uspješnog izvršavanja ove naredbe, u zapisniku ćemo vidjeti nešto poput sljedećeg:

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

Dakle, prva implementacija helloworld aplikacije na JBoss EAP trajala je nešto više od 8 sekundi.

Testiranje helloworld

Ponašanje striktno prema uputstvu Pristupite aplikaciji, otvorite u pretraživaču 127.0.0.1:8080/helloworld i vidimo ovo:

Quarkus: modernizacija aplikacije na primjeru helloworld iz JBoss EAP Quickstart

Rice. 2. Original Hello World iz JBoss EAP-a.

Pravljenje promjena

Promijenite ulazni parametar createHelloMessage(String name) iz World u Marco:

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

Ponovo pokrenite sljedeću naredbu:

$ mvn clean install wildfly:deploy

Zatim osvježimo stranicu u pretraživaču i vidimo da se tekst promijenio:

Quarkus: modernizacija aplikacije na primjeru helloworld iz JBoss EAP Quickstart

Rice. 3. Zdravo Marko u JBoss EAP-u.

Vratite helloworld implementaciju i isključite JBoss EAP

Ovo nije obavezno, ali ako želite da otkažete implementaciju, možete to učiniti sa sljedećom naredbom:

$ mvn clean install wildfly:undeploy

Da biste isključili JBoss EAP instancu, jednostavno pritisnite Ctrl+C u prozoru terminala.

Nadogradnja helloworld

Sada modernizirajmo originalnu helloworld aplikaciju.

Kreirajte novu granu

Kreiramo novu radnu granu nakon što je projekat brzog pokretanja završen:

$ git checkout -b quarkus 7.2.0.GA

Promjena datoteke pom.xml

Počet ćemo mijenjati aplikaciju iz pom.xml datoteke. Da biste omogućili Quarkusu da u njega umetne XML blokove, pokrenite sljedeću naredbu u folderu helloworld:

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

Prilikom pisanja ovog članka korištena je verzija 0.23.2. Quarkus često objavljuje nove verzije, možete saznati koja je najnovija verzija na web stranici github.com/quarkusio/quarkus/releases/latest.

Gornja naredba će umetnuti sljedeće elemente u pom.xml:

  • Nekretnina , koji specificira verziju Quarkusa koju treba koristiti.
  • Blokiraj da uvezete Quarkus BOM (broj materijala), kako ne biste dodali verziju za svaku Quarkus zavisnost.
  • quarkus-maven-plugin je odgovoran za pakovanje aplikacije i pružanje načina razvoja.
  • Izvorni profil za kreiranje izvršnih datoteka aplikacije.

Osim toga, ručno unosimo sljedeće promjene u pom.xml:

  1. Izvlačenje etikete iz bloka i postavite je iznad oznake . Jer u sljedećem koraku ćemo ukloniti blok , onda morate sačuvati .
  2. Uklanjanje bloka , jer kada radi sa Quarkusom, ovoj aplikaciji više neće biti potreban JBoss-ov roditeljski pom.
  3. Dodajte oznaku i stavite ga ispod oznake . Možete odrediti broj verzije koji želite.
  4. Uklanjanje oznake , pošto ova aplikacija više nije WAR, već običan JAR.
  5. Mi mijenjamo sljedeće zavisnosti:
    1. Promijenite ovisnost javax.enterprise:cdi-api u io.quarkus:quarkus-arc, uklanjajući obezbeđeno , budući da (prema dokumentima) ova Quarkus ekstenzija pruža injekciju CDI zavisnosti.
    2. Promijenite ovisnost org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec u io.quarkus:quarkus-undertow, uklanjajući obezbeđeno , jer (prema dokumentaciji) ova Quarkus ekstenzija pruža podršku za servlete.
    3. Uklanjamo ovisnost org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec jer dolazi s ovisnostima koje smo upravo promijenili.

Verzija datoteke pom.xml sa svim promjenama nalazi se na github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml.

Imajte na umu da gornja naredba mvn io.quarkus:quarkus-maven-plugin:0.23.2:create ne samo da mijenja datoteku pom.xml, već i dodaje brojne komponente projektu, odnosno sljedeće datoteke i mape:

  • Datoteke mvnw i mvnw.cmd i fascikla .mvn: Maven Wrapper vam omogućava da pokrenete Maven projekte date Maven verzije bez instaliranja te verzije.
  • Docker folder (u direktoriju src/main/): Ovo sadrži primjere Dockerfiles-a za native i jvm modove (zajedno sa .dockerignore datotekom).
  • Fascikla Resursi (u direktoriju src/main/): Ovo sadrži praznu datoteku application.properties i primjer Quarkus index.html početne stranice (pogledajte Pokreni modernizirani helloworld za više detalja).

Pokreni helloworld
Za testiranje aplikacije koristimo quarkus:dev, koji pokreće Quarkus u razvojnom modu (za više detalja pogledajte ovaj odjeljak u priručniku Razvojni mod).

Napomena: Ovaj korak će očekivano rezultirati greškom, jer još nismo izvršili sve potrebne promjene.

Sada pokrenimo naredbu da vidimo kako funkcionira:

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

Dakle, ne radi... Zašto?

UnsatisfiedResolutionException ukazuje na klasu HelloService, koja je član klase HelloWorldServlet (java član: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). Problem je u tome što HelloWorldServletu treba ubačena instanca HelloServicea, a ona se ne može pronaći (iako su obje ove klase u istom paketu).

Vrijeme je da se vratimo dokumentaciju i pročitajte kako to radi u Quarkusu Injektirati, i zbog toga Konteksti i injekcija zavisnosti (CDI). Stoga, otvorite vodič za ubacivanje konteksta i zavisnosti i u odjeljku Bean Discovery čitamo: "Bean klasa koja nema bean-definirajuću bilješku ne pretražuje se."

Pogledajmo klasu HelloService - ona zaista nema takvu napomenu. Stoga se mora dodati tako da Quarkus može pretraživati ​​i pronaći bean. A pošto je ovo objekat bez stanja, lako možemo dodati napomenu @ApplicationScoped ovako:

@ApplicationScoped
public class HelloService {

Napomena: ovdje razvojno okruženje može tražiti od vas da dodate potreban paket (pogledajte red ispod), a to ćete morati učiniti ručno, ovako:

import javax.enterprise.context.ApplicationScoped;

Ako ste u nedoumici koji opseg treba koristiti u slučaju kada uopće nije naveden za izvorni bean, pročitajte dokumentaciju JSR 365: Konteksti i ubacivanje zavisnosti za Javu 2.0—Podrazumevani opseg.

Sada ponovo pokušavamo pokrenuti aplikaciju naredbom ./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]

Sada sve ide bez grešaka.

Pokretanje moderniziranog helloworlda
Kao što je napisano u dnevniku, otvorite ga u pretraživaču 0.0.0.0:8080 (podrazumevana Quarkus početna stranica) i vidimo ovo:

Quarkus: modernizacija aplikacije na primjeru helloworld iz JBoss EAP Quickstart

Rice. 4. Quarkus dev početna stranica.

WebServlet napomena za ovu aplikaciju sadrži sljedeću definiciju konteksta:

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

Stoga idemo u pretraživač na 0.0.0.0:8080/HelloWorld i vidimo sljedeće:

Quarkus: modernizacija aplikacije na primjeru helloworld iz JBoss EAP Quickstart

Rice. 5: Quarkus dev stranica za aplikaciju Hello World.

Pa, sve radi.

Sada napravimo promjene u kodu. Imajte na umu da naredba ./mvnw compile quarkus:dev još uvijek radi i da nemamo namjeru da je zaustavimo. Sada pokušajmo primijeniti iste - najtrivijalnije - promjene na sam kod i vidjeti kako Quarkus olakšava život programeru:

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

Sačuvajte datoteku, a zatim osvježite web stranicu da vidite Hello Marco, kao što je prikazano na slici ispod:

Quarkus: modernizacija aplikacije na primjeru helloworld iz JBoss EAP Quickstart

Rice. 6. Hello Marco stranica u Quarkus dev.

Sada provjerimo izlaz u 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

Osvježavanje stranice pokrenulo je otkrivanje promjena u izvornom kodu, a Quarkus je automatski izvršio stop-start proceduru. I sve je to završeno za samo 0.371 sekundu (evo je ta „ultra-brza subatomska Java“).

Izgradnja helloworlda u JAR paket
Sada kada kod radi kako treba, hajde da ga upakujemo sa sljedećom naredbom:

$ ./mvnw clean package

Ova komanda kreira dvije JAR datoteke u /target folderu: helloworld-.jar datoteku, koja je standardni artefakt koji je sastavio Maven tim zajedno sa klasama i resursima projekta. I helloworld-runner.jar fajl, koji je izvršni JAR.

Imajte na umu da ovo nije uber-jar, jer se sve zavisnosti jednostavno kopiraju u /target/lib folder (ne pakuju u JAR fajl). Stoga, da biste pokrenuli ovaj JAR iz drugog foldera ili na drugom hostu, morate kopirati i samu JAR datoteku i /lib mapu tamo, s obzirom da element Class-Path u datoteci MANIFEST.MF u JAR paketu sadrži eksplicitna lista JAR-ova iz lib foldera
Da naučite kako kreirati uber-jar aplikacije, pogledajte tutorijal Kreiranje Uber-Jar-a.

Pokrenite helloworld upakovan u JAR

Sada možemo pokrenuti naš JAR koristeći standardnu ​​java komandu:

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

Nakon što sve ovo uradite, idite na svoj pretraživač na 0.0.0.0:8080 i provjeri da li sve radi kako treba.

Prevođenje helloworld u izvornu izvršnu datoteku

Dakle, naš helloworld radi kao samostalna Java aplikacija koristeći Quarkus zavisnosti. Ali možete ići dalje i pretvoriti ga u izvornu izvršnu datoteku.

Instaliranje GraalVM-a
Prije svega, za to morate instalirati potrebne alate:

1. Preuzmite GraalVM 19.2.0.1 sa github.com/oracle/graal/releases/tag/vm-19.2.0.1.

2. Proširite preuzetu arhivu:

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

3. Idite u mapu untar.

4. Pokrenite naredbu ispod da preuzmete i dodate izvornu sliku:

$ ./bin/gu install native-image

5. Registrirajte mapu kreiranu u koraku 2 u varijablu okruženja GRAALVM_HOME:

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

Za više informacija i uputstva za instalaciju na drugim OS-ovima, pogledajte priručnik Izrada izvorne izvršne datoteke—preduvjeti.

Izgradnja helloworlda u izvornu izvršnu datoteku
Čitanje priručnika Izrada izvorne izvršne datoteke—proizvodnja izvorne izvršne datoteke: „Sada napravimo izvornu izvršnu datoteku za našu aplikaciju kako bismo smanjili vrijeme njenog pokretanja i veličinu diska. Izvršna datoteka imat će sve što je potrebno za pokretanje aplikacije, uključujući JVM (ili bolje rečeno, skraćenu verziju, koja sadrži samo ono što je potrebno za pokretanje aplikacije) i samu našu aplikaciju.”

Da kreirate izvornu izvršnu datoteku, morate omogućiti izvorni Maven profil:

$ ./mvnw package -Pnative

Naša izrada trajala je jednu minutu i 10 sekundi, a konačna datoteka helloworld—runner f kreirana je u /target folderu.

Pokrenite izvornu izvršnu datoteku helloworld

U prethodnom koraku dobili smo izvršnu datoteku /target/helloworld—runner. Sada ga pokrenimo:

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

Ponovo ga otvorite u pretraživaču 0.0.0.0:8080 i provjeri da li sve radi kako treba.

Nastaviti!

Vjerujemo da metod modernizacije Java aplikacija korištenjem Quarkus mogućnosti o kojem se govori u ovom postu (iako koristeći jednostavan primjer) treba aktivno koristiti u stvarnom životu. Pri tome ćete vjerovatno naići na niz problema, koje ćemo djelimično pozabaviti u sljedećem postu, gdje ćemo govoriti o tome kako mjeriti potrošnju memorije za procjenu poboljšanja performansi, što je važan dio cjelokupnog procesa modernizacije aplikacije.

izvor: www.habr.com

Dodajte komentar