AdBlock Detected

It looks like you're using an ad-blocker!

Our team work realy hard to produce quality content on this website and we noticed you have ad-blocking enabled. Advertisements and advertising enable us to continue working and provide high-quality content.

First steps with Quarkus

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.

First steps with Quarkus
Quarkus project structure with Maven

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!!

Leave a Reply

Your email address will not be published. Required fields are marked *