Përshëndetje të gjithëve në këtë blog, dhe me ju është postimi i katërt në serinë për Quarkus!

ishte pĂ«r mĂ«nyrĂ«n se si Quarkus bashkon MicroProfile dhe Spring. KujtojmĂ« se pozicionohet si âJava super e shpejtĂ« subatomikeâ, si edhe âstack Java i orientuar drejt Kubernetes, i optimizuar pĂ«r GraalVM dhe OpenJDK HotSpot dhe i ndĂ«rtuar nga bibliotekat dhe standardet mĂ« tĂ« miraâ. Sot do tĂ« tregojmĂ« se si tĂ« modernizoni aplikacionet ekzistuese Java duke pĂ«rdorur mundĂ«sitĂ« e Quarkus, me shembullin e , ku pĂ«rdoren teknologjitĂ« CDI dhe Servlet 3 tĂ« mbĂ«shtetura nga Quarkus.
Këtu është e rëndësishme të theksohet se si Quarkus, ashtu edhe JBoss EAP, i kushtojnë vëmendje përdorimit të mjeteve të ndërtuara sa më shumë mbi standarde. Nuk keni një aplikacion që punon në JBoss EAP? Nuk ka problem, ai mund të migrohet lehtësisht nga serveri aktual i aplikacioneve në JBoss EAP me ndihmën e . Pas kësaj, versioni përfundimtar dhe funksional i kodit të modernizuar do të jetë i disponueshëm në depon , në modulin .
Gjatë shkrimit të këtij postimi u përdorën , kryesisht dhe Building a .
Le të sigurojmë kodin
Së pari, do të krijojmë një klon lokal të depos :
$ 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/
Shikojmë se si funksionon helloworld fillestar
Në fakt, thelbi i këtij aplikacioni kuptohet nga vetë emri, por ne do ta modernizojmë kodin e tij në mënyrë rigoroze dhe metodike. Prandaj, fillimisht do ta shohim këtë aplikacion në gjendjen e tij fillestare.
Vendosim në funksion helloworld
1. Hapni terminalin dhe kaloni te rrënja e dosjes JBoss EAP (mund ta shkarkoni ), pra te dosja EAP_HOME.
2. Nisni serverin JBoss EAP me profilin e parazgjedhur:
$ EAP_HOME/bin/standalone.sh
Vërejtje: në Windows për nisje përdoret skripti EAP_HOMEbinstandalone.bat.
Pas disa sekondash, në log duhet të shfaqet afërsisht kjo:
[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. Hapni në shfletues :8080 dhe do të shihni këtë:

Fig. 1. Faqja kryesore e JBoss EAP.
4. Ndiqni udhëzimet në udhëzues : vendosim helloworld dhe ekzekutojmë (nga dosja rrënjë e projektit) komandën e mëposhtme:
$ mvn clean install wildfly:deploy
Pas ekzekutimit me sukses të kësaj komande, në log do të shohim afërsisht sa vijon:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.224 s
Pra, vendosja e parë e aplikacionit helloworld në JBoss EAP zgjati pak më shumë se 8 sekonda.
Testojmë helloworld
Duke ndjekur me përpikëri udhëzuesin , hapim në shfletues :8080/helloworld dhe shohim këtë:

Fig. 2. Hello World origjinal nga JBoss EAP.
Bëjmë ndryshime
Ndryshojmë parametrin hyrës createHelloMessage(String name) nga World në Marco:
writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");
Ekzekutojmë sërish komandën e mëposhtme:
$ mvn clean install wildfly:deploy
Pastaj rifreskojmë faqen në shfletues dhe shohim që teksti ka ndryshuar:

Fig. 3. Hello Marco në JBoss EAP.
Anulojmë vendosjen e helloworld dhe mbyllim JBoss EAP
Kjo nuk është e detyrueshme, por nëse dëshironi të anuloni vendosjen, mund ta bëni me komandën e mëposhtme:
$ mvn clean install wildfly:undeploy
Për të ndalur instancën e JBoss EAP, thjesht shtypni Ctrl+C në dritaren e terminalit.
Modernizojmë helloworld
Tani do të merremi me modernizimin e aplikacionit burimor helloworld.
Krijojmë një degë të re
Krijojmë një degë të re pune pasi të përfundojë ekzekutimi i projektit quickstart:
$ git checkout -b quarkus 7.2.0.GA
Ndryshojmë skedarin pom.xml
Do të fillojmë ndryshimet në aplikacion nga skedari pom.xml. Që Quarkus të mund të fusë blloqe XML në të, ekzekutoni komandën e mëposhtme në dosjen helloworld:
$ mvn io.quarkus:quarkus-maven-plugin:0.23.2:create
Gjatë shkrimit të këtij artikulli është përdorur versioni 0.23.2. Quarkus publikon shpesh versione të reja; për të parë cili është versioni më i fundit, mund të vizitoni .
Komanda e mësipërme do të fusë në pom.xml elementet e mëposhtme:
- Vetia , që përcakton versionin e Quarkus në përdorim.
- Blloku për importimin e Quarkus BOM (bill of materials), në mënyrë që të mos shtohet versioni për çdo varësi të Quarkus.
- Shtojca quarkus-maven-plugin, e cila merret me paketimin e aplikacionit dhe ofron modalitetin development mode.
- Profili native për krijimin e skedarëve të ekzekutueshëm të aplikacionit.
Përveç kësaj, në pom.xml bëjmë manualisht ndryshimet e mëposhtme:
- E nxjerrim etiketën nga blloku dhe e vendosim mbi etiketën . Meqenëse në hapin tjetër do të heqim bllokun , duhet të ruajmë .
- Heqim bllokun , pasi gjatĂ« punĂ«s me Quarkus kĂ«tij aplikacioni nuk do tâi duhet mĂ« POM prind nga JBoss.
- Shtojmë tag-un dhe e vendosim poshtë tag-ut . Numrin e versionit mund ta përcaktoni sipas dëshirës.
- Heqim tag-un , pasi ky aplikacion nuk është më WAR, por një JAR i zakonshëm.
- Modifikojmë varësitë e mëposhtme:
- Zëvendësojmë varësinë javax.enterprise:cdi-api me io.quarkus:quarkus-arc, duke hequr provided, sepse (sipas dokumentacionit) ky zgjerim i Quarkus siguron injektimin e varësive CDI.
- Zëvendësojmë varësinë org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec me io.quarkus:quarkus-undertow, duke hequr provided, sepse (sipas dokumentacionit) ky zgjerim i Quarkus ofron mbështetje për servlet-et.
- Heqim varësinë org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec, sepse ajo përfshihet tashmë në varësitë që sapo ndryshuam.
Versioni i skedarit pom.xml me të gjitha ndryshimet gjendet në adresën .
Vini re se komanda e mësipërme mvn io.quarkus:quarkus-maven-plugin:0.23.2:create jo vetëm që ndryshon skedarin pom.xml, por gjithashtu shton në projekt një sërë komponentësh, konkretisht skedarët dhe dosjet e mëposhtme:
- Skedarët mvnw dhe mvnw.cmd si edhe dosja .mvn: Maven Wrapper ju lejon të ekzekutoni projekte Maven me një version të caktuar të Maven pa e instaluar atë version.
- Dosja docker (në direktorinë src/main/): këtu gjenden shembuj të skedarëve Dockerfile për mënyrat native dhe jvm (së bashku me skedarin .dockerignore).
- Dosja resources (në direktorinë src/main/): këtu gjenden një skedar bosh application.properties dhe një shembull i faqes fillestare Quarkus index.html (për më shumë detaje shihni Run the modernized helloworld).
Nisim helloworld
Për të testuar aplikacionin, përdorim quarkus:dev, i cili nis Quarkus në development mode (për më shumë detaje shihni këtë seksion në udhëzuesin për ).
Vërejtje: ky hap pritet të çojë në një gabim, pasi ende nuk i kemi bërë të gjitha ndryshimet e nevojshme.
Tani ekzekutojmë komandën për të kontrolluar se si do të funksionojë kjo:
$ ./mvnw compile quarkus:dev
[INFO] Skanimi i projekteve...
[INFO]
[INFO] --------------------------------
[INFO] Ndërtimi i Quickstart: helloworld quarkus
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ helloworld ---
[INFO] Përdoret kodimi 'UTF-8' për të kopjuar burimet e filtruara.
[INFO] Po kopjohen 2 burime
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ helloworld ---
[INFO] Nuk ka asgjë për të kompiluar - të gjitha klasat janë të përditësuara
[INFO]
[INFO] --- quarkus-maven-plugin:0.23.2:dev (default-cli) @ helloworld ---
Po pritet për transportin dt_socket në adresën: 5005
INFO [io.qua.dep.QuarkusAugmentor] Fillimi i zgjerimit të quarkus
INFO [org.jbo.threads] Versioni i JBoss Threads 3.0.0.Final
ERROR [io.qua.dev.DevModeMain] Nisja e quarkus dështoi: java.lang.RuntimeException: io.quarkus.builder.BuildException: Dështim i build: Build dështoi për shkak të gabimeve
[error]: Hapi i build io.quarkus.arc.deployment.ArcProcessor#validate hodhi një përjashtim: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Varësi e paplotësuar për tipin org.jboss.as.quickstarts.helloworld.HelloService dhe kualifikuesit [@Default]
- anëtari java: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService
- e deklaruar në bean CLASS [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: Varësi e paplotësuar për tipin org.jboss.as.quickstarts.helloworld.HelloService dhe kualifikuesit [@Default]
- anëtari java: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService
- e deklaruar në bean CLASS [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 më shumë
Pra, nuk funksionon⊠Po pse?
Përjashtimi UnsatisfiedResolutionException tregon klasën HelloService, e cila është anëtare e klasës HelloWorldServlet (java member: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). Problemi është se HelloWorldServlet ka nevojë për një instancë të injektuar të HelloService, por ajo nuk mund të gjendet (edhe pse të dyja këto klasa ndodhen në të njëjtin paketë).
Tani është momenti të kthehemi te dhe të lexojmë si funksionon në Quarkus , dhe për rrjedhojë edhe (CDI). Prandaj hapim udhëzuesin Contexts and Dependency Injection dhe në seksionin lexojmë: «Një klasë bean që nuk ka një anotim përcaktues bean nuk zbulohet».
ShikojmĂ« klasĂ«n HelloService â nĂ« tĂ« vĂ«rtetĂ«, ajo nuk e ka njĂ« anotim tĂ« tillĂ«. Prandaj duhet ta shtojmĂ«, nĂ« mĂ«nyrĂ« qĂ« Quarkus tĂ« mund ta kĂ«rkojĂ« dhe ta gjejĂ« bean-in. Dhe meqĂ« ky Ă«shtĂ« njĂ« objekt stateless, mund tĂ« shtojmĂ« fare mirĂ« anotimin @ApplicationScoped si mĂ« poshtĂ«:
@ApplicationScoped
public class HelloService {
Vërejtje: Këtu mjedisi i zhvillimit mund t'ju kërkojë të shtoni paketën e nevojshme (shihni rreshtin më poshtë), dhe kjo do të duhet bërë manualisht, kështu:
import javax.enterprise.context.ApplicationScoped;
Nëse dyshoni se cilin scope duhet të përdorni kur për bean-in burimor ai nuk është përcaktuar fare, studioni dokumentacionin .
Tani provojmë sërish të nisim aplikacionin me komandën ./mvnw compile quarkus:dev:
$ ./mvnw compile quarkus:dev
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------------
[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]
Tani gjithçka kalon pa gabime.
Nisim helloworld-in e modernizuar
Siç është shkruar në log, hapim në shfletues :8080 (faqja fillestare standarde e Quarkus) dhe shohim këtë:

Fig. 4. Faqja fillestare e Quarkus dev.
Në anotimin WebServlet, për këtë aplikacion është përcaktuar ky kontekst:
@WebServlet("/HelloWorld")
public class HelloWorldServlet extends HttpServlet {
Prandaj, në shfletues hapim :8080/HelloWorld dhe shohim sa vijon:

Fig. 5: Faqja The Quarkus dev për aplikacionin Hello World.
Ja ku jemi, gjithçka funksionon.
Tani bëjmë ndryshime në kod. Vini re se komanda ./mvnw compile quarkus:dev ende po ekzekutohet dhe nuk do ta ndalim. Tani le të provojmë të aplikojmë të njëjtat ndryshime, krejtësisht minimale, drejtpërdrejt në kod dhe të shohim se si Quarkus ia lehtëson punën zhvilluesit:
writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");
Ruajmë skedarin dhe më pas rifreskojmë faqen e internetit për të parë mbishkrimin Hello Marco, siç tregohet në pamjen më poshtë:

Fig. 6. Faqja Hello Marco në Quarkus dev.
Tani le të kontrollojmë daljen në 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
Rifreskimi i faqes aktivizoi zbulimin e ndryshimeve nĂ« kodin burimor dhe Quarkus kreu automatikisht procedurĂ«n âstop-startâ. E gjithĂ« kjo u krye pĂ«r vetĂ«m 0.371 sekonda (ja ku Ă«shtĂ« ajo âJava super e shpejtĂ« nĂ«natomikeâ).
Ndërtojmë helloworld në paketë JAR
Tani që kodi funksionon siç duhet, le ta paketojmë me komandën e mëposhtme:
$ ./mvnw clean package
Kjo komandĂ« krijon dy skedarĂ« JAR nĂ« dosjen /target: skedarin helloworld-.jar, i cili Ă«shtĂ« njĂ« artefakt standard i ndĂ«rtuar nga komanda Maven sĂ« bashku me klasat dhe burimet e projektit, si dhe skedarin helloworldârunner.jar, i cili Ă«shtĂ« njĂ« JAR i ekzekutueshĂ«m.
Vini re se ky nuk është një uber-jar, sepse të gjitha varësitë thjesht kopjohen në dosjen /target/lib (dhe nuk paketohen brenda skedarit JAR). Prandaj, për ta nisur këtë JAR nga një dosje tjetër ose në një host tjetër, duhet të kopjoni si vetë skedarin JAR, ashtu edhe dosjen /lib, duke pasur parasysh se elementi Class-Path në skedarin MANIFEST.MF brenda paketës JAR përmban një listë të qartë të skedarëve JAR nga dosja lib.
Për të mësuar se si të krijoni aplikacione uber-jar, shihni udhëzuesin .
Nisim helloworld të paketuar në JAR
Tani mund ta nisim JAR-in tonë me komandën standarde java:
$ java -jar ./target/helloworld--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]
Pasi të përfundojë e gjithë kjo, hapeni në shfletues :8080 dhe kontrolloni që gjithçka të funksionojë si duhet.
Ndërtojmë helloworld në një skedar ekzekutues native
Pra, helloworld ynë funksionon si një aplikacion Java standalone, duke përdorur varësitë e Quarkus. Por mund të shkojmë më tej dhe ta kthejmë në një skedar ekzekutues native.
Instalojmë GraalVM
Së pari, duhet të instaloni mjetet e nevojshme:
1. Shkarkoni GraalVM 19.2.0.1 nga .
2. Shpaketoni arkivin e shkarkuar:
$ tar xvzf graalvm-ce-linux-amd64-19.2.0.1.tar.gz
3. Kaloni te dosja e shpaketuar.
4. Ekzekutoni komandën më poshtë për të shkarkuar dhe shtuar imazhin native:
$ ./bin/gu install native-image
5. Vendosni dosjen e krijuar në hapin 2 në variablën e mjedisit GRAALVM_HOME:
$ export GRAALVM_HOME={untar-folder}/graalvm-ce-19.2.0.1)
Informacione shtesë dhe udhëzime instalimi për sisteme të tjera operative i gjeni në udhëzuesin .
Ndërtojmë helloworld në një skedar ekzekutues native
Lexoni udhëzuesin : «Tani do të krijojmë një skedar ekzekutues native për aplikacionin tonë, për të ulur kohën e nisjes dhe hapësirën që zë në disk. Skedari ekzekutues do të përmbajë gjithçka që nevojitet për të nisur aplikacionin, përfshirë JVM-në (më saktë, një version të reduktuar të saj, që përmban vetëm atë që kërkohet për ekzekutimin e aplikacionit) dhe vetë aplikacionin tonë».
Për të krijuar një skedar ekzekutues native, duhet të aktivizoni profilin native të Maven:
$ ./mvnw package -Pnative
Te ne, ndĂ«rtimi zgjati njĂ« minutĂ« e 10 sekonda, ndĂ«rsa skedari pĂ«rfundimtar helloworldârunner f u krijua nĂ« dosjen /target.
Nisim skedarin ekzekutues native helloworld
NĂ« hapin e mĂ«parshĂ«m morĂ«m skedarin ekzekutues /target/helloworldârunner. Tani le ta nisim:
$ ./target/helloworld--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]
Hapeni sërish në shfletues :8080 dhe kontrolloni që gjithçka të funksionojë si duhet.
Vazhdon!
Ne besojmë se metoda e modernizimit të aplikacioneve Java me përdorimin e mundësive të Quarkus, e trajtuar në këtë postim (edhe pse në një shembull shumë të thjeshtë), ia vlen të zbatohet në mënyrë aktive në praktikë. Megjithatë, ka shumë gjasa që të hasni një sërë problemesh, zgjidhjen e të cilave do ta shqyrtojmë pjesërisht në postimin e ardhshëm, ku do të flasim për mënyrën se si të matet konsumi i memories për të vlerësuar përmirësimin e performancës, një pjesë e rëndësishme e gjithë procesit të modernizimit të aplikacioneve.
Burimi: habr.com
