fbpx
Hero Illustration
0 Comments
Java, Quarkus, Software Development, Spring Boot

Using Quarkus as an Alternative for Spring Boot

It had been so long since I last opened Java EE. While most of my development experience has been conducted through the Spring Framework, and I moved onto Spring Boot a couple of years ago, I was generally of the opinion that JEE was dead. There had been so little improvements to the framework since Java EE 5 and no major improvements in either Java EE 6 or 7. Oracle even stopped its support on Glassfish in 2013 which is the official implementation of JEE technologies. Oracle also donated JEE to the Eclipse Foundation in 2017 and Eclipse then renamed Java EE it to Jakarta EE. It seemed that the platform was circling the drain.

So why did I start to reinvestigate Jakarta EE? The reason is Quarkus.

Quarkus started as Thorntail 4.x proof-of-concept, which aimed to make Jakarta EE development easier. It’s similar to the Spring Boot approach, whereby you can run your application by simply executing the ‘java -jar’ command. I know this is not revolutionary – Payara Micro, Wildfly Swarm and TomEE have all already done this. However, backed by Red Hat, Quarkus taking it further by adding support for Kubernetes, serverless, and cloud applications. Looking at the latest Jakarta EE Developer Survey result, Quarkus usage is has been shown to increase to about 16% in 2020, with Jakarta EE emerging as the second-place cloud-native framework with 35% usage in this year’s survey.

After investigating and testing Quarkus, I found some interesting features that make Quarkus a superior alternative for Spring Boot that will save you time and money in your development.

Project Template

Using code.quarkus.io allows you to generate project templates for your Quarkus project, saving developers time and money and get you moving on new applications FAST. Similar to the Spring Boot variant, start.spring.io, you can save time and effort working out dependancies and external services (like the Maven Respoitory) in the large Java ecosystem. Get to a minimum viable product quickly and easily using these project templates.

Quarkus Project Template Generator

Persistence

Quarkus supports both SQL and NoSQL databases, while also providing an abstraction to work with those databases using either Active Record pattern or Repository pattern. For now, the abstraction only supports Hibernate and MongoDB, although this may change in the future.

Here’s how code will look like for Hibernate using Active Record pattern.

import io.quarkus.hibernate.orm.panache.PanacheEntity;

import javax.persistence.Entity;
import java.util.List;

@Entity
public class Employee extends PanacheEntity { // (1)
    public String firstName;
    public String lastName;

    public static List<Employee> findByFirstName(String firstName){ // (2)
        return find("firstName", firstName).list(); // (3)
    }
}
  1. We extend the entity io.quarkus.hibernate.orm.panache.PanacheEntity – this is needed to allow common functions to operate with this entity e.g. save, delete, update, and even performing searches.
  2. Custom method to create queries. In this case, we are retrieving employee data by their firstName.
  3. Use the built-in query method “find” to construct custom queries.

Here is how we use this entity:

@ApplicationScoped
public class EmployeeService {

    public Employee create(){
        Employee e = new Employee();
        e.firstName = "John";
        e.lastName = "Doe";
        e.persist();
        return e;
    }
    
    public List<Employee> findByFirstName(String firstName){
        return Employee.findByFirstName(firstName);
    }

}

You can also use Repository pattern:

import io.quarkus.hibernate.orm.panache.PanacheRepository;
import org.quarkus.model.Employee;

import javax.enterprise.context.ApplicationScoped;
import java.util.List;

@ApplicationScoped // (1)
public class EmployeeRepository implements PanacheRepository<Employee> { // (2)
    public List<Employee> findByFirstName(String firstName){
        return find("firstName", firstName).list(); // (3)
    }
}
  1. Tell Quarkus to manage this class as bean. We will discuss this later in this article.
  2. We extend the repository class from io.quarkus.hibernate.orm.panache.PanacheRepository. This will provide a built-in function similar to the previous Active Record pattern.
  3. Use the built-in query method “find” to construct custom queries.

Here’s how to use the repository:

@ApplicationScoped
public class EmployeeService {
    private final EmployeeRepository employeeRepository;

    public EmployeeService(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    public Employee create(){
        Employee e = new Employee();
        e.firstName = "John";
        e.lastName = "Doe";
        employeeRepository.persist(e);
        return e;
    }

    public List<Employee> findByFirstName(String firstName){
        return employeeRepository.findByFirstName(firstName);
    }
}

Dependency Injection

Because Quarkus adopts JEE technologies, Quarkus uses JSR 365 Contexts and Dependency Injection for its IOC (Inversion of Control) container. For those with experience developing JEE Applications, this isn’t new – but for those using the Spring Framework, this is similar to the Spring Dependency Injection function.

For example, to make a class as a Spring bean we use @org.springframework.stereotype.Component, while in Quarkus we use @javax.enterprise.context.ApplicationScoped and when the other class need this bean as their dependencies, then we can use @javax.inject.Inject to tell Quarkus to inject the bean. In Spring you will use @org.springframework.beans.factory.annotation.Autowired for this.

RESTful Web

Again, Quarkus adopt JEE technologies, including JAX-RS and RESTEasy as default implementations. Here is how the code will appear when serving an Employee resource as REST.

@Path("/employees") // (1)
@Produces(MediaType.APPLICATION_JSON) // (2)
public class EmployeeResource {
    private final EmployeeRepository employeeRepository;

    public EmployeeResource(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    @GET // (3)
    public List<Employee> findAll(){
        return employeeRepository.findAll().list();
    }
}
  1. Defines the URL path for the resource.
  2. Defines the content-type for the resource.
  3. Defines the method type for the resource.

The table below lists commonly used annotations and their correlation with the Spring Framework.

QuakusSpring Framework
javax.ws.rs.Pathorg.springframework.web.bind.annotation.RequestMapping
javax.ws.rs.Producesorg.springframework.web.bind.annotation.RequestMapping#produces
javax.ws.rs.GETorg.springframework.web.bind.annotation.GetMapping
javax.ws.rs.POSTorg.springframework.web.bind.annotation.PostMapping
javax.ws.rs.PUTorg.springframework.web.bind.annotation.PutMapping
javax.ws.rs.DELETEorg.springframework.web.bind.annotation.DeleteMapping

Conclusion

Although I have barely scratched the surface of Quarkus, it’s clear that Quarkus offers the same programming principles we see in Spring Framework or Spring Boot.

So why make the switch? In my opinion, Quarkus will shine when we need to migrate legacy JEE applications into modern lightweight platforms because there will be less code adjustment than if you were using Spring Framework. Saving time and development hours is always worth investigating for any developer, and so I encourage you to look at Quarkus for your next application.

If you’re loving Quarkus or have found something that makes Quarkus a poor fit for you, we want to hear about it! Comment below and join the conversation.

Author:
Kustian – Technology Evangelist

Contact us to learn more!

Please complete the brief information below and we will follow up shortly.

    ** All fields are required
    Leave a comment