Quarkus: peningkatan aplikasi menggunakan contoh helloworld dari JBoss EAP Quickstart

Halo semuanya di blog ini, dan bersama Anda pos keempat dari seri Quarkus! (Ngomong-ngomong, daftarkan dan buka webinar kami “ Ini adalah Quarkus - kerangka kerja asli Jawa Kubernetes ”, yang akan diadakan pada tanggal 27 Mei. Kami akan menunjukkan bagaimana memulai dari awal atau mentransfer solusi yang sudah jadi)



Posting sebelumnya adalah tentang bagaimana Quarkus menggabungkan MicroProfile dan Spring. Ingat bahwa Quarkus diposisikan sebagai “Java subatomik ultra cepat”, ini adalah “Java-stack yang berorientasi Kubernet, dipertajam oleh GraalVM dan OpenJDK HotSpot dan disusun dari perpustakaan dan standar terbaik.” Hari ini kami menunjukkan cara meningkatkan aplikasi Java yang ada menggunakan fitur Quarkus menggunakan aplikasi helloworld dari repositori QuickStart JBoss Enterprise Application Platform (JBoss EAP).menggunakan teknologi CDI dan Servlet 3 yang didukung oleh Quarkus.

Penting untuk dicatat di sini bahwa Quarkus dan JBoss EAP fokus pada penggunaan alat yang dibangun dengan standar maksimum. Tidak memiliki aplikasi yang berjalan di JBoss EAP? Bukan masalah, itu dapat dengan mudah dimigrasikan dari server aplikasi saat ini ke JBoss EAP menggunakan Red Hat Application Migration Toolkit . Setelah itu, versi terakhir dan yang berfungsi dari kode yang ditingkatkan akan tersedia di github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus repository , dalam modul helloworld .

Posting ini ditulis menggunakan tutorial Quarkus , terutama Membuat Aplikasi Pertama Anda dan Membangun yang Asli Dapat Dieksekusi .

Kami mendapat kode


Pertama, buat klon lokal dari repositori quickstarts JBoss EAP :

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

Lihat cara kerja helloworld asli


Sebenarnya, esensi dari aplikasi ini jelas dari namanya, tetapi kami akan memutakhirkan kodenya secara ilmiah. Karena itu, untuk mulai dengan, lihat aplikasi ini dalam bentuk aslinya.

Expand helloworld

1. Buka terminal dan pergi ke root folder JBoss EAP (Anda dapat mengunduhnya di sini ), yaitu, ke dalam folder EAP_HOME.

2. Mulai server JBoss EAP dengan profil default:

$ EAP_HOME/bin/standalone.sh

Catatan: pada Windows, skrip EAP_HOME \ bin \ standalone.bat digunakan untuk menjalankan.

Setelah beberapa detik, yang berikut akan muncul di log:

[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. Buka browser 127.0.0.1 : 8080 dan lihat ini:



Ara. 1. Beranda JBoss EAP.

4. Ikuti instruksi dalam panduan Membangun dan Menyebarkan Quickstart : gunakan helloworld dan jalankan (dari folder root proyek) perintah berikut:

$ mvn clean install wildfly:deploy

Setelah berhasil mengeksekusi perintah ini di log, kita akan melihat sesuatu seperti berikut:

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

Jadi, penyebaran pertama aplikasi helloworld di JBoss EAP hanya membutuhkan waktu lebih dari 8 detik.

Kami menguji helloworld

Bertindak secara ketat sesuai dengan panduan Access the Application , buka 127.0.0.1 : 8080 / helloworld di browser dan lihat ini:



Ara. 2. Hello World Asli dari JBoss EAP.

Lakukan perubahan

Ubah parameter input createHelloMessage (Nama string) dari Dunia ke Marco:

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

Sekali lagi, jalankan perintah berikut:

$ mvn clean install wildfly:deploy

Kemudian kami menyegarkan halaman di browser dan melihat bahwa teks telah berubah:



Ara. 3. Halo Marco di JBoss EAP.

Kami memutar kembali penyebaran helloworld dan keluar dari JBoss EAP.

Ini opsional, tetapi jika Anda ingin membatalkan penyebaran, Anda bisa melakukan ini dengan perintah berikut:

$ mvn clean install wildfly:undeploy

Untuk mematikan instance JBoss EAP, cukup tekan Ctrl + C di jendela terminal.

Memutakhirkan helloworld


Sekarang mari kita tingkatkan aplikasi asli helloworld.

Buat cabang baru

Buat cabang kerja baru setelah proyek quickstart selesai:

$ git checkout -b quarkus 7.2.0.GA

Mengubah file pom.xml

Kami akan mulai mengubah aplikasi dari file pom.xml. Agar Quarkus dapat menyisipkan blok XML ke dalamnya, jalankan perintah berikut di folder helloworld:

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

Saat menulis artikel ini, versi 0.23.2 digunakan. Quarkus sering memiliki versi baru, Anda dapat mengetahui versi mana yang terbaru di github.com/quarkusio/quarkus/releases/latest .

Perintah di atas akan memasukkan elemen-elemen berikut ke pom.xml:

  • Properti <quarkus.version> yang menentukan versi Quarkus untuk digunakan.
  • Blok <dependencyManagement> untuk mengimpor Quarkus BOM (bill of material) agar tidak menambahkan versi untuk setiap ketergantungan Quarkus.
  • Plugin quarkus-maven-plugin, yang bertanggung jawab untuk mengemas aplikasi dan menyediakan mode pengembangan.
  • Profil asli untuk membuat aplikasi yang dapat dieksekusi.

Selain itu, kami secara manual membuat perubahan berikut ke pom.xml:

  1. <groupId> <parent> <artifactId>. <parent>, <groupId>.
  2. <parent>, Quarkus pom JBoss.
  3. <version> <artifactId>. .
  4. <packaging>, WAR, JAR.
  5. :
    1. javax.enterprise:cdi-api io.quarkus:quarkus-arc, <scope>provided</scope>, ( ) Quarkus- injection CDI.
    2. Kami mengubah dependensi org.jboss.spec.javax.servlet: jboss-servlet-api_4.0_spec ke io.quarkus: quarkus-undertow, menghapus <scope> disediakan </scope>, karena (sesuai dengan dermaga) ekstensi Quarkus ini menyediakan dukungan untuk servlet ini
    3. Kami menghapus dependensi org.jboss.spec.javax.annot: jboss-annotations-api_1.3_spec, karena mereka datang dengan dependensi yang baru saja kami ubah.


Versi file pom.xml dengan semua perubahan ada di github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml .

Harap perhatikan bahwa mvn io.quarkus di atas: quarkus-maven-plugin: 0.23.2: membuat perintah tidak hanya mengubah file pom.xml, tetapi juga menambahkan sejumlah komponen ke proyek, yaitu file dan folder berikut:

  • mvnw and mvnw.cmd .mvn: Maven Wrapper Maven Maven .
  • docker ( src/main/): Dockerfile native jvm ( .dockerignore).
  • resources ( src/main/): application.properties Quarkus index.html ( . Run the modernized helloworld ).

Kami mulai helloworld
Untuk menguji aplikasi, kami menggunakan quarkus: dev, yang memulai Quarkus dalam mode pengembangan (untuk lebih jelasnya lihat bagian ini di manual Mode Pengembangan ).

Catatan: langkah ini diharapkan menghasilkan kesalahan, karena kami belum melakukan semua perubahan yang diperlukan.

Sekarang jalankan perintah untuk memeriksa cara kerjanya:

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

Jadi, itu tidak berhasil ... Dan mengapa?

Pengecualian UnsatisfiedResolutionException menunjuk ke kelas HelloService, yang merupakan anggota kelas HelloWorldServlet (anggota java: org.jboss.as.quickstarts.helloworld.HelloWorldServlet # helloService). Masalahnya adalah HelloWorldServlet membutuhkan instance HelloService yang disuntikkan, tetapi tidak dapat ditemukan (meskipun kedua kelas ini berada dalam paket yang sama).

Sudah waktunya untuk kembali ke dokumentasi dan membaca cara kerja QuarkusMenyuntikkandan karenanya Konteks dan Injeksi Ketergantungan (CDI). Oleh karena itu, kami membuka panduan Contexts and Dependency Injection dan membaca di bagian Bean Discovery : “Kelas kacang yang tidak memiliki anotasi yang mendefinisikan kacang tidak dicari.”

Kami melihat kelas HelloService - itu benar-benar tidak memiliki penjelasan seperti itu. Karena itu, harus ditambahkan agar Quarkus dapat mencari dan menemukan kacang. Dan karena ini adalah objek stateless, kita bisa menambahkan penjelasan @ApplicationScoped sebagai berikut:

@ApplicationScoped
public class HelloService {

Catatan: di sini lingkungan pengembangan mungkin meminta Anda untuk menambahkan paket yang diperlukan (lihat baris di bawah), dan ini harus dilakukan secara manual, seperti ini:

import javax.enterprise.context.ApplicationScoped;

Jika ragu ruang lingkup mana yang harus digunakan ketika sumber kacang tidak disetel sama sekali, periksa dokumentasi JSR 365: Konteks dan Injeksi Ketergantungan untuk Java 2.0 - Ruang lingkup default .

Sekarang lagi, kami mencoba untuk memulai aplikasi dengan perintah ./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]

Sekarang semuanya berjalan tanpa kesalahan.

Kami meluncurkan helloworld yang ditingkatkan
Seperti yang tertulis dalam log, buka di browser 0.0.0.0 : 8080 (halaman awal Quarkus default) dan lihat ini:



Ara. 4. Halaman awal Quarkus dev.

Anotasi WebServlet untuk aplikasi ini memiliki definisi konteks berikut:

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

Oleh karena itu, kita masuk ke 0.0.0.0 : 8080 / HelloWorld di browser dan melihat yang berikut:



Ara. 5: Halaman dev Quarkus untuk aplikasi Hello World.

Semuanya bekerja.

Dan sekarang kami membuat perubahan pada kode. Perhatikan bahwa perintah ./mvnw kompilasi quarkus: dev masih berfungsi dan kami tidak akan menghentikannya. Sekarang mari kita coba menerapkan hal yang sama - sepele - perubahan pada kode itu sendiri dan melihat bagaimana Quarkus membuat hidup lebih mudah bagi pengembang:

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

Simpan file dan kemudian segarkan halaman web untuk melihat Halo Marco, seperti yang ditunjukkan pada tangkapan layar di bawah ini:



Ara. 6. Halo halaman Marco di Quarkus dev.

Sekarang periksa output di 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

Refresh halaman memicu deteksi perubahan dalam kode sumber, dan Quarkus secara otomatis melakukan prosedur "stop start". Dan semua ini selesai hanya dalam 0,371 detik (ini dia, "subatomic Java yang sangat cepat").

Kami membangun helloworld menjadi paket JAR
Sekarang setelah kode berfungsi sebagaimana mestinya, kami kemas dengan perintah berikut:

$ ./mvnw clean package

Perintah ini membuat dua file JAR di folder / target: file helloworld-.jar, yang merupakan artefak standar yang dirakit oleh tim Maven bersama dengan kelas dan sumber daya proyek. Dan file helloworld adalah runner.jar, yang merupakan JAR yang dapat dieksekusi.

Perhatikan bahwa ini bukan tabung-uber, karena semua dependensi hanya disalin ke folder / target / lib (dan tidak dikemas ke file JAR). Oleh karena itu, untuk menjalankan JAR ini dari folder lain atau pada host yang berbeda, Anda perlu menyalin file JAR dan folder / lib di sana, mengingat bahwa elemen Path-Kelas dalam file MANIFEST.MF dalam paket JAR berisi daftar eksplisit JAR dari folder lib.
Untuk mempelajari cara membuat aplikasi uber-jar, lihat tutorial Pembuatan Uber-Jar .

Luncurkan helloworld, dikemas dalam JAR

Sekarang Anda dapat menjalankan JAR kami menggunakan perintah java standar:

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

Setelah semua ini selesai, buka browser di 0.0.0.0 : 8080 dan periksa apakah semuanya berfungsi sebagaimana mestinya.

Menempatkan helloworld ke dalam executable asli

Jadi, helloworld kami berfungsi sebagai aplikasi Java mandiri menggunakan dependensi Quarkus. Tapi Anda bisa melangkah lebih jauh dan mengubahnya menjadi file yang dapat dieksekusi asli.

Instal GraalVM
Pertama-tama, untuk ini Anda harus menginstal alat yang diperlukan:

1. Unduh GraalVM 19.2.0.1 dari github.com/oracle/graal/releases/tag/vm-19.2.0.1 .

2. Perluas arsip yang diunduh:

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

3. Buka folder untar.

4. Jalankan perintah di bawah ini untuk mengunduh dan menambahkan gambar asli:

$ ./bin/gu install native-image

5. Kami mendaftarkan folder yang dibuat pada langkah 2 ke dalam variabel lingkungan GRAALVM_HOME:

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

Untuk informasi lebih lanjut dan instruksi pemasangan pada sistem operasi lain, lihat Membangun Native Executable - Prasyarat .

Bangun helloworld menjadi executable asli.
Baca Building a Native Executable - Menghasilkan manual executable asli : "Sekarang buat executable asli untuk aplikasi kami untuk mengurangi waktu startup dan ukuran disk. File yang dapat dieksekusi akan memiliki semua yang diperlukan untuk menjalankan aplikasi, termasuk mesin JVM (atau lebih tepatnya, versi terpotongnya, hanya berisi apa yang diperlukan untuk menjalankan aplikasi) dan aplikasi kita sendiri. "

Untuk membuat executable asli, Anda harus mengaktifkan profil asli Maven:

$ ./mvnw package -Pnative

Perakitan kami membutuhkan waktu satu menit dan 10 detik, dan file final helloworld - pelari f dibuat di folder / target.

Kami memulai file executable asli helloworld

Pada langkah sebelumnya kami mendapatkan file executable / target / helloworld - runner. Sekarang jalankan:

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

Sekali lagi, buka browser 0.0.0.0 : 8080 dan periksa apakah semuanya berfungsi sebagaimana mestinya.

Bersambung!

Kami percaya bahwa metode modernisasi aplikasi Java menggunakan kemampuan Quarkus dipertimbangkan dalam posting ini (meskipun dengan contoh paling sederhana) harus diterapkan secara aktif dalam kehidupan nyata. Dalam hal ini, Anda kemungkinan akan menghadapi sejumlah masalah, solusinya yang akan kita pertimbangkan sebagian pada posting berikutnya, yang akan fokus pada bagaimana mengukur konsumsi memori untuk mengevaluasi peningkatan kinerja, bagian penting dari keseluruhan proses modernisasi aplikasi.

All Articles