DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Building a Simple RAG Application With Java and Quarkus
  • Simplify Java Persistence Using Quarkus and Hibernate Reactive
  • Build Even Faster Quarkus Applications With fast-jar
  • AOT Compilation Make Java More Power

Trending

  • Driving DevOps With Smart, Scalable Testing
  • How Kubernetes Cluster Sizing Affects Performance and Cost Efficiency in Cloud Deployments
  • How to Build Real-Time BI Systems: Architecture, Code, and Best Practices
  • Data Lake vs. Warehouse vs. Lakehouse vs. Mart: Choosing the Right Architecture for Your Business
  1. DZone
  2. Coding
  3. Java
  4. Thoughts on Quarkus

Thoughts on Quarkus

What are the benefits and shortcomings of using Quarkus?

By 
Sebastian Daschner user avatar
Sebastian Daschner
·
Apr. 19, 19 · Analysis
Likes (15)
Comment
Save
Tweet
Share
44.1K Views

Join the DZone community and get the full member experience.

Join For Free

Quarkus, the new “supersonic, subatomic” Java framework is currently getting a lot of attention. The ideas behind this build and runtime tool are indeed more than interesting for the future of enterprise Java. What are the benefits and shortcomings of using Quarkus? Let's find out.

Getting Rid of Dynamics

Quarkus takes the reasoning that most of the dynamics of an enterprise Java runtime is not really required in a containerized world. Once you build your application to a container image, the functionality is usually not supposed to change. All of the dynamics that an enterprise container brings allows for very powerful and flexible programming and deployment models, but once our applications have been started inside containers, they typically don’t change anymore.

The approach that Quarkus takes is to tailor a runtime that only contains what your application needs and to boil down most of the dynamics of an enterprise runtime. Enterprise Java code heavily relies on Inversion of Control (IoC), aka “don’t call us, we call you.” Think of dependency injection alà @Inject, HTTP resources with @Path and @GET, or event observers with @Observes. We developers declaratively specify what should happen and the implementation makes sure it does. This allows an extremely productive programming model but also comes with heavy lifting at runtime, since someone has to put together all these loose ends. Now, the idea is that if our applications aren’t supposed to mutate at runtime, most of these dynamics can be resolved at build time. The resulting code can then mainly consist of direct invocations; all of the magic is being boiled down.

Now, is this the same result that one achieved in the past with a (from today’s view) cumbersome enterprise framework that didn’t support IoC and required to directly invoke functionality in our code? From a developer’s perspective, not at all. In our code, we still use the same effective, declarative approaches, the same annotations; the build process takes care of bringing the dynamics back to earth.

Quarkus also supports to build native executables with GraalVM. With that approach, we use ahead-of-time (AOT) compilation to pre-build and compile our applications to native executables that don’t need to dynamically scan and load all our classes into a JVM. The resulting executable starts up very quickly and comes with lower resources consumption compared to a regular JVM.

Power of Standards

Looking at Quarkus, what I find the most appealing is that it’s built on top of known Enterprise standards, such as CDI, JAX-RS, and many more. Instead of a fully-fledged application server, we run our applications in an optimized runtime, either via a native executable or using a Java runtime.

A lot of uprising enterprise frameworks require developers to, once again, learn new APIs and are, sometimes more sometimes less, reinventing the wheel, how to implement REST endpoints for example. However, from a developer’s and project’s point of view, I don’t see the benefit of re-learning and re-writing applications when existing APIs and solutions would suffice. With the approach that Quarkus takes, developers can write and take an application that is based on CDI, JAX-RS, and JPA, for example, and optimize it by changing the runtime to Quarkus.

Extensions to Enterprise Java

Besides what is contained in Java Enterprise, Quarkus also extends the available functionality where this could be required in projects. Aside from the supported Java EE and MicroProfile specifications, there are, for example, Quarkus extensions for reactive messaging, Vert.x, or Camel. Vert.x’s EventBus type, for instance, is injectable via @Inject. This matches the developer experience that we’re used to in EE.

I like the approach of starting with known enterprise APIs and extending them with what applications require, furthermore, by keeping the same declarative approaches.

Serverless Enterprise Java

One of the unique selling points of Quarkus, and running Java applications natively, is the extremly short startup time. Like seriously, everything that starts in a few milliseconds is a gamechanger for requirements, where we need to quickly start-up and tear down our applications.

That is still one of the biggest limitations in an otherwise suitable-for-almost-everything Java world. Performance-wise, the JVM needs a huge amount of time to start up, let alone to warm up the HotSpot engine and to reach its full throughput. Fair enough, there’s a reason for that since the runtime has mostly been optimized for throughput in long-running processes. With the demand that applications should aim to start-up quickly, as in that fast so that users can wait for it, it’s simply not enough to start a JVM in the normal way.

The mentioned approaches of AOT compilation enables us to write our Java applications while executing them as native images. By doing so, we enable our Java workload to be executed in “serverless” environments where we can scale our workload to zero and be able to start up quickly without punishing the user with initial startup time.

However, as often in practice, life’s not quite that easy. GraalVM doesn’t support the whole feature set of a regular JVM. For example, it doesn’t support Reflection in the usual way and a lot of enterprise runtimes wouldn’t run out-of-the-box as a native executable.

That being said, it’s pretty impressive how much work the friends at Red Hat have put into the development of Quarkus, by developing the implementations with the limitations of this runtime in mind. Only this enables us to combine these pieces and run our Java Enterprise app in a native way. A Quarkus application also runs well on a normal JVM, by starting up “fast enough,” at least in my eyes, in way less than one second.

Despite all that great news for Enterprise Java, and the requirement of scaling to zero and thus starting up quickly, from my point of view, startup time is not everything. While this new movement is certainly interesting, we just shouldn’t forget that the vast majority of enterprises are running, and probably will continue running, their workload for a longer period of time. However, the approach of getting rid of most of the “dynamics” at runtime also has a positive impact on the overall resource consumption and is certainly promising.

But, in my opinion, the native startup time is not even the biggest benefit.

Development Turnaround Time: “Coding That Sparks Joy”

Quarkus allows us developers to modify and test our business code with extremely fast hot-reloads. The quarkus:dev goal of the Maven plugin enables us to change and save a file, the framework reloads the classes and swaps the behavior inside the running application, in an automated approach. We can simply re-execute and test the changed functionality after a few milliseconds, which is, in human reaction-time, instantly. The turnaround time of the development cycle and the feedback loop thus becomes as short as it will get. As my friend Edson Yanaga puts it: “This is coding that sparks joy.” I fully agree.

In general, I’m a huge fan of short latencies. The mantra of fighting latency is what I believe made a lot of the Google services a joy to use. In general, when coding, we want to get and stay in the flow. The developer thinking the time is very precious, and we don’t want to be disrupted from that flow and wait for more than very few seconds; otherwise, one gets distracted, fetches yet another coffee, or worse, looks on social media, and there goes your attention.

In my eyes, this minimal turnaround time is the biggest advantage of the Quarkus framework. However, even without Quarkus, if you use a modern application container and some tooling, you can already achieve hot-redeployment times that enable a keep-in-the-flow development mode. For example, Open Liberty can deploy applications in less than a second, and when combined with tooling such as WAD, we can really improve our turnaround times, as described in this video.

Some notes on integration testing: What is also very helpful is that the quick startups of the overall Quarkus applications make tests actually much more suited for integration tests on a deployment level, rather than a code level. That is, a single application is deployed and end-to-end-tested using the application’s communication interfaces. However, one of the major causes for slow build times are long-running test phases that start up the application, or parts of it, for every. single. test run. Even with low startup times provided by Quarkus, this impact becomes huge, once more and more test scenarios become part of the pipeline. What we should do, in general, is to define a single or at most a few deployments during our test suite execution where we end-to-end-test our application without restarting the running application-under-test in between. This is regardless of whether we use Quarkus' capabilities for testing or a dedicated test project that hammers a fired-up application.

Continuous Delivery Turnaround Time

One of the downsides of native builds alà GraalVM is that this build takes a looooong time. Depending on your machine, it can take thirty seconds and more. It can even be much longer than what we are used to in a Java world. In our development pipeline, this implies that we don’t want to execute the native build on each code change, only inside the Continuous Delivery pipeline. Even still, we need to take into account that this will slow down our overall pipeline execution time that, otherwise, could be executed faster. Following the mantra of building our application only once and fully testing that very build before we ship to production, this implies that also the end-to-end/system/acceptance test turnaround times increase.

Besides native executables, Quarkus also supports thin deployment artifact, as thin JARs, which only contain the actual business logic classes, which are developed by us. This approach is possible with Quarkus since it separates the concerns of libraries and our own code. Have a look at the size and contents of the built *-runner.jar. The implementation and required libraries are contained under the lib/ directory. Just as with regular Java Enterprise applications, this allows us to leverage the benefits of Docker by optimizing for the copy-on-write file system image layers. If you know a little about these image layers, you’ll notice that this certainly makes sense in a containerized world. The build and transmission times of the container image also affect the overall build execution time. In this case, thin deployment artifacts offer the best possible experience. From my experience, the overall image sizes seldomly matter. What matters is how quickly can we re-build and re-transmit the layers that actually change. Even with tiny native images, these sizes and times are still orders of magnitude larger compared to a thin deployment artifact.

In projects, we need to make this trade-off between pipeline execution times and container startup time. Besides the approach of scaling to zero, deployment scenarios should make use of some form of blue-green deployment, in order to avoid downtime for users, anyway. With that in mind, production startup time becomes less of an issue, since the old version will always stay active, until the new one is ready to roll. If you’re involved in an enterprise project with enough users that scaling to zero is not something to think about, but quickly shipping new versions to production is, the approach of thin deployment artifacts might be more suitable.

Current Limitations

One of the current framework limitations is that Quarkus doesn’t support the full set of some of the EE standards yet. EJBs, for example, aren’t supported. However, transactions are supported and some other functionality can be substituted with Quarkus' own features. One example is scheduling where Quarkus ships its own @Scheduled annotation. This seems like a reasonable approach to try to realize the functionality that projects might need and delivering a framework that already supports the, from my point of view, majority of required functionality.

However, Quarkus is moving very quickly, so let’s see how these gaps are closed. Again, I believe it’s very impressive how mature and exhaustive this framework already looks.

The Maven plugin declaration, and especially how it’s being advertised on the Quarkus documentation, is something else that could be improved. A lot of folks seem to be fans of putting in quite an amount of XML into their pom.xml, however, I’m not that much. I prefer to maintain a clearer separation of concerns of our Java application and not letting Maven “build everything.” If we allow the projects to use Maven’s defaults, we keep the required LoCs inside the pom.xml to a bare minimum and let everything on top of that be handled by the CI infrastructure. With Quarkus, you can at least get rid of the most of its pom.xml definition and only define and build the native image in your CI pipeline, for example. Then, it’s possible to boil down the pom.xml a bit.

However, the documentation promises that there’s a native CLI “coming soon,” which sounds promising to me.

Conclusion

Quarkus takes cloud-native Enterprise Java to the next level and enables scenarios that haven’t been possible before, especially in regard to application startup times. If you’re planning to deliver scale to zero approaches, this is certainly a technology that you want to have a look into.

I very much like how Quarkus follows up on the approaches that a few technologies took before, takes them further, and delivers a single framework, everything under one umbrella. This makes it easy for developers to get started and use enterprise standards that they might already be familiar with, such as CDI or JAX-RS. In my opinion, this is a big benefit: not trying to reinvent the enterprise world and using familiar technology, but with a highly-optimized implementation.

As a developer, I find the AOT compilations and other JVM optimizations very interesting in general. You might also have a look at the OpenJ9 JVM and its optimizations; maybe combining that runtime with the JVM execution mode of a Quarkus application would be interesting.

For a quick turnaround developer experience with "plain" Java EE, you can have a look at WAD and how to integrate it in Docker.

Quarkus application Java (programming language) Continuous Integration/Deployment

Published at DZone with permission of Sebastian Daschner. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Building a Simple RAG Application With Java and Quarkus
  • Simplify Java Persistence Using Quarkus and Hibernate Reactive
  • Build Even Faster Quarkus Applications With fast-jar
  • AOT Compilation Make Java More Power

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!