What is Quarkus
Quarkus is a full-stack, Kubernetes-native Java framework that was developed by Red Hat. It first appeared in early 2019, aimed at optimizing Java specifically for containers and enabling it to become an effective platform in serverless environments.
The motivation behind Quarkus was to breathe new life into the Java ecosystem for modern cloud-native applications. It seeks to overcome the traditional shortcomings of Java, like slow startup time and high memory consumption, which are particularly notable in containerized environments. Quarkus achieves this through ahead-of-time (AOT) compilation which drastically reduces the runtime memory overhead and speeds up the startup time, making Java a more competitive choice in the modern landscape of microservices and serverless architectures.
What makes Quarkus distinct, especially under the guidance of Red Hat, is its live coding feature which allows developers to see changes in real-time without the need for redeploys, enhancing the developer experience greatly. Additionally, Quarkus is designed to work seamlessly with popular Java standards, frameworks, and libraries, meaning that developers don’t have to learn new APIs to start benefiting from it. It integrates effortlessly with Kubernetes and OpenShift, promoting a simplified and productive development process, especially in cloud-native environments.
Furthermore, it emphasizes unifying imperative and reactive programming models, bringing in a new paradigm that is more flexible and powerful, catering to a broader range of use-cases and accommodating a larger audience of developers who are familiar with different programming models.
In essence, with the development of Quarkus, Red Hat has propelled Java into the modern age, making it a strong contender in the cloud-native development space, fostering quicker, more efficient, and scalable application development.
Why you should use Quarkus
we’re talking about Quarkus, Spring Boot, and Micronaut. These guys are like the superheroes of the Java ecosystem, each with its own superpower!
Spring Boot, the seasoned veteran in the group, has been the go-to for building Java applications for quite a while now. It comes packed with a rich set of libraries and a massive community support, which makes it pretty robust and versatile. But, as it’s quite mature, it can sometimes feel a bit too heavy, especially when you’re trying to whip up microservices that are lean and mean.
Then enters Micronaut, which was like a breath of fresh air when it appeared on the scene. It came in swinging, offering quicker startup times and lower memory footprint compared to Spring Boot, thanks to its ahead-of-time (AOT) compilation. It kind of shook things up, showing that Java applications can indeed be lightweight and nimble.
Now, let’s talk about the new kid on the block, Quarkus. Developed by Red Hat, it kind of took the Java world by storm around 2019. It’s like it looked at what Spring Boot and Micronaut were doing and said, “Hold my coffee!” Quarkus further ramps up the efficiency game, offering blisteringly fast startup times and incredibly low memory usage. It’s tailor-made for containerized environments like Kubernetes, making it a rockstar in the cloud-native development arena.
But here’s where Quarkus really shines - its live coding feature is nothing short of a game-changer. Imagine being able to see the changes to your code in real-time, without those pesky redeploys. It’s like having a conversation with your application, which seriously ramps up productivity.
So, why should you consider hitching your wagon to Quarkus? Well, it’s kind of bringing sexy back to Java. It’s lightweight, it’s nimble, and it’s just perfect for the modern, containerized world where resources are at a premium. Not to mention, it marries the best of both worlds – the imperative and reactive programming models – giving you the flexibility to code the way you like it.
In a nutshell, if you’re looking to build microservices that are not just efficient but also fun to work with, you might want to give Quarkus a whirl. It’s fresh, it’s exciting, and it might just be the spark that reignites your passion for Java development.
So there you have it, a quick glimpse into the cool, modern world of Java frameworks. Each has its strengths, but Quarkus seems to be nudging ahead with its innovative approach to making Java fun and efficient again. Give it a shot, and you might just find it to be a breath of fresh air in your development adventures!
Development
Quarkus provides a convenient way for local development, using quarkus dev
command to start up the app in local with OpenAPI available to test the Rest endpoints. In addition, Quarkus allows us to use different dev
profiles by specifying the application.properties
, e.g. we could use quarkus dev -Dquarkus.profile=dev
to start the app using application-dev.properties
. Thus we could customize the development environment with database connections or listening port.
Once the app starts up, the changes to the code would be lively deployed so we don’t have to rebuild and redeploy. And it is very easy to add debugger to Quarkus (# How to debug a Quarkus application with IntelliJ IDEA).
Dependency Injection
Quarkus using Jarkarta for DI and all it needs is adding the proper annotation like @ApplicationScoped
or @Singleton
. But the official site mainly uses @ApplicationScoped
. This is a great article explaining the different scopes in Quarkus.
Exception Handler
Quarkus also supports exception handler shown as below:
@Provider
public class CustomExceptionHandler implements ExceptionMapper<CustomException> {
private final static Logger logger = LoggerFactory.getLogger(CustomExceptionHandler.class);
@Override
public Response toResponse(CustomException e) {
logger.error("cannot complete the request.", e);
if (e.getCause() instanceof RecordAlreadyExistingException
|| e.getCause() instanceof NotFoundException
|| e.getCause() instanceof IllegalArgumentException) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(new CustomException.ErrorResponseBody(e.getCause().getMessage()))
.build();
} else {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new CustomException.ErrorResponseBody("Something unexpected happened. Try again"))
.build();
}
}
}
We could replace CustomException
with any exception type we want to further process and map to a response.
Health Check
Health check is also easy. We just need to add the Liveness
annotation and implements the interface HealthCheck
. Quarkus will provide the health check endpoint at {http://localhost:8080}/q/health/live
.
@Liveness
@ApplicationScoped
public class SimpleHealthCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("I am healthy");
}
}
Database Connection
You could use Hibernate via Panache if you want to use ORM (tutorial). But I personally like using Jooq to interact with database. And it is also very easy (example POM):
- Install the required dependency
- flyway
- Jooq
- Generate the Jooq records
DSLContext
could be directly inject
Test
The best part I love with Quarkus is its devservice
which is a built-in test container allowing us to test the transactions. We could set up the database connection in the application.properties
in test folder or a separate test profile class which could be specified for a particular test class. In below, I set up the MySQL db for devservice
and flyway
to create the schemas for transaction tests.
quarkus.datasource.db-kind=mysql
quarkus.datasource.devservices.db-name=minance
quarkus.datasource.devservices.username=quarkus
quarkus.datasource.devservices.password=quarkus
quarkus.datasource.devservices.port=30301
quarkus.flyway.enabled=true
quarkus.flyway.clean-at-start=true
quarkus.flyway.migrate-at-start=true
quarkus.flyway.username=quarkus
quarkus.flyway.password=quarkus
quarkus.flyway.jdbc-url=jdbc:mysql://127.0.0.1:30301/minance?createDatabaseIfNotExist=true
quarkus.flyway.default-schema=minance
Build & Deploy
Since Quarkus is meant to be a cloud native framework, it comes with several Dockerfile
for building a docker image. For example, we could firstly run quarkus build
to build an exectuatble jar and build a docker image using: docker build --platform linux/amd64 -f src/main/docker/Dockerfile.jvm -t repo/image:0.0.1 .
for amd64 platform.
Then we could deploy it by running docker run -p 8080:8080 repo/image:0.0.1
to start the container.