Hej alla i den hÀr bloggen, och hÀr Àr det fjÀrde inlÀgget i serien om Quarkus!

handlade om hur Quarkus förenar MicroProfile och Spring. LÄt oss pÄminna om att det positioneras som "super snabb subatomÀr Java", Àven kallad "Kubernetes-orienterad Java-stack, optimerad för GraalVM och OpenJDK HotSpot och byggd med de bÀsta biblioteken och standarderna". Idag ska vi visa hur man moderniserar befintliga Java-applikationer med Quarkus möjligheter, genom exemplet , dÀr vi anvÀnder teknologier i Quarkus som CDI och Servlet 3.
Det Àr viktigt att notera att bÄde Quarkus och JBoss EAP fokuserar pÄ att anvÀnda verktyg som i största möjliga mÄn Àr byggda pÄ standarder. Har du ingen applikation som kör pÄ JBoss EAP? Inga problem, den kan enkelt flyttas frÄn din nuvarande applikationsserver till JBoss EAP med hjÀlp av . Den slutliga och fungerande versionen av den moderniserade koden kommer att finnas tillgÀnglig i repositoriet , i modulen .
Vid skrivandet av det hÀr inlÀgget anvÀndes , mestadels och Building a .
HĂ€mta koden
Först skapar vi en lokal klon av repositoriet :
$ git clone https://github.com/jboss-developer/jboss-eap-quickstarts.git
Klonar in i 'jboss-eap-quickstarts'...
remote: Enumrerar objekt: 148133, klart.
remote: Totalt 148133 (delta 0), ÄteranvÀnds 0 (delta 0), pack ÄteranvÀnds 148133
Mottar objekt: 100% (148133/148133), 59.90 MiB | 7.62 MiB/s, klart.
Löser deltar: 100% (66476/66476), klart.
$ cd jboss-eap-quickstarts/helloworld/
Tittar pÄ hur den ursprungliga helloworld fungerar
I grunden Àr syftet med denna applikation tydligt utifrÄn namnet, men vi kommer att modernisera dess kod strikt vetenskapligt. SÄ lÄt oss först titta pÄ denna applikation i sin ursprungliga form.
Starta helloworld
1. Ăppna terminalen och gĂ„ till roten av JBoss EAP-mappen (du kan ladda ner den ), det vill sĂ€ga i mappen EAP_HOME.
2. Starta JBoss EAP-servern med standardprofilen:
$ EAP_HOME/bin/standalone.sh
AnmÀrkning: för Windows anvÀnds skriptet EAP_HOMEbinstandalone.bat för att starta.
Efter nÄgra sekunder bör loggen visa ungefÀr följande:
[org.jboss.as] (Controller Boot Thread) WFLYSRV0025: JBoss EAP 7.2.0.GA (WildFly Core 6.0.11.Final-redhat-00001) startad pÄ 3315 ms - Startade 306 av 527 tjÀnster (321 tjÀnster Àr lata, passiva eller pÄ begÀran)
3. Ăppna i webblĂ€saren :8080 och vi ser detta:

Fig. 1. Startsidan för JBoss EAP.
4. Följ instruktionerna i guiden : vi kör igÄng helloworld och kör följande kommando (frÄn projektets rotmapp):
$ mvn clean install wildfly:deploy
Efter att kommandot har körts framgÄngsrikt ser vi ungefÀr följande i loggen:
[INFO] ------------------------------------------------------------------------
[INFO] BYGG SUCCĂ
[INFO] ------------------------------------------------------------------------
[INFO] Total tid: 8.224 s
SÄ första distributionen av helloworld-applikationen pÄ JBoss EAP tog lite mer Àn 8 sekunder.
Testar helloworld
Följ noggrant guiden , öppnar i webblÀsaren :8080/helloworld och ser detta:

Fig. 2. Ursprungligt Hello World frÄn JBoss EAP.
Gör Àndringar
Ăndrar inparametern createHelloMessage(String name) frĂ„n World till Marco:
writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");
Kör Äterigen följande kommando:
$ mvn clean install wildfly:deploy
Uppdaterar sedan sidan i webblÀsaren och ser att texten har Àndrats:

Fig. 3. Hello Marco i JBoss EAP.
à terstÀller distributionen av helloworld och avslutar JBoss EAP
Detta Àr valfritt, men om du vill ÄterstÀlla distributionen kan du göra det med följande kommando:
$ mvn clean install wildfly:undeploy
För att avsluta JBoss EAP-instansen, tryck bara Ctrl+C i terminalfönstret.
Uppgraderar helloworld
Nu ska vi modernisera den ursprungliga helloworld-applikationen.
Skapar en ny gren
Skapar en ny arbetsgren efter att projektet quickstart har slutförts:
$ git checkout -b quarkus 7.2.0.GA
Ăndrar filen pom.xml
Vi börjar Àndra applikationen med filen pom.xml. För att Quarkus ska kunna infoga XML-block i den, kör vi följande kommando i helloworld-mappen:
$ mvn io.quarkus:quarkus-maven-plugin:0.23.2:create
Vid tiden för att skriva denna artikel anvÀndes version 0.23.2. Quarkus uppdateras ofta med nya versioner, för att se vilken version som Àr den senaste kan du besöka .
OvanstÄende kommando kommer att infoga följande element i pom.xml:
- Egenskapen , som anger den version av Quarkus som anvÀnds.
- Blocket för att importera Quarkus BOM (bill of materials), sÄ att du inte behöver lÀgga till versionen för varje Quarkus-beroende.
- Plugin quarkus-maven-plugin, som ansvarar för att paketera applikationen och erbjuder utvecklingslÀge.
- Profilen native för att skapa körbara filer av applikationen.
Dessutom gör vi manuellt följande Àndringar i pom.xml:
- Flyttar taggen frÄn blocket och placerar den över taggen . Eftersom vi i nÀsta steg kommer att ta bort blocket , mÄste vi spara .
- Tar bort blocket , eftersom den hÀr applikationen inte lÀngre behöver en förÀldra-pom frÄn JBoss nÀr man arbetar med Quarkus.
- LĂ€gg till taggen och placera den under taggen . Versionsnumret kan anges som du vill.
- Ta bort taggen , eftersom denna applikation inte lÀngre Àr en WAR, utan en vanlig JAR.
- Modifiera följande beroenden:
- Byt ut beroendet javax.enterprise:cdi-api mot io.quarkus:quarkus-arc, ta bort provided, eftersom (enligt dokumentationen) detta Quarkus-tillÀgg tillhandahÄller CDI-beroendeinjektion.
- Byt ut beroendet org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec mot io.quarkus:quarkus-undertow, ta bort provided, eftersom (enligt dokumentationen) detta Quarkus-tillÀgg ger stöd för servlets.
- Ta bort beroendet org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec, eftersom det ingÄr i de beroenden vi just har Àndrat.
Versionen av filen pom.xml med alla förÀndringar finns pÄ adressen .
Observera att det ovanstÄende kommandot mvn io.quarkus:quarkus-maven-plugin:0.23.2:create inte bara Àndrar filen pom.xml, utan Àven lÀgger till en rad komponenter i projektet, nÀmligen följande filer och mappar:
- Filen mvnw och mvnw.cmd samt mappen .mvn: Maven Wrapper gör det möjligt att köra Maven-projekt i en viss version av Maven utan att installera den versionen.
- Mappen docker (i katalogen src/main/): hÀr finns exempel pÄ Dockerfile-filer för lÀgena native och jvm (tillsammans med filen .dockerignore).
- Mappen resources (i katalogen src/main/): hÀr finns en tom fil application.properties och ett exempel pÄ startsidan Quarkus index.html (se mer i avsnittet Kör den moderniserade helloworld).
Kör helloworld
För att testa applikationen anvÀnder vi quarkus:dev, som startar Quarkus i utvecklingslÀge (se mer i detta avsnitt i handboken för ).
AnmÀrkning: detta steg kommer förvÀntat att leda till ett fel, eftersom vi inte har gjort alla nödvÀndiga Àndringar Àn.
Nu kör vi kommandot för att se hur det fungerar:
$ .\/mvnw compile quarkus:dev
[INFO] Skanning av projekt...
[INFO]
[INFO] ----------------< org.jboss.eap.quickstarts:helloworld >----------------
[INFO] Bygger Quickstart: helloworld quarkus
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (standard-resurser) @ helloworld ---
[INFO] AnvÀnder 'UTF-8' kodning för att kopiera filtrerade resurser.
[INFO] Kopierar 2 resurser
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (standard-kompilering) @ helloworld ---
[INFO] Ingenting att kompilera - alla klasser Àr uppdaterade
[INFO]
[INFO] --- quarkus-maven-plugin:0.23.2:dev (standard-cli) @ helloworld ---
Lyssnar för transport dt_socket pÄ adress: 5005
INFO [io.qua.dep.QuarkusAugmentor] Börjar quarkus-augmentering
INFO [org.jbo.threads] JBoss Threads version 3.0.0.Final
ERROR [io.qua.dev.DevModeMain] Kunde inte starta quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Byggfel: Byggningen misslyckades pÄ grund av fel
[error]: Byggsteget io.quarkus.arc.deployment.ArcProcessor#validate kastade ett undantag: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: OtillfredsstÀlld beroende för typ org.jboss.as.quickstarts.helloworld.HelloService och kvalificerare [@Default]
- java-medlem: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService
- deklarerat pÄ CLASS-bean [typer=[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], kvalificerare=[@Default, @Any], mÄl=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)
Orsakat av: javax.enterprise.inject.UnsatisfiedResolutionException: OtillfredsstÀlld beroende för typ org.jboss.as.quickstarts.helloworld.HelloService och kvalificerare [@Default]
- java-medlem: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService
- deklarerat pÄ CLASS-bean [typer=[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], kvalificerare=[@Default, @Any], mÄl=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 mer
SÄ, det fungerar inte⊠Varför?
Undantaget UnsatisfiedResolutionException pekar pÄ klassen HelloService, som Àr en medlem av klassen HelloWorldServlet (java medlem: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). Problemet Àr att HelloWorldServlet behöver en injicerad instans av HelloService, men den gÄr inte att hitta (Àven om bÄda dessa klasser finns i samma paket).
Det Àr dags att ÄtervÀnda till och lÀsa om hur , och dÀrmed (CDI). SÄ vi öppnar manualen för Contexts and Dependency Injection och lÀser i avsnittet att: "En bean-klass som inte har nÄgon definierande bean-annotering söks inte."
Tittar pĂ„ klassen HelloService â den har faktiskt ingen sĂ„dan annotering. DĂ€rför mĂ„ste vi lĂ€gga till den sĂ„ att Quarkus kan söka och hitta bean. Eftersom detta Ă€r ett stateless-objekt kan vi helt enkelt lĂ€gga till annoteringen @ApplicationScoped pĂ„ följande sĂ€tt:
@ApplicationScoped
public class HelloService {
AnmÀrkning: hÀr kan utvecklingsmiljön be om att du lÀgger till den erforderliga paketet (se raden nedan), och detta mÄste göras manuellt, sÄ hÀr:
import javax.enterprise.context.ApplicationScoped;
Om du Àr osÀker pÄ vilken scope du ska anvÀnda nÀr den ursprungliga bean'en inte alls har definierats, studera dokumentationen .
Nu försöker vi igen att köra applikationen med kommandot .\/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]
Nu gÄr allt utan fel.
Vi kör den uppgraderade helloworld
Som angivet i loggen, öppnar vi i webblÀsaren :8080 (standard Quarkus start sida) och ser detta:

Fig. 4. Quarkus dev start sida.
I annoteringen WebServlet för denna applikation finns följande kontextdefinition:
@WebServlet("\/HelloWorld")
public class HelloWorldServlet extends HttpServlet {
DÀrför gÄr vi i webblÀsaren till :8080/HelloWorld och ser följande:

Fig. 5: The Quarkus dev-sidan för Hello World-applikationen.
Och sÄ hÀr, allt fungerar.
Nu gör vi Ă€ndringar i koden. Observera att kommandot ./mvnw compile quarkus:dev fortfarande fungerar, och vi tĂ€nker inte stoppa det. Nu ska vi försöka tillĂ€mpa samma â mycket triviala â Ă€ndringar pĂ„ sjĂ€lva koden och se hur Quarkus underlĂ€ttar livet för utvecklaren:
writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");
Vi sparar filen och uppdaterar sedan webbsidan för att se meddelandet Hello Marco, som visas pÄ skÀrmdumpen nedan:

Fig. 6. Sidan Hello Marco i Quarkus dev.
Nu kontrollerar vi utskriften i terminalen:
INFO [io.qua.dev] (vert.x-worker-thread-3) Ăndrade kĂ€llfiler upptĂ€ckta, kompilera om [/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 stoppades pÄ 0.003s
INFO [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) PÄbörjar quarkus-augmentation
INFO [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) Quarkus-augmentation slutförd pÄ 232ms
INFO [io.quarkus] (vert.x-worker-thread-3) Quarkus 0.23.2 startade pÄ 0.257s. Lyssnar pÄ: http://0.0.0.0:8080
INFO [io.quarkus] (vert.x-worker-thread-3) Profil dev aktiverad. Live Coding aktiverad.
INFO [io.quarkus] (vert.x-worker-thread-3) Installerade funktioner: [cdi]
INFO [io.qua.dev] (vert.x-worker-thread-3) Total tid för varm ersÀttning: 0.371s
Uppdateringen av sidan utlöste upptÀckten av Àndringar i kÀllkoden, och Quarkus utförde automatiskt proceduren "stop-start". Och allt det hÀr utfördes pÄ endast 0.371 sekunder (dÀr har ni, den "super-snabba subatomÀra Java").
Bygger helloworld till JAR-paket
Nu nÀr koden fungerar som den ska, paketerar vi den med följande kommando:
$ ./mvnw clean package
Detta kommando skapar tvĂ„ JAR-filer i mappen /target: filen helloworld-.jar, som Ă€r den standard artefakten som skapats av Maven-kommandot tillsammans med klasser och resurser frĂ„n projektet. Och filen helloworldârunner.jar, som Ă€r en körbar JAR.
Observera att detta inte Àr en uber-jar, eftersom alla beroenden bara kopieras till mappen /target/lib (och inte packas in i JAR-filen). DÀrför, för att köra denna JAR frÄn en annan mapp eller pÄ en annan vÀrd, mÄste bÄde JAR-filen och mappen /lib kopieras dit, med tanke pÄ att Class-Path-elementet i filen MANIFEST.MF i JAR-paketet innehÄller en explicit lista över JAR-filerna frÄn lib-mappen.
För att lÀra dig hur man skapar uber-jars, se guiden .
Kör helloworld paketerat i JAR
Nu kan vi köra vÄr JAR med det standardkommandot java:
$ java -jar ./target/helloworld--runner.jar
INFO [io.quarkus] (main) Quarkus 0.23.2 startade pÄ 0.673s. Lyssnar pÄ: http://0.0.0.0:8080
INFO [io.quarkus] (main) Profil prod aktiverad.
INFO [io.quarkus] (main) Installerade funktioner: [cdi]
NÀr allt detta har slutförts, gÄ in i din webblÀsare pÄ :8080 och kolla att allt fungerar som det ska.
Vi bygger helloworld till en inbyggd körbar fil
SÄ, vÄr helloworld fungerar som en fristÄende Java-applikation, med Quarkus beroenden. Men vi kan gÄ lÀngre och omvandla den till en inbyggd körbar fil.
Vi installerar GraalVM
Först mÄste vi installera de nödvÀndiga verktygen:
1. Ladda ner GraalVM 19.2.0.1 frÄn .
2. Packa upp den nedladdade arkivet:
$ tar xvzf graalvm-ce-linux-amd64-19.2.0.1.tar.gz
3. GĂ„ till untar-mappen.
4. Kör kommandot nedan för att ladda ner och lÀgga till den inbyggda bilden:
$ ./bin/gu install native-image
5. Skriv mappen som skapades i steg 2 i miljövariabeln GRAALVM_HOME:
$ export GRAALVM_HOME={untar-folder}/graalvm-ce-19.2.0.1)
Ytterligare information och installationsinstruktioner för andra OS kan hittas i guiden .
Vi bygger helloworld till en inbyggd körbar fil
LÀs guiden : "Och nu ska vi skapa en inbyggd körbar fil för vÄr applikation, för att minska uppstartstiden och storleken pÄ disken. Den körbara filen kommer att ha allt som behövs för att köra applikationen, inklusive JVM-maskinen (snarare dess nedskurna version som endast innehÄller det som krÀvs för att köra applikationen) och sjÀlva vÄr applikation."
För att skapa en inbyggd körbar fil mÄste vi aktivera native-profilen i Maven:
$ ./mvnw package -Pnative
VÄr byggning tog en minut och 10 sekunder, och den slutgiltiga filen helloworld-runner skapades i mappen /target.
Vi kör den inbyggda körbara filen helloworld
I det föregÄende steget fick vi den körbara filen /target/helloworld-runner. Nu kör vi den:
$ ./target/helloworld--runner
INFO [io.quarkus] (main) Quarkus 0.23.2 startade pÄ 0.006s. Lyssnar pÄ: http://0.0.0.0:8080
INFO [io.quarkus] (main) Profil prod aktiverad.
INFO [io.quarkus] (main) Installerade funktioner: [cdi]
Ăppna igen i webblĂ€saren :8080 och kontrollera att allt fungerar som det ska.
FortsÀttning följer!
Vi anser att metoden för att modernisera Java-applikationer med hjÀlp av Quarkus, som diskuterats i detta inlÀgg (Àven om den Àr baserad pÄ ett enkelt exempel), bör tillÀmpas aktivt i verkliga livet. Du kommer troligtvis att stöta pÄ en rad problem, vars lösningar vi delvis kommer att ta upp i nÀsta inlÀgg, dÀr vi kommer att diskutera hur man mÀter minnesanvÀndningen för att utvÀrdera prestandaförbÀttringar, en viktig del av hela moderniseringsprocessen för applikationer.
KĂ€lla: habr.com
