Sveiki visi šiame tinklaraštyje, štai ketvirtasis Quarkus serijos įrašas!

buvo apie tai, kaip Quarkus sujungia MicroProfile ir Spring. Leiskite jums tai priminti yra „itin greita subatominė Java“, dar žinoma kaip „į Kubernetes orientuotas Java dėklas, pritaikytas GraalVM ir OpenJDK HotSpot ir surinktas iš geriausių bibliotekų ir standartų“. Šiandien mes parodysime, kaip modernizuoti esamas Java programas naudojant Quarkus galimybes, naudojant pavyzdį , kuri naudoja CDI ir Servlet 3 technologijas, kurias palaiko Quarkus.
Čia svarbu pažymėti, kad tiek „Quarkus“, tiek „JBoss EAP“ pabrėžia, kad naudojami kiek įmanoma standartais pagrįsti įrankiai. Neturite programos, veikiančios JBoss EAP? Jokių problemų, jį galima lengvai perkelti iš dabartinio taikomųjų programų serverio į JBoss EAP naudojant . Po to saugykloje bus pasiekiama galutinė ir darbinė modernizuoto kodo versija , modulyje .
Rašydami šį įrašą naudojome , dažniausiai ir A pastatas .
Paimkime kodą
Pirmiausia sukurkime vietinį saugyklos kloną :
$ 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/
Pažiūrėkime, kaip veikia originalus helloworld
Tiesą sakant, šios programos esmė yra aiški iš pavadinimo, tačiau mes modernizuosime jos kodą griežtai moksliškai. Todėl pirmiausia pažvelkime į šią programą originalia forma.
Helloworld diegimas
1. Atidarykite terminalą ir eikite į JBoss EAP aplanko šaknį (galite jį atsisiųsti ), ty į aplanką EAP_HOME.
2. Paleiskite JBoss EAP serverį naudodami numatytąjį profilį:
$ EAP_HOME/bin/standalone.sh
Pastaba: apie Windows Paleidimui naudojamas scenarijus EAP_HOMEbinstandalone.bat.
Po kelių sekundžių žurnale turėtų pasirodyti kažkas panašaus:
[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. Atidarykite naršyklėje :8080 ir matome tai:

Ryžiai. 1. JBoss EAP pagrindinis puslapis.
4. Vykdykite vadove pateiktas instrukcijas : išplėskite helloworld ir paleiskite (iš projekto šakninio aplanko) šią komandą:
$ mvn clean install wildfly:deploy
Sėkmingai įvykdę šią komandą, žurnale pamatysime kažką panašaus į šį:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.224 s
Taigi pirmasis helloworld programos diegimas JBoss EAP užtruko kiek daugiau nei 8 sekundes.
„Helloworld“ testavimas
Veikia griežtai pagal instrukcijas , atidarykite naršyklėje :8080/helloworld ir matome tai:

Ryžiai. 2. Originalus Hello World iš JBoss EAP.
Pakeitimų darymas
Pakeiskite įvesties parametrą createHelloMessage(String name) iš Pasaulis į Marco:
writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");
Dar kartą paleiskite šią komandą:
$ mvn clean install wildfly:deploy
Tada atnaujiname puslapį naršyklėje ir matome, kad tekstas pasikeitė:

Ryžiai. 3. Sveiki, Marco, JBoss EAP.
Grąžinkite „helloworld“ diegimą ir išjunkite „JBoss EAP“.
Tai neprivaloma, bet jei norite atšaukti diegimą, galite tai padaryti naudodami šią komandą:
$ mvn clean install wildfly:undeploy
Norėdami išjungti JBoss EAP egzempliorių, tiesiog paspauskite Ctrl+C terminalo lange.
„helloworld“ atnaujinimas
Dabar modernizuokime originalią „helloworld“ programą.
Sukurkite naują filialą
Užbaigus greitosios pradžios projektą sukuriame naują darbo šaką:
$ git checkout -b quarkus 7.2.0.GA
Keisti pom.xml failą
Mes pradėsime keisti programą nuo pom.xml failo. Norėdami leisti Quarkus įterpti XML blokus, aplanke helloworld paleiskite šią komandą:
$ mvn io.quarkus:quarkus-maven-plugin:0.23.2:create
Rašant šį straipsnį buvo naudojama 0.23.2 versija. Quarkus dažnai išleidžia naujas versijas, kuri yra naujausia, galite sužinoti svetainėje .
Aukščiau pateikta komanda į pom.xml įterps šiuos elementus:
- Nuosavybė , kuriame nurodoma naudotina Quarkus versija.
- Blokuoti importuoti Quarkus BOM (medžiagų sąskaitą), kad nebūtų pridėta kiekvienos Quarkus priklausomybės versija.
- „Quarkus-maven-plugin“ yra atsakingas už programos supakavimą ir kūrimo režimo teikimą.
- Vietinis profilis, skirtas programos vykdomiesiems failams kurti.
Be to, rankiniu būdu atliekame šiuos pom.xml pakeitimus:
- Ištraukiant etiketę nuo bloko ir padėkite virš žymos . Nes kitame žingsnyje bloką pašalinsime , tada reikia išsaugoti .
- Bloko pašalinimas , nes kai paleisite su Quarkus, šiai programai nebereikės pirminio JBoss pom.
- Pridėkite žymą ir padėkite po žyma . Galite nurodyti norimą versijos numerį.
- Žymės pašalinimas , nes ši programa nebėra WAR, o įprasta JAR.
- Mes keičiame šias priklausomybes:
- Pakeiskite priklausomybę javax.enterprise:cdi-api į io.quarkus:quarkus-arc, pašalinkite jeigu , nes (pagal dokumentus) šis Quarkus plėtinys suteikia CDI priklausomybių injekciją.
- Pakeiskite priklausomybę org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec į io.quarkus:quarkus-undertow, pašalinama jeigu , nes (pagal dokumentus) šis Quarkus plėtinys palaiko servletus.
- Pašaliname org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec priklausomybę, nes ji pateikiama kartu su priklausomybėmis, kurias ką tik pakeitėme.
Pom.xml failo versija su visais pakeitimais yra adresu .
Atminkite, kad aukščiau pateikta komanda mvn io.quarkus:quarkus-maven-plugin:0.23.2:create ne tik pakeičia pom.xml failą, bet ir prideda prie projekto komponentų, būtent šiuos failus ir aplankus:
- Failai mvnw ir mvnw.cmd bei .mvn aplankas: „Maven Wrapper“ leidžia paleisti tam tikros „Maven“ versijos „Maven“ projektus tos versijos neįdiegę.
- Docker aplankas (kataloge src/main/): jame yra pavyzdiniai Docker failai, skirti vietiniams ir jvm režimams (kartu su .dockerignore failu).
- Aplankas Resources (kataloge src/main/): jame yra tuščias application.properties failas ir pavyzdinis Quarkus index.html pradžios puslapis (daugiau informacijos žr. Paleisti modernizuotą helloworld).
Paleiskite helloworld
Norėdami išbandyti programą, naudojame quarkus:dev, kuris paleidžia Quarkus kūrimo režimu (daugiau informacijos rasite šiame vadovo skyriuje ).
Pastaba: Tikimasi, kad šis veiksmas sukels klaidą, nes dar neatlikome visų būtinų pakeitimų.
Dabar paleiskite komandą, kad pamatytumėte, kaip ji veikia:
$ ./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
Taigi, tai neveikia... Kodėl?
UnsatisfiedResolutionException nurodo HelloService klasę, kuri yra HelloWorldServlet klasės narė (java narys: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). Problema ta, kad HelloWorldServlet reikia įterpto HelloService egzemplioriaus ir jo nepavyksta rasti (net jei abi šios klasės yra tame pačiame pakete).
Atėjo laikas grįžti prie ir skaitykite, kaip tai veikia Quarkus , ir todėl (CDI). Todėl atidarykite kontekstų ir priklausomybės įvedimo vadovą ir skyriuje skaitome: „Pupelių klasė, kurioje nėra pupelių apibrėžimo anotacijos, neieškoma“.
Pažiūrėkime į HelloService klasę – joje tokios anotacijos tikrai nėra. Todėl jis turi būti pridėtas, kad Quarkus galėtų ieškoti ir rasti pupelę. Ir kadangi tai yra objektas be būsenos, galime lengvai pridėti @ApplicationScoped anotaciją taip:
@ApplicationScoped
public class HelloService {
Pastaba: čia kūrimo aplinka gali paprašyti pridėti reikiamą paketą (žr. žemiau esančią eilutę), ir jūs turėsite tai padaryti rankiniu būdu, pavyzdžiui:
import javax.enterprise.context.ApplicationScoped;
Jei abejojate, kurią taikymo sritį reikėtų naudoti tuo atveju, kai šaltinio pupelei ji visai nenurodyta, perskaitykite dokumentaciją .
Dabar vėl bandome paleisti programą naudodami komandą ./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]
Dabar viskas vyksta be klaidų.
Modernizuoto „helloworld“ paleidimas
Kaip parašyta žurnale, atidarykite jį naršyklėje :8080 (numatytasis Quarkus pradžios puslapis) ir matome tai:

Ryžiai. 4. Quarkus dev pradžios puslapis.
Šios programos „WebServlet“ anotacijoje yra toks konteksto apibrėžimas:
@WebServlet("/HelloWorld")
public class HelloWorldServlet extends HttpServlet {
Todėl mes einame į naršyklę į :8080/HelloWorld ir matome:

Ryžiai. 5: „Hello World“ programos „Quarkus“ kūrėjo puslapis.
Na viskas veikia.
Dabar pakeiskime kodą. Atminkite, kad komanda ./mvnw kompiliuoti quarkus:dev vis dar veikia ir mes neketiname jos sustabdyti. Dabar pabandykime pritaikyti tuos pačius – labai nereikšmingus – pakeitimus pačiam kode ir pažiūrėkime, kaip „Quarkus“ palengvina kūrėjo gyvenimą:
writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");
Išsaugokite failą ir atnaujinkite tinklalapį, kad pamatytumėte Hello Marco, kaip parodyta toliau esančioje ekrano kopijoje:

Ryžiai. 6. Sveiki Marco puslapis Quarkus dev.
Dabar patikrinkime terminalo išvestį:
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
Puslapio atnaujinimas suaktyvino šaltinio kodo pakeitimų aptikimą, o Quarkus automatiškai atliko sustabdymo-paleidimo procedūrą. Ir visa tai buvo atlikta vos per 0.371 sekundės (čia yra ta „itin greita subatominė Java“).
Helloworldo kūrimas į JAR paketą
Dabar, kai kodas veikia taip, kaip turėtų, supakuokite jį naudodami šią komandą:
$ ./mvnw clean package
Ši komanda sukuria du JAR failus aplanke /target: failą helloworld-.jar, kuris yra standartinis artefaktas, kurį surinko Maven komanda kartu su projekto klasėmis ir ištekliais. Ir helloworld-runner.jar failas, kuris yra vykdomasis JAR.
Atminkite, kad tai nėra „uber-jar“, nes visos priklausomybės tiesiog nukopijuojamos į aplanką /target/lib (nesupakuotos į JAR failą). Todėl, norėdami paleisti šį JAR iš kito aplanko arba kitame pagrindiniame kompiuteryje, turite nukopijuoti ir patį JAR failą, ir /lib aplanką, atsižvelgiant į tai, kad JAR paketo MANIFEST.MF failo elemente Class-Path yra aiškus JAR sąrašas iš lib aplankų
Norėdami sužinoti, kaip kurti „uber-jar“ programas, žr. mokymo programą .
Paleiskite helloworld supakuotą JAR
Dabar galime paleisti savo JAR naudodami standartinę java komandą:
$ 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]
Kai visa tai atliksite, eikite į savo naršyklę adresu :8080 ir patikrinkite, ar viskas veikia taip, kaip turėtų.
Helloworld kompiliavimas į vietinį vykdomąjį failą
Taigi mūsų „helloworld“ veikia kaip atskira „Java“ programa, naudojanti „Quarkus“ priklausomybes. Bet galite eiti toliau ir paversti jį vietiniu vykdomuoju failu.
GraalVM diegimas
Visų pirma, tam turite įdiegti reikiamus įrankius:
1. Atsisiųskite GraalVM 19.2.0.1 iš .
2. Išplėskite atsisiųstą archyvą:
$ tar xvzf graalvm-ce-linux-amd64-19.2.0.1.tar.gz
3. Eikite į aplanką untar.
4. Vykdykite toliau pateiktą komandą, kad atsisiųstumėte ir pridėtumėte savąjį vaizdą:
$ ./bin/gu install native-image
5. Užregistruokite 2 veiksme sukurtą aplanką GRAALVM_HOME aplinkos kintamajame:
$ export GRAALVM_HOME={untar-folder}/graalvm-ce-19.2.0.1)
Daugiau informacijos ir diegimo instrukcijų kitose OS rasite vadove .
Helloworld kūrimas į vietinį vykdomąjį failą
Skaitant vadovą : „Dabar sukurkime savo programos vykdomąjį failą, kad sumažintume jos paleidimo laiką ir disko dydį. Vykdomajame faile bus viskas, ko reikia programai paleisti, įskaitant JVM (tiksliau, sutrumpintą jos versiją, kurioje yra tik tai, kas reikalinga programai paleisti) ir pačią mūsų programą.
Norėdami sukurti vietinį vykdomąjį failą, turite įjungti vietinį Maven profilį:
$ ./mvnw package -Pnative
Mūsų kūrimas užtruko vieną minutę ir 10 sekundžių, o paskutinis helloworld-runner f failas buvo sukurtas aplanke /target.
Paleiskite vietinį vykdomąjį failą helloworld
Ankstesniame veiksme gavome vykdomąjį failą /target/helloworld—runner. Dabar paleiskite jį:
$ ./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]
Dar kartą atidarykite jį naršyklėje :8080 ir patikrinkite, ar viskas veikia taip, kaip turėtų.
Tęsinys!
Manome, kad šiame įraše aptartas Java programų modernizavimo metodas naudojant Quarkus galimybes (nors ir naudojant paprastą pavyzdį) turėtų būti aktyviai naudojamas realiame gyvenime. Tai darydami greičiausiai susidursite su daugybe problemų, kurias iš dalies išspręsime kitame įraše, kuriame kalbėsime apie tai, kaip išmatuoti atminties suvartojimą, kad būtų galima įvertinti našumo patobulinimus – svarbią viso taikomųjų programų modernizavimo proceso dalį.
Šaltinis: www.habr.com
