Currently, it has become essential that the developments made are deployed on any cloud regardless of the infrastructure, where the environments in which they run, the instances that are created and destroyed, and the application startup times are extremely important. In this context, Quarkus, a RedHat project, appeared to be able to bring Java to the cloud in a much more efficient way. In this article, we will go through the first steps with Quarkus, where we will see some of its features.
Introduction
Over 20 years ago, developers created Java, and it still remains one of the predominant programming languages.. However, nowadays, there is a tendency to move to a world dominated by cloud, containers, microservices, FaaS (Function as a Service), etc. Therefore, cloud-native applications are gaining more and more momentum.
Cloud-native applications can develop and increase productivity and efficiency, so in cloud-oriented environments, Quarkus and Supersonic Subatomic Java become considerably important.
Quarkus is a native Java framework for Kubernetes that works under GraalVM and HotSpot, whose goal is to make Java a leading language in Kubernetes and serverless environments, and offer developers a reactive and imperative development environment.
Getting started with Quarkus
Creating the project
The best and most practical way to create our first application is by using maven, you will need at least version 3.6.2 (mvn -version)
mvn io.quarkus:quarkus-maven-plugin:1.8.0.Final:create \ -DprojectGroupId=com.refactorizando.quarkus \ -DprojectArtifactId=quarkus-project \ -DclassName="com.refactorizando.quarkus.HelloWorldResource" \ -Dpath="/helloworld"
The above command will generate the basic project structure, with a helloworld endpoint and the necessary Dockerfile.
Analyzing the structure
The Maven-generated project has a typical structure for frameworks. The only exceptions would be the docker folder and the index.html file generated inside the resources folder.
As we mentioned earlier, the idea is to facilitate development to make it a native framework for Kubernetes. That’s why in the docker folder, we will find two different files for JVM and native.
If we analyze our pom.xml file, we can see how our Quarqus BOM has been generated. And the quarkus-maven-plugin, which will be responsible for packaging the application and also providing us with the development mode.
Dependency injection in Quarqus
Like many other frameworks, Quarkus brings a Dependency Injection solution. This solution is based on ArC, which is a dependency injection based on CDI (Contexts and Dependency Injection) for the Quarkus architecture.
To create a bean, we will use the @ApplicationScoped annotation, whose function would be the same as Spring does with the @Component annotation. Once we have created that bean, we will inject it into a class, in this case, we can do an injection by constructor or by using the @Inject annotation.
Here’s an example of how to do dependency injection in Quarkus:
package com.refactorizando.quarkus; import javax.enterprise.context.ApplicationScoped; @ApplicationScoped public class HelloWorldService { public String sayHello(String name) { return "hello " + name; } }
package com.refactorizando.quarkus; import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.jboss.resteasy.annotations.jaxrs.PathParam; @Path("/helloworld") public class HelloWorldResource { @Inject HelloWorldService helloWorldService; @GET @Produces(MediaType.TEXT_PLAIN) @Path("/sayHello/{name}") public String hello(@PathParam String name) { return helloWorldService.sayHello(name); } @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "hello"; } }
Hot reload
One of the advantages that Quarkus brings out of the box is hot reload, meaning that any modifications to the code will be automatically applied, although this functionality will only be available in development mode (compile quarkus:dev).
Based on the class we created earlier, HelloService, and the modification to the HelloWorldResource class, we are going to make a change to the code and see how it applies “on the fly”.
Let’s run:
mvn compile quarkus:dev
Creating an image of our Quarkus project
Now let’s move on to the really exciting part of Quarkus, creating a native image. This image will contain everything necessary to be deployed, we just need to have GraalVM installed, just like we have Java installed in our Home and IDE.
Remember to have GraalVM installed and configured.
We execute the following command to create the image:
mvn package -Pnative
The previous command will create the image by pulling quarkus/ubi-quarkus-native-image to create a native executable. Then, once the image creation is complete, we will create an executable that will run in the container:
mvn package -Pnative -Dnative-image.docker-build=true
And finally, we will create and run the image created with the project archetype and our small modification added with the HelloWorldService class.
docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-project .
docker run -i --rm -p 8080:8080 quarkus/quarkus-project
Take a look at how long it took to start up, the time was practically 0.
One of the contributions of Quarkus is its low startup time.
From your browser, Postman or with curl, execute: http://localhost:8080/helloworld
Deploying a Quarkus application on Kubernetes
To deploy a Quarkus application on Kubernetes, we will use a set of extensions when using the Maven archetype to generate our project:
mvn io.quarkus:quarkus-maven-plugin:1.8.1.Final:create \ -DprojectGroupId=com.refactorizando.quarkus \ -DprojectArtifactId=quarkus-project \ -DclassName="com.refactorizando.quarkus.HelloWorldResource" \ -Dpath="/helloworld" -Dextensions="kubernetes, jib"
Alternatively, to avoid modifying the previous code, we could directly add the Maven dependencies to our pom.xml:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-kubernetes</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-container-image-jib</artifactId> </dependency>
These dependencies will create the json/yaml files for the services and deployments:
--- apiVersion: v1 kind: ServiceAccount metadata: annotations: app.quarkus.io/build-timestamp: 2020-09-02 - 18:42:35 +0000 labels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT name: quarkus-project --- apiVersion: v1 kind: Service metadata: annotations: app.quarkus.io/build-timestamp: 2020-09-02 - 18:42:35 +0000 labels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT name: quarkus-project spec: ports: - name: http port: 8080 targetPort: 8080 selector: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: annotations: app.quarkus.io/build-timestamp: 2020-09-02 - 18:42:35 +0000 labels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT name: quarkus-project spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT template: metadata: annotations: app.quarkus.io/build-timestamp: 2020-09-02 - 18:42:35 +0000 labels: app.kubernetes.io/name: quarkus-project app.kubernetes.io/version: 1.0-SNAPSHOT spec: containers: - env: - name: KUBERNETES_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: nrodriguez/quarkus-project:1.0-SNAPSHOT imagePullPolicy: IfNotPresent name: quarkus-project ports: - containerPort: 8080 name: http protocol: TCP serviceAccount: quarkus-project
Next, we apply these files using the kubectl command:
kubectl apply -f target/kubernetes/kubernetes.yaml
Conclusion on first steps with Quarkus
In these first steps with Quarkus, we have seen how we can create a helloworld and deploy it on Kubernetes. Also, we have observed how Quarkus provides comparatively fast startup times compared to other frameworks.
If you want to take a look at the example, you can check it out on our Github.
If you need more information, you can leave us a comment or send an email to refactorizando.web@gmail.com You can also contact us through our social media channels on Facebook or twitter and we will be happy to assist you!!