Sick Gaming
Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1 - Printable Version

+- Sick Gaming (https://www.sickgaming.net)
+-- Forum: Programming (https://www.sickgaming.net/forum-76.html)
+--- Forum: Java Language, JVM, and the JRE (https://www.sickgaming.net/forum-78.html)
+--- Thread: Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1 (/thread-93321.html)



Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1 - xSicKxBot - 01-25-2020

Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1

<div style="margin: 5px 5% 10px 5%;"><img src="https://www.sickgaming.net/blog/wp-content/uploads/2020/01/quarkus-modernize-helloworld-jboss-eap-quickstart-part-1.png" width="1024" height="644" title="" alt="" /></div><div><p><a href="https://quarkus.io/" target="_blank" rel="noopener noreferrer">Quarkus</a> is, in its own words, “Supersonic subatomic Java” and a “Kubernetes native Java stack tailored for GraalVM &amp; OpenJDK HotSpot, crafted from the best of breed Java libraries and <a href="https://quarkus.io/vision/standards" target="_blank" rel="noopener noreferrer">standards.</a>” For the purpose of illustrating how to modernize an existing Java application to Quarkus, I will use the <a href="https://github.com/jboss-developer/jboss-eap-quickstarts/tree/7.2.0.GA/helloworld" target="_blank" rel="noopener noreferrer">Red Hat JBoss Enterprise Application Platform (JBoss EAP) quickstarts <code>helloworld</code></a> quickstart as sample of a Java application builds using technologies (CDI and Servlet 3) supported in Quarkus.</p>
<p>It’s important to note that both Quarkus and JBoss EAP rely on providing developers with tools based—as much as possible—on standards. If your application is not already running on JBoss EAP, there’s no problem. You can migrate it from your current application server to JBoss EAP using the <a href="https://developers.redhat.com/products/rhamt">Red Hat Application Migration Toolkit</a>. After that, the final and working modernized version of the code is available in the <a href="https://github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus" target="_blank" rel="noopener noreferrer">https://github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus</a> repository inside the <a href="https://github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus/helloworld" target="_blank" rel="noopener noreferrer"><code>helloworld</code></a> module.</p>
<p>This article is based on the <a href="https://quarkus.io/guides/" target="_blank" rel="noopener noreferrer">guides Quarkus provides</a>, mainly <a href="https://quarkus.io/guides/getting-started-guide" target="_blank" rel="noopener noreferrer">Creating Your First Application</a> and <a href="https://quarkus.io/guides/building-native-image-guide.html" target="_blank" rel="noopener noreferrer">Building a Native Executable</a>.<span id="more-642737"></span></p>
<h2>Get the code</h2>
<p>To start, clone the <a href="https://github.com/jboss-developer/jboss-eap-quickstarts" target="_blank" rel="noopener noreferrer">JBoss EAP quickstarts</a> repository locally, running:</p>
<pre>$ 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/</pre>
<h2 id="try-plain-vanilla-helloworld">Try plain, vanilla <code>helloworld</code></h2>
<p>The name of the quickstart is a strong clue about what this application does, but let’s follow a scientific approach in modernizing this code, so first things first: Try the application as it is.</p>
<h3 id="deploy-helloworld">Deploy <code>helloworld</code></h3>
<ol>
<li>Open a terminal and navigate to the root of the JBoss EAP directory <code>EAP_HOME</code> (which you can <a href="https://developers.redhat.com/products/eap/download">download</a>).</li>
<li>Start the JBoss EAP server with the default profile by typing the following command:</li>
</ol>
<pre style="padding-left: 40px">$ EAP_HOME/bin/standalone.sh </pre>
<p style="padding-left: 40px"><strong>Note: </strong>For Windows, use the <code>EAP_HOME\bin\standalone.bat</code> script.</p>
<p style="padding-left: 40px">After a few seconds, the log should look like:</p>
<pre style="padding-left: 40px">[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)</pre>
<ol start="3">
<li>Open <code>http://127.0.0.1:8080</code> in a browser, and a page like Figure 1 should appear:</li>
</ol>
<div id="attachment_642767" style="width: 650px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-642767" class="wp-image-642767 size-large" src="https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-home-page-1024x644.png" alt="The JBoss EAP home page." width="640" height="403" srcset="https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-home-page-1024x644.png 1024w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-home-page-300x189.png 300w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-home-page-768x483.png 768w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-home-page.png 1316w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p id="caption-attachment-642767" class="wp-caption-text"><em>Figure 1: The JBoss EAP home page.</em></p>
</div>
<ol start="4">
<li>Following instructions from <a href="https://github.com/jboss-developer/jboss-eap-quickstarts#build-and-deploy-the-quickstart" target="_blank" rel="noopener noreferrer">Build and Deploy the Quickstart</a>, deploy the <code>helloworld</code> quickstart and execute (from the project root directory) the command:</li>
</ol>
<pre style="padding-left: 40px">$ mvn clean install wildfly:deploy </pre>
<p style="padding-left: 40px">This command should end successfully with a log like this:</p>
<pre style="padding-left: 40px">[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 8.224 s </pre>
<p>The <code>helloworld</code> application has now been deployed for the first time in JBoss EAP in about eight seconds.</p>
<h3 id="test-helloworld">Test <code>helloworld</code></h3>
<p>Following the <a href="https://github.com/jboss-developer/jboss-eap-quickstarts/tree/7.2.0.GA/helloworld#access-the-application" target="_blank" rel="noopener noreferrer">Access the Application</a> guide, open <code>http://127.0.0.1:8080/helloworld</code> in the browser and see the application page, as shown in Figure 2:</p>
<div id="attachment_642787" style="width: 650px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-642787" class="wp-image-642787 size-large" src="https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-world-1024x644.png" alt="JBoss EAP's Hello World." width="640" height="403" srcset="https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-world-1024x644.png 1024w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-world-300x189.png 300w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-world-768x483.png 768w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-world.png 1316w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p id="caption-attachment-642787" class="wp-caption-text"><em>Figure 2: JBoss EAP’s Hello World.</em></p>
</div>
<h3 id="make-some-changes">Make changes</h3>
<p>Change the <code>createHelloMessage(String name)</code> input parameter from <code>World</code> to <code>Marco</code> (my ego is cheap):</p>
<pre>writer.println("&lt;h1&gt;" + helloService.createHelloMessage("Marco") + "&lt;/h1&gt;");</pre>
<p>Execute again the command:</p>
<pre>$ mvn clean install wildfly:deploy </pre>
<p>and then refresh the web page in the browser to check the message displayed changes, as shown in Figure 3:</p>
<div id="attachment_642797" style="width: 650px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-642797" class="wp-image-642797 size-large" src="https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-marco-1024x644.png" alt="JBoss EAP's Hello Marco." width="640" height="403" srcset="https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-marco-1024x644.png 1024w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-marco-300x189.png 300w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-marco-768x483.png 768w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/jboss-eap-hello-marco.png 1316w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p id="caption-attachment-642797" class="wp-caption-text"><em>Figure 3: JBoss EAP’s Hello Marco.</em></p>
</div>
<h3 id="undeploy-helloworld-and-shutdown">Undeploy <code>helloworld</code> and shut down</h3>
<p>If you want to undeploy (optional) the application before shutting down JBoss EAP, run the following command:</p>
<pre>$ mvn clean install wildfly:undeploy </pre>
<p>To shut down the JBoss EAP instance, enter Ctrl+C in the terminal where it’s running.</p>
<h2 id="lets-modernize-helloworld">Let’s modernize <code>helloworld</code></h2>
<p>Now we can leave the original <code>helloworld</code> behind and update it.</p>
<h3 id="create-a-new-branch-useful-or-ot">Create a new branch</h3>
<p>Create a new working branch once the quickstart project finishes executing:</p>
<pre>$ git checkout -b quarkus 7.2.0.GA </pre>
<h3 id="changes-in-pomxml-file">Change the <code>pom.xml</code> file</h3>
<p>The time has come to start changing the application. starting from the <code>pom.xml</code> file. From the <code>helloworld</code> folder, run the following command to let Quarkus add XML blocks:</p>
<pre>$ mvn io.quarkus:quarkus-maven-plugin:0.23.2:create </pre>
<p>This article uses the 0.23.2 version. To know which is the latest version is, please refer to <a href="https://github.com/quarkusio/quarkus/releases/latest/" target="_blank" rel="noopener noreferrer">https://github.com/quarkusio/quarkus/releases/latest/</a>, since the Quarkus release cycles are short.</p>
<p>This command changed the <code>pom.xml</code>, file adding:</p>
<ul>
<li>The property <code>&lt;quarkus.version&gt;</code> to define the Quarkus version to be used.</li>
<li>The <code>&lt;dependencyManagement&gt;</code> block to import the Quarkus bill of materials (BOM). In this way, there’s no need to add the version to each Quarkus dependency.</li>
<li>The <code>quarkus-maven-plugin</code> plugin responsible for packaging the application, and also providing the development mode.</li>
<li>The <code>native</code> profile to create application native executables.</li>
</ul>
<p>Further changes required to <code>pom.xml</code>, to be done manually:</p>
<ol>
<li>Move the <code>&lt;groupId&gt;</code> tag outside of the <code>&lt;parent&gt;</code> block, and above the <code>&lt;artifactId&gt;</code> tag. Because we remove the <code>&lt;parent&gt;</code> block in the next step, the <code>&lt;groupId&gt;</code> must be preserved.</li>
<li>Remove the <code>&lt;parent&gt;</code> block: The application doesn’t need the JBoss parent pom anymore to run with Quarkus.</li>
<li>Add the <code>&lt;version&gt;</code> tag (below the <code>&lt;artifactId&gt;</code> tag) with the value you prefer.</li>
<li>Remove the <code>&lt;packaging&gt;</code> tag: The application won’t be a WAR anymore, but a plain JAR.</li>
<li>Change the following dependencies:
<ol>
<li>Replace the <code>javax.enterprise:cdi-api</code> dependency with <a href="https://quarkus.io/extensions/#core"><code>io.quarkus:quarkus-arc</code></a>, removing <code>&lt;scope&gt;provided&lt;/scope&gt;</code> because—as stated in the documentation—this Quarkus extension provides the CDI dependency injection.</li>
<li>Replace the <code>org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec</code> dependency with <a href="https://quarkus.io/extensions/#web"><code>io.quarkus:quarkus-undertow</code></a>, removing the <code>&lt;scope&gt;provided&lt;/scope&gt;</code>, because—again as stated in the documentation—this is the Quarkus extension that provides support for servlets.</li>
<li>Remove the <code>org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec</code> dependency because it’s coming with the previously changed dependencies.</li>
</ol>
</li>
</ol>
<p>The <code>pom.xml</code> file’s fully changed version is available at <a href="https://github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml" target="_blank" rel="noopener noreferrer">https://github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml</a>.</p>
<p>Note that the above <code>mvn io.quarkus:quarkus-maven-plugin:0.23.2:create</code> command, besides the changes to the <code>pom.xml</code> file, added components to the project. The added file and folders are:</p>
<ul>
<li>The files <code>mvnw</code> and <code>mvnw.cmd</code>, and <code>.mvn</code> folder: The <a href="https://github.com/takari/maven-wrapper" target="_blank" rel="noopener noreferrer">Maven Wrapper</a> allows you to run Maven projects with a specific version of Maven without requiring that you install that specific Maven version.</li>
<li>The <code>docker</code> folder (in <code>src/main/</code>): This folder contains example <code>Dockerfile</code> files for both <code>native</code> and <code>jvm</code> modes (together with a <code>.dockerignore</code> file).</li>
<li>The <code>resources</code> folder (in <code>src/main/</code>): This folder contains an empty <code>application.properties</code> file and the sample Quarkus landing page <code>index.html</code> (more in the section “<a href="#try-the-modernized-helloworld">Run the modernized <code>helloworld</code></a>“).</li>
</ul>
<h3 id="try-to-run-helloworld">Run <code>helloworld</code></h3>
<p>To test the application, use <code>quarkus:dev</code>, which runs Quarkus in development mode (more details on <a href="https://quarkus.io/guides/getting-started-guide#development-mode" target="_blank" rel="noopener noreferrer">Development Mode here</a>).</p>
<p><strong>Note: </strong>We expect this step to fail as changes are still required to the application, as detailed in this section.</p>
<p>Now run the command to check if and how it works:</p>
<pre>$ ./mvnw compile quarkus:dev [INFO] Scanning for projects... [INFO] [INFO] ----------------&lt; org.jboss.eap.quickstarts:helloworld &gt;---------------- [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 </pre>
<p>It failed. Why? What happened?</p>
<p>The <code>UnsatisfiedResolutionException</code> exception refers to the <code>HelloService</code> class, which is a member of the <code>HelloWorldServlet</code> class (<code>java member: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService</code>). The problem is that <code>HelloWorldServlet</code> needs an injected instance of <code>HelloService</code>, but it can not be found (even if the two classes are in the very same package).</p>
<p>It’s time to return to <a href="https://quarkus.io/guides/" target="_blank" rel="noopener noreferrer">Quarkus guides</a> to leverage the documentation and understand how <code>@Inject</code>—and hence Contexts and Dependency Injection (CDI)—works in Quarkus, thanks to the <a href="https://quarkus.io/guides/cdi-reference" target="_blank" rel="noopener noreferrer">Contexts and Dependency Injection</a> guide. In the <a href="https://quarkus.io/guides/cdi-reference#bean_discovery" target="_blank" rel="noopener noreferrer">Bean Discovery</a> paragraph, it says, “Bean classes that don’t have a bean defining annotation are not discovered.”</p>
<p>Looking at the <code>HelloService</code> class, it’s clear there’s no bean defining annotation, and one has to be added to have Quarkus to discover the bean. So, because it’s a stateless object, it’s safe to add the <code>@ApplicationScoped</code> annotation:</p>
<pre>@ApplicationScoped public class HelloService { </pre>
<p><strong>Note: </strong>The IDE should prompt you to add the required package shown here (add it manually if need be):</p>
<pre>import javax.enterprise.context.ApplicationScoped; </pre>
<p>If you’re in doubt about which scope to apply when the original bean has no scope defined, please refer to the <a href="https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#default_scope" target="_blank" rel="noopener noreferrer">JSR 365: Contexts and Dependency Injection for Java 2.0—Default scope</a> documentation.</p>
<p>Now, try again to run the application, executing again the <code>./mvnw compile quarkus:dev</code> command:</p>
<pre>$ ./mvnw compile quarkus:dev [INFO] Scanning for projects... [INFO] [INFO] ----------------&lt; org.jboss.eap.quickstarts:helloworld &gt;---------------- [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] </pre>
<p>This time the application runs successfully.</p>
<h3 id="try-the-modernized-helloworld">Run the modernized <code>helloworld</code></h3>
<p>As the terminal log suggests, open a browser to <code>http://0.0.0.0:8080</code>(the default Quarkus landing page), and the page shown in Figure 4 appears:</p>
<div id="attachment_642837" style="width: 650px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-642837" class="wp-image-642837 size-large" src="https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-landing-page-1024x644.png" alt="The Quarkus dev landing page." width="640" height="403" srcset="https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-landing-page-1024x644.png 1024w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-landing-page-300x189.png 300w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-landing-page-768x483.png 768w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-landing-page.png 1316w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p id="caption-attachment-642837" class="wp-caption-text"><em>Figure 4: The Quarkus dev landing page.</em></p>
</div>
<p>This application has the following context’s definition in the <code>WebServlet</code> annotation:</p>
<pre>@WebServlet("/HelloWorld") public class HelloWorldServlet extends HttpServlet { </pre>
<p>Hence, you can browse to <code>http://0.0.0.0:8080/HelloWorld</code>to reach the page shown in Figure 5:</p>
<div id="attachment_642857" style="width: 650px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-642857" class="wp-image-642857 size-large" src="https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-world-1024x644.png" alt="The Quarkus dev Hello World page." width="640" height="403" srcset="https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-world-1024x644.png 1024w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-world-300x189.png 300w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-world-768x483.png 768w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-world.png 1316w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p id="caption-attachment-642857" class="wp-caption-text"><em>Figure 5: The Quarkus dev Hello World page.</em></p>
</div>
<p>It works!</p>
<h3 id="make-some-changes">Make changes</h3>
<p>Please, pay attention to the fact that the <code>./mvnw compile quarkus:dev</code> command is still running, and we’re not going to stop it. Now, try to apply the same—very trivial—change to the code and see how Quarkus improves the developer experience:</p>
<pre>writer.println("&lt;h1&gt;" + helloService.createHelloMessage("Marco") + "&lt;/h1&gt;");</pre>
<p>Save the file, and then refresh the web page to check that <code>Hello Marco</code> appears, as shown in Figure 6:</p>
<div id="attachment_647397" style="width: 650px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-647397" class="wp-image-647397 size-large" src="https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-marco-1024x644.png" alt="The Quarkus dev Hello Marco page." width="640" height="403" srcset="https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-marco-1024x644.png 1024w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-marco-300x189.png 300w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-marco-768x483.png 768w, https://developers.redhat.com/blog/wp-content/uploads/2019/10/quarkus-dev-hello-marco.png 1316w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p id="caption-attachment-647397" class="wp-caption-text"><em>Figure 6: The Quarkus dev Hello Marco page.</em></p>
</div>
<p>Take time to check the terminal output:</p>
<pre>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 </pre>
<p>Refreshing the page triggered the source code change detection and the Quarkus automagic “stop-and-start.” All of this executed in just 0.371 seconds (that’s part of the Quarkus “Supersonic Subatomic Java” experience).</p>
<h3 id="build-the-helloworld-packaged-jar">Build the <code>helloworld</code> packaged JAR</h3>
<p>Now that the code works as expected, it can be packaged using the command:</p>
<pre>$ ./mvnw clean package</pre>
<p>This command creates two JARs in the <code>/target</code> folder. The first is <code>helloworld-&lt;version&gt;.jar</code>, which is the standard artifact built from the Maven command with the project’s classes and resources. The second is <code>helloworld-&lt;version&gt;-runner.jar</code>, which is an executable JAR.</p>
<p>Please pay attention to the fact that this is not an <em>uber-jar</em>, because all of the dependencies are copied into the <code>/target/lib</code> folder (and not bundled within the JAR). Hence, to run this JAR in another location or host, both the JAR file and the libraries in the <code>/lib</code> folder have to be copied, considering that the <code>Class-Path</code> entry of the <code>MANIFEST.MF</code> file in the JAR explicitly lists the JARs from the <code>lib</code> folder.</p>
<p>To create an <em>uber-jar</em> application, please refer to the <a href="https://quarkus.io/guides/maven-tooling#uber-jar-maven" target="_blank" rel="noopener noreferrer">Uber-Jar Creation</a> Quarkus guide.</p>
<h3 id="run-the-helloworld-packaged-jar">Run the <code>helloworld</code> packaged JAR</h3>
<p>Now, the packaged JAR can be executed using the standard <code>java</code> command:</p>
<pre>$ java -jar ./target/helloworld-<b>&lt;version&gt;</b>-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] </pre>
<p>As done above, open the <code>http://0.0.0.0:8080</code> URL in a browser, and test that everything works.</p>
<h3 id="build-the-helloworld-quickstart-native-executable">Build the <code>helloworld</code> quickstart-native executable</h3>
<p>So far so good. The <code>helloworld</code> quickstart ran as a standalone Java application using Quarkus dependencies, but more can be achieved by adding a further step to the modernization path: Build a native executable.</p>
<h4 id="install-graalvm">Install GraalVM</h4>
<p>First of all, the tools for creating the native executable have to be installed:</p>
<ol>
<li>Download GraalVM 19.2.0.1 from <a href="https://github.com/oracle/graal/releases/tag/vm-19.2.0.1" target="_blank" rel="noopener noreferrer">https://github.com/oracle/graal/releases/tag/vm-19.2.0.1</a>.</li>
<li>Untar the file using the command:</li>
</ol>
<p style="padding-left: 40px"><code>$ tar xvzf graalvm-ce-linux-amd64-19.2.0.1.tar.gz</code></p>
<ol start="3">
<li>Go to the <code>untar</code> folder.</li>
<li>Execute the following to download and add the native image component:</li>
</ol>
<p style="padding-left: 40px"><code>$ ./bin/gu install native-image</code></p>
<ol start="5">
<li>Set the <code>GRAALVM_HOME</code> environment variable to the folder created in step two, for example:</li>
</ol>
<p style="padding-left: 40px"><code>$ export GRAALVM_HOME={untar-folder}/graalvm-ce-19.2.0.1</code>)</p>
<p>More details and install instructions for other operating systems are available in <a href="https://quarkus.io/guides/building-native-image-guide.html#prerequisites" target="_blank" rel="noopener noreferrer">Building a Native Executable—Prerequisites</a> Quarkus guide.</p>
<h4 id="build-the-helloworld-native-executable">Build the <code>helloworld</code> native executable</h4>
<p>As stated in the <a href="https://quarkus.io/guides/building-native-image-guide.html#producing-a-native-executable" target="_blank" rel="noopener noreferrer">Building a Native Executable—Producing a native executable</a> Quarkus guide, “Let’s now produce a native executable for our application. It improves the startup time of the application and produces a minimal disk footprint. The executable would have everything to run the application including the ‘JVM’ (shrunk to be just enough to run the application), and the application.”</p>
<p>To create the native executable, the Maven <code>native</code> profile has to be enabled by executing:</p>
<pre>$ ./mvnw package -Pnative</pre>
<p>The build took me about 1:10 minutes and the result is the <code>helloworld-&lt;version&gt;-runner</code> file in the <code>/target</code> folder.</p>
<h3 id="run-the-helloworld-native-executable">Run the <code>helloworld</code> native executable</h3>
<p>The <code>/target/helloworld-&lt;version&gt;-runner</code> file created in the previous step. It’s executable, so running it is easy:</p>
<pre>$ ./target/helloworld-<b>&lt;version&gt;</b>-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] </pre>
<p>As done before, open the <code>http://0.0.0.0:8080</code> URL in a browser and test that everything is working.</p>
<h2>Next steps</h2>
<p>I believe that this modernization, even of a basic application, is the right way to approach a brownfield application using technologies available in Quarkus. This way, you can start facing the issues and tackling them to understand and learn how to solve them.</p>
<p><a href="https://developers.redhat.com/blog/2019/11/08/quarkus-modernize-helloworld-jboss-eap-quickstart-part-2/">In part two of this series,</a> I’ll look at how to capture memory consumption data in order to evaluate performance improvements, which is a fundamental part of the modernization process.</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fdevelopers.redhat.com%2Fblog%2F2019%2F11%2F07%2Fquarkus-modernize-helloworld-jboss-eap-quickstart-part-1%2F&amp;linkname=Quarkus%3A%20Modernize%20%E2%80%9Chelloworld%E2%80%9D%20JBoss%20EAP%20quickstart%2C%20Part%201" title="Facebook" rel="nofollow noopener noreferrer" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fdevelopers.redhat.com%2Fblog%2F2019%2F11%2F07%2Fquarkus-modernize-helloworld-jboss-eap-quickstart-part-1%2F&amp;linkname=Quarkus%3A%20Modernize%20%E2%80%9Chelloworld%E2%80%9D%20JBoss%20EAP%20quickstart%2C%20Part%201" title="Twitter" rel="nofollow noopener noreferrer" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fdevelopers.redhat.com%2Fblog%2F2019%2F11%2F07%2Fquarkus-modernize-helloworld-jboss-eap-quickstart-part-1%2F&amp;linkname=Quarkus%3A%20Modernize%20%E2%80%9Chelloworld%E2%80%9D%20JBoss%20EAP%20quickstart%2C%20Part%201" title="LinkedIn" rel="nofollow noopener noreferrer" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fdevelopers.redhat.com%2Fblog%2F2019%2F11%2F07%2Fquarkus-modernize-helloworld-jboss-eap-quickstart-part-1%2F&amp;linkname=Quarkus%3A%20Modernize%20%E2%80%9Chelloworld%E2%80%9D%20JBoss%20EAP%20quickstart%2C%20Part%201" title="Email" rel="nofollow noopener noreferrer" target="_blank"></a><a class="a2a_button_print" href="https://www.addtoany.com/add_to/print?linkurl=https%3A%2F%2Fdevelopers.redhat.com%2Fblog%2F2019%2F11%2F07%2Fquarkus-modernize-helloworld-jboss-eap-quickstart-part-1%2F&amp;linkname=Quarkus%3A%20Modernize%20%E2%80%9Chelloworld%E2%80%9D%20JBoss%20EAP%20quickstart%2C%20Part%201" title="Print" rel="nofollow noopener noreferrer" target="_blank"></a><a class="a2a_button_reddit" href="https://www.addtoany.com/add_to/reddit?linkurl=https%3A%2F%2Fdevelopers.redhat.com%2Fblog%2F2019%2F11%2F07%2Fquarkus-modernize-helloworld-jboss-eap-quickstart-part-1%2F&amp;linkname=Quarkus%3A%20Modernize%20%E2%80%9Chelloworld%E2%80%9D%20JBoss%20EAP%20quickstart%2C%20Part%201" title="Reddit" rel="nofollow noopener noreferrer" target="_blank"></a><a class="a2a_button_flipboard" href="https://www.addtoany.com/add_to/flipboard?linkurl=https%3A%2F%2Fdevelopers.redhat.com%2Fblog%2F2019%2F11%2F07%2Fquarkus-modernize-helloworld-jboss-eap-quickstart-part-1%2F&amp;linkname=Quarkus%3A%20Modernize%20%E2%80%9Chelloworld%E2%80%9D%20JBoss%20EAP%20quickstart%2C%20Part%201" title="Flipboard" rel="nofollow noopener noreferrer" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fdevelopers.redhat.com%2Fblog%2F2019%2F11%2F07%2Fquarkus-modernize-helloworld-jboss-eap-quickstart-part-1%2F&title=Quarkus%3A%20Modernize%20%E2%80%9Chelloworld%E2%80%9D%20JBoss%20EAP%20quickstart%2C%20Part%201" data-a2a-url="https://developers.redhat.com/blog/2019/11/07/quarkus-modernize-helloworld-jboss-eap-quickstart-part-1/" data-a2a-title="Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1"><img src="https://static.addtoany.com/buttons/favicon.png" alt="Share"></a></p>
<p>The post <a rel="nofollow" href="https://developers.redhat.com/blog/2019/11/07/quarkus-modernize-helloworld-jboss-eap-quickstart-part-1/">Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1</a> appeared first on <a rel="nofollow" href="https://developers.redhat.com/blog">Red Hat Developer</a>.</p>
</div>


https://www.sickgaming.net/blog/2019/11/07/quarkus-modernize-helloworld-jboss-eap-quickstart-part-1/