Halo semuanya di blog ini, inilah postingan keempat dalam seri Quarkus!

adalah tentang bagaimana Quarkus menggabungkan MicroProfile dan Spring. Izinkan kami mengingatkan Anda akan hal itu diposisikan sebagai “Java subatomik ultra-cepat”, alias “tumpukan Java berorientasi Kubernetes, disesuaikan untuk GraalVM dan OpenJDK HotSpot dan dirakit dari perpustakaan dan standar terbaik.” Hari ini kami akan menunjukkan cara memodernisasi aplikasi Java yang ada menggunakan kemampuan Quarkus, dengan menggunakan sebuah contoh , yang menggunakan teknologi CDI dan Servlet 3 yang didukung oleh Quarkus.
Penting untuk dicatat di sini bahwa Quarkus dan JBoss EAP menekankan penggunaan alat yang berbasis standar mungkin. Tidak memiliki aplikasi yang berjalan di JBoss EAP? Tidak masalah, ini dapat dengan mudah dimigrasikan dari server aplikasi Anda saat ini ke JBoss EAP menggunakan . Setelah itu, versi final dan berfungsi dari kode yang dimodernisasi akan tersedia di repositori , dalam modul .
Saat menulis posting ini kami menggunakan , kebanyakan dan Gedung a .
Ayo ambil kodenya
Pertama-tama, mari kita buat tiruan lokal dari repositori :
$ 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/
Mari kita lihat cara kerja helloworld yang asli
Sebenarnya inti dari aplikasi ini sudah jelas dari namanya, namun kami akan memodernisasi kodenya secara ilmiah. Oleh karena itu, mari kita lihat dulu aplikasi ini dalam bentuk aslinya.
Menyebarkan helloworld
1. Buka terminal dan masuk ke root folder JBoss EAP (Anda dapat mendownloadnya ), yaitu ke folder EAP_HOME.
2. Luncurkan server JBoss EAP dengan profil default:
$ EAP_HOME/bin/standalone.sh
Catatan: pada Windows Skrip EAP_HOMEbinstandalone.bat digunakan untuk menjalankan program.
Setelah beberapa detik, sesuatu seperti ini 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 di browser :8080 dan kita melihat ini:

Beras. 1. Halaman Beranda JBoss EAP.
4. Ikuti petunjuk di manual : perluas helloworld dan jalankan (dari folder root proyek) perintah berikut:
$ mvn clean install wildfly:deploy
Setelah berhasil menjalankan perintah ini, kita akan melihat sesuatu seperti berikut di log:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.224 s
Jadi, penerapan pertama aplikasi helloworld di JBoss EAP hanya membutuhkan waktu 8 detik.
Menguji helloworld
Bertindak tegas sesuai instruksi , buka di browser :8080/helloworld dan kita melihat ini:

Beras. 2. Halo Dunia Asli dari JBoss EAP.
Membuat perubahan
Ubah parameter input createHelloMessage(String name) dari World menjadi Marco:
writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");
Jalankan kembali perintah berikut:
$ mvn clean install wildfly:deploy
Kemudian kami menyegarkan halaman di browser dan melihat bahwa teks telah berubah:

Beras. 3. Halo Marco di JBoss EAP.
Kembalikan penerapan helloworld dan matikan JBoss EAP
Ini opsional, namun jika Anda ingin membatalkan penerapan, Anda dapat melakukannya dengan perintah berikut:
$ mvn clean install wildfly:undeploy
Untuk mematikan instance JBoss EAP Anda, cukup tekan Ctrl+C di jendela terminal.
Meningkatkan helloworld
Sekarang mari kita modernkan aplikasi helloworld yang asli.
Buat cabang baru
Kami membuat 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. Untuk mengizinkan Quarkus memasukkan 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 mengeluarkan versi baru, Anda dapat mengetahui versi terbaru di website .
Perintah di atas akan memasukkan elemen berikut ke pom.xml:
- Properti , yang menentukan versi Quarkus yang akan digunakan.
- Memblokir untuk mengimpor Quarkus BOM (bill of material), agar tidak menambahkan versi untuk setiap ketergantungan Quarkus.
- Plugin quarkus-maven bertanggung jawab untuk mengemas aplikasi dan menyediakan mode pengembangan.
- Profil asli untuk membuat aplikasi yang dapat dieksekusi.
Selain itu, kami secara manual melakukan perubahan berikut pada pom.xml:
- Menarik keluar labelnya dari blok dan letakkan di atas tag . Karena pada langkah selanjutnya kita akan menghapus blok tersebut , maka Anda perlu menyimpan .
- Menghapus satu blok , karena jika dijalankan dengan Quarkus, aplikasi ini tidak memerlukan lagi pom induk dari JBoss.
- Tambahkan tanda dan letakkan di bawah tag . Anda dapat menentukan nomor versi yang Anda inginkan.
- Menghapus tag , karena aplikasi ini bukan lagi WAR, melainkan JAR biasa.
- Kami memodifikasi dependensi berikut:
- Ubah ketergantungan javax.enterprise:cdi-api menjadi io.quarkus:quarkus-arc, hapus asalkan , karena (menurut dokumen) ekstensi Quarkus ini menyediakan injeksi dependensi CDI.
- Ubah ketergantungan org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec menjadi io.quarkus:quarkus-undertow, hapus asalkan , karena (menurut dokumen) ekstensi Quarkus ini menyediakan dukungan untuk servlet.
- Kami menghapus dependensi org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec karena dependensi tersebut disertakan dengan dependensi yang baru saja kami ubah.
Versi file pom.xml dengan semua perubahannya ada di .
Perhatikan bahwa perintah mvn io.quarkus:quarkus-maven-plugin:0.23.2:create di atas tidak hanya mengubah file pom.xml saja, tetapi juga menambahkan sejumlah komponen pada proyek, yaitu file dan folder berikut:
- File mvnw dan mvnw.cmd serta folder .mvn: Maven Wrapper memungkinkan Anda menjalankan proyek Maven dari versi Maven tertentu tanpa menginstal versi tersebut.
- Folder Docker (di direktori src/main/): Ini berisi contoh Dockerfiles untuk mode native dan jvm (bersama dengan file .dockerignore).
- Folder Resources (di direktori src/main/): Ini berisi file application.properties kosong dan contoh halaman awal Quarkus index.html (lihat Menjalankan helloworld yang dimodernisasi untuk lebih jelasnya).
Luncurkan helloworld
Untuk menguji aplikasi, kami menggunakan quarkus:dev, yang meluncurkan Quarkus dalam mode pengembangan (untuk lebih jelasnya, lihat bagian ini di manual ).
Catatan: Langkah ini diperkirakan akan menghasilkan kesalahan, karena kami belum melakukan semua perubahan yang diperlukan.
Sekarang mari kita jalankan perintah untuk melihat 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, tidak berhasil... Kenapa?
UnsatisfiedResolutionException menunjuk ke kelas HelloService, yang merupakan anggota kelas HelloWorldServlet (anggota Java: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). Masalahnya adalah HelloWorldServlet memerlukan instance HelloService yang disuntikkan, dan tidak dapat ditemukan (walaupun kedua kelas ini berada dalam paket yang sama).
Saatnya untuk kembali ke dan baca cara kerjanya di Quarkus , dan maka dari itu (CDI). Oleh karena itu, buka panduan Konteks dan Injeksi Ketergantungan dan di bagian tersebut kita membaca: “Kelas kacang yang tidak memiliki anotasi yang mendefinisikan kacang tidak akan dicari.”
Mari kita lihat kelas HelloService - kelas ini sebenarnya tidak memiliki anotasi seperti itu. Oleh karena itu harus ditambahkan agar Quarkus dapat mencari dan menemukan kacang tersebut. Dan karena ini adalah objek tanpa kewarganegaraan, kita dapat dengan mudah menambahkan anotasi @ApplicationScoped seperti ini:
@ApplicationScoped
public class HelloService {
Catatan: di sini lingkungan pengembangan mungkin meminta Anda untuk menambahkan paket yang diperlukan (lihat baris di bawah), dan Anda harus melakukannya secara manual, seperti ini:
import javax.enterprise.context.ApplicationScoped;
Jika Anda ragu tentang cakupan mana yang harus digunakan jika cakupan tersebut tidak ditentukan sama sekali untuk kacang sumber, baca dokumentasi .
Sekarang kita coba lagi meluncurkan aplikasi dengan perintah ./mvnw kompilasi 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.
Meluncurkan helloworld yang dimodernisasi
Seperti yang tertulis di log, buka di browser :8080 (halaman awal Quarkus default) dan kita melihat ini:

Beras. 4. Halaman awal pengembang Quarkus.
Anotasi WebServlet untuk aplikasi ini berisi definisi konteks berikut:
@WebServlet("/HelloWorld")
public class HelloWorldServlet extends HttpServlet {
Oleh karena itu, kami masuk ke browser :8080/HelloWorld dan kita melihat yang berikut:

Beras. 5: Halaman pengembang Quarkus untuk aplikasi Hello World.
Ya, semuanya berfungsi.
Sekarang mari kita lakukan perubahan pada kodenya. Perhatikan bahwa perintah ./mvnw kompilasi quarkus:dev masih berjalan dan kami tidak berniat menghentikannya. Sekarang mari kita coba menerapkan perubahan yang sama - sangat sepele - pada kode itu sendiri dan lihat bagaimana Quarkus membuat hidup lebih mudah bagi pengembang:
writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");
Simpan file lalu segarkan halaman web untuk melihat Hello Marco, seperti yang ditunjukkan pada gambar di bawah:

Beras. 6. Halaman Halo Marco di Quarkus dev.
Sekarang mari kita 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
Penyegaran halaman memicu deteksi perubahan dalam kode sumber, dan Quarkus secara otomatis melakukan prosedur stop-start. Dan semua ini diselesaikan hanya dalam 0.371 detik (ini dia, “Java subatomik ultra-cepat”).
Membangun helloworld menjadi paket JAR
Sekarang kodenya berfungsi sebagaimana mestinya, mari kita paketkan 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-runner.jar, yang merupakan JAR yang dapat dieksekusi.
Harap dicatat bahwa ini bukan uber-jar, karena semua dependensi hanya disalin ke folder /target/lib (tidak dikemas ke dalam file JAR). Oleh karena itu, untuk menjalankan JAR ini dari folder lain atau di host lain, Anda perlu menyalin file JAR itu sendiri dan folder /lib di sana, mengingat elemen Class-Path dalam file MANIFEST.MF dalam paket JAR berisi daftar eksplisit JAR dari folder lib
Untuk mempelajari cara membuat aplikasi uber-jar, silakan simak tutorialnya .
Luncurkan helloworld yang dikemas dalam JAR
Sekarang kita dapat menjalankan JAR 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 Anda di :8080 dan periksa apakah semuanya berfungsi sebagaimana mestinya.
Mengkompilasi helloworld menjadi file asli yang dapat dieksekusi
Jadi helloworld kita berjalan sebagai aplikasi Java mandiri menggunakan dependensi Quarkus. Namun Anda dapat melangkah lebih jauh dan mengubahnya menjadi file asli yang dapat dieksekusi.
Menginstal GraalVM
Pertama-tama, untuk ini Anda perlu menginstal alat yang diperlukan:
1. Unduh GraalVM 19.2.0.1 dari .
2. Perluas arsip yang diunduh:
$ tar xvzf graalvm-ce-linux-amd64-19.2.0.1.tar.gz
3. Masuk ke folder untar.
4. Jalankan perintah di bawah ini untuk mendownload dan menambahkan gambar asli:
$ ./bin/gu install native-image
5. Daftarkan folder yang dibuat pada langkah 2 ke variabel lingkungan GRAALVM_HOME:
$ export GRAALVM_HOME={untar-folder}/graalvm-ce-19.2.0.1)
Untuk informasi lebih lanjut dan petunjuk instalasi pada OS lain, lihat manualnya .
Membangun helloworld menjadi file asli yang dapat dieksekusi
Membaca manualnya : “Sekarang mari kita buat file asli yang dapat dieksekusi untuk aplikasi kita guna mengurangi waktu peluncuran dan ukuran disk. File yang dapat dieksekusi akan memiliki semua yang diperlukan untuk menjalankan aplikasi, termasuk JVM (atau lebih tepatnya, versi terpotongnya, hanya berisi apa yang diperlukan untuk menjalankan aplikasi) dan aplikasi kita sendiri.”
Untuk membuat file asli yang dapat dieksekusi, Anda perlu mengaktifkan profil Maven asli:
$ ./mvnw package -Pnative
Pembuatan kami memakan waktu satu menit 10 detik, dan file helloworld—runner f terakhir dibuat di folder /target.
Jalankan executable helloworld asli
Pada langkah sebelumnya, kami menerima file yang dapat dieksekusi /target/helloworld—runner. Sekarang mari kita 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]
Buka lagi di browser :8080 dan periksa apakah semuanya berfungsi sebagaimana mestinya.
одолжение едует!
Kami percaya bahwa metode memodernisasi aplikasi Java menggunakan kemampuan Quarkus yang dibahas dalam postingan ini (walaupun menggunakan contoh sederhana) harus digunakan secara aktif dalam kehidupan nyata. Saat melakukannya, Anda mungkin akan menghadapi sejumlah masalah, yang sebagian akan kami bahas di postingan berikutnya, di mana kami akan membahas tentang cara mengukur konsumsi memori untuk menilai peningkatan kinerja, yang merupakan bagian penting dari keseluruhan proses modernisasi aplikasi.
Sumber: www.habr.com
