According to the Quarkus product page it is “A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards.” I wanted to explore the differences between a typical Spring Boot/Data application and a Quarkus application through a code comparison.
Since JHipster generates an actual runnable application out of the box, I fired up the Quarkus JHipster blueprint. I would like to thank this post for providing step-by-step instructions on how to install the Quarkus blueprint and generate an application.
Since the entities are still using JPA, they do not look all that much different from the Spring version. They do extend from PanacheEntityBase
which is a Quarkus-specific class that provides your typical findById
, find
, findAll
, list
and similar methods. This is markedly different from the Spring Data pattern where the Entity classes do not typically extend another class and the Repository interface provides these types of methods. The Repository pattern can still be used with Quarkus but it uses a class that implements PanacheRepository
instead of an interface.
@Entity
@Table(name = "country")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Country implements Serializable {
@Entity
@Table(name = "country")
@Cacheable
@RegisterForReflection
public class Country extends PanacheEntityBase implements Serializable
Spring Data provides “syntactic sugar” for a variety of queries. Queries can be built simply by adding Repository methods with the correct naming scheme.
List<User> findAllByActivatedIsFalseAndCreatedDateBefore(Instant dateTime)
And for more complex queries, the @Query annotation can be used.
@Query(value = "select distinct ticket from Ticket ticket left join fetch ticket.labels")
List<Ticket> findAllWithEagerRelationships();
Quarkus does not provide the method name query syntax. For simple add-ons to a typical list query, (i.e. an ORDER BY clause) the PanacheEntityBase
methods provide String inputs.
List<Person> persons = Person.list("order by name,birth");
More complex queries can be passed in this SQL-like syntax to the find and list methods.
With Spring Data, implement the PagingAndSortingRepository
and a paginated findAll
method is provided for the simple case.
Page<T> findAll(Pageable pageable);
In Quarkus, the finder methods return a PanacheQuery
object that can be operated on to provide pagination.
// create a query for all living persons
PanacheQuery<Person> livingPersons = Person.find("status", Status.Alive);
// make it use pages of 25 entries at a time
livingPersons.page(Page.ofSize(25));
// get the first page
List<Person> firstPage = livingPersons.list();
// get the second page
List<Person> secondPage = livingPersons.nextPage().list();
The REST resources are very similar between the two frameworks. The differences are basically syntactical and use about the same amount of code.
This is an example class declaration:
@RestController
@RequestMapping("/api")
public class AccountResource
@Path("/api")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RequestScoped
public class AccountResource
The method declarations are similar as well:
@PostMapping("/register")
@ResponseStatus(HttpStatus.CREATED)
public void registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM)
@POST
@Path("/register")
@PermitAll
public CompletionStage<Response> registerAccount(@Valid ManagedUserVM managedUserVM)
It is clear that Spring is the more mature platform and has had many more years to provide some of the ergonomics that developers have grown used to having. More code is definitely required to use Quarkus at this point. There are plenty of resources online that talk about performance gains from using Quarkus so that very well could drive the decision to try it out. Based on this introductory analysis, the learning curve does not look too steep for Quarkus. A future blog post will investigate how Quarkus handles security and other developer concerns.
My understanding is that much of the performance gains provided by Quarkus are directly tied to using the GraalVM. Fairly recently, Spring has introduced Spring Native for GraalVM that may end up making the performance gains less of a factor for choosing Quarkus.