Java contributed to making a significant impact on the history of programming like few other coding languages but, as time passes, it is constantly being sidelined by other frameworks offering different performances in terms of resources and flexibility.
In contrast, Java-based solutions are very well known and can still offer a great path to cloud-based applications such as reactive programming, serverless computing, and container-based applications.
Niklas Heidloff, IBM Developer Advocate, has written many technical blog posts in this area and thus we asked for his contribution as part of a deep dive. Niklas shares our passion for coding and finding new solutions.
“I find this work amazing because we learn new technologies every day. We talk to other developers to improve our skills. This is the best job in the world!”
Being a programmer is very exciting today, he details: “It’s so much easier to get started than in the past as you just rely on cloud or other self-service solutions, and with two clicks they free you of the code part“. And then he adds about the continuous renewal of the coding ecosystem: “The new trend in programming techniques is MVM, micro virtual machine“, explains Niklas, “and the container approach is one of the solutions offered in this area, where the key is to split the applications into modules“.
The year 2020 is a very interesting time for Java, he declares: “This language was declared dead too soon!“, he grins, “Java is still alive and kicking for several reasons. To name one, the number of enthusiasts is too high and giving up would be a shame“.
Indeed, many new initiatives have recently given more life to Java. In particular, Quarkus, upon which Niklas Heidloff predicts: “Quarkus effects will span over the next few years: it is easy and fun to use and gives Java the boost it needed“.
Put this way, Quarkus really seems the best of both worlds – Java and Cloud – to build cloud-native applications. But to make sense of it, it is necessary to know more about it and its context.
What is Quarkus?
Quarkus is a full-stack, Kubernetes-native Java framework made for Java Virtual Machines and native compilation. It optimizes Java specifically for containers and enables it to become an effective platform for serverless, cloud, and Kubernetes.
It is designed to work with popular Java standards, frameworks, and libraries like Eclipse MicroProfile, Apache Kafka, RESTEasy (JAX-RS), Hibernate ORM (JPA), Spring, Infinispan, Camel, and many more.
Quarkus is based on a CDI framework. Its dependency injection solution focuses on contexts and dependency injection, and includes an extension framework needed to configure, boot, and integrate a framework into your application. Simply put, Quarkus also offers tools to add extensions.
Designed for developers
Quarkus was built around a container-first philosophy and with an eye for developers’ enjoyment. It was designed to be easy to use right from the start as its features allow a developer to code with little to no configuration issues.
The Java framework of choice can be run in JVM mode, or compiled and run in native mode. Quarkus also supports live coding, unified imperative and reactive programming, unified configuration, and easy native executable generation. Thus, developers can check the effect of code changes in real-time thanks to live coding.
Fast startup and low memory consumption are important characteristics, independent of the execution environment. Whether your application is running on a public cloud or in an internally hosted Kubernetes cluster, you need to boost execution while keeping costs down.
Quarkus was built around a container-first philosophy. This means that it is optimized for lower memory usage and faster startup times in the following ways:
- First-class support for Graal/SubstrateVM;
- Build-time metadata processing;
- Reduction in reflection usage;
- Native image pre-boot.
Quarkus creates applications that consume 1/10th of the memory when compared to traditional Java, with a faster startup time: up to 300 times faster! Clearly, this greatly reduces the cost of cloud resources.
Imperative and reactive code
Let’s now explore reactive programming and its combination with Java’s imperative coding method. Quarkus is designed to seamlessly combine the familiar imperative style code and the non-blocking, reactive style when developing applications.
This is helpful for both Java developers who are used to working with the imperative model and don’t want to switch, and those working with a cloud-native/reactive approach. The Quarkus development model can adapt itself to whatever app you’re developing.
Quarkus has it all to be a truly effective solution for running Java in the new scenario made of serverless architecture, microservices, containers, Kubernetes, function-as-a-service (FaaS), and cloud. After all, it was created with all these things in mind.
The future is Java-driven!
“I think Quarkus is a game changer and will change the landscape of enterprise development”, says Niklas. The Java world is under a constant revolution, as the new virtual machine, OpenJ9, demonstrates. This version has a low-memory footprint, but boosts performances in full compliance to the JVM specifications. “Quarkus, together with OpenJ9, is a perfect fit for container workloads so that enterprise developers with Java skills can build modern cloud-native applications”.
Talking about containers, one of the best online resources is the Cloud Native track of the IBM Digital Dev Conference. The conference sessions detail subjects such as “Containerized workloads on the IBM cloud”, “Microservices in practice” and “Hands-on with Kubernetes”.
Resources to explore the key benefits of Quarkus
Microservices on IBM Cloud Kubernetes Service
The need for more efficient applications and better user experiences is key, today. That’s why “reactivity” is becoming more and more important in the context of cloud-native applications.
We will use toolchains in IBM Cloud, which contains CD/CI pipelines to build and deploy all microservices, and not any client-side setup.
The sample application used in this article is available as open source in GitHub as part of the cloud-native-starter project, which details how to get started with Java-based microservices. You can deploy the sample yourself in less than an hour (30 – 60 minutes).
Benefits of reactive applications
One benefit of reactive models is the ability to update web applications by sending messages rather than pulling for updates, which improves the user experience. The image below shows how a web application is updated automatically when new objects are created using REST API invocations:
Another benefit of reactive systems is efficiency. For example, reactive REST endpoints can provide much faster response times. Especially in public clouds, where costs depend on CPU, RAM, and compute durations, this model saves money. In the cloud-native-starter sample, the response times are cut in half compared to synchronous REST endpoints.
Deploying on IBM Cloud Kubernetes Service
In order to make the deployment of the sample application as easy as possible, a toolchain has been created. Client-side installations and configurations are not necessary. The toolchain installs the following components:
- PostgreSQL and admin client
- Microservices: articles, authors, web-api
- Web application
- Eclipse Orion web IDE
When all prerequisites are met, you can simply click on a button to deploy the application. For more detail, Niklas has created a GitHub repo for step-by-step instructions.
The next screenshot shows the pipeline. The log of the last job “Deploy web-app” displays all the URLs you need to access the application:
The definitions of the toolchain and the pipeline are open source and also available in GitHub which you can use as a starting point for your own toolchains.
The challenges of reactive applications
A different application will show how to operate synchronous microservices with imperative coding. For a deeper dive, Niklas has also written Development of Reactive Applications with Quarkus which offers more details.
The term “reactive” is overused and overloaded and describes different aspects, for example reactive programming, reactive systems, reactive manifesto and reactive streams. There are several frameworks which support different functionalities and use other terminologies.
In order to understand how to use these functions together, it helps to look at more complete applications with use cases that come closer to what developers need when building enterprise applications to be easily deployed on Kubernetes platforms.
A good example proposes a web application which displays links to press/blog articles with their author information in a simple web application. The web application invokes the web-api service; it implements a backend-for-frontend pattern and invokes the articles and author’s service. The articles service stores data in a Postgres database. Messages are sent between the microservices via Kafka. This diagram describes the high level architecture:
Reactive REST Endpoints for higher Efficiency
Another benefit of reactive systems and reactive REST endpoints is efficiency. This scenario describes how to use reactive systems and reactive programming to achieve faster response times. This is especially beneficial in public clouds where costs depend on CPU, RAM and compute durations, and this model saves money.
The project contains the endpoint ‘/articles’ of the web-api service in two different versions, one uses imperative code, the other one reactive code. The reactive stack of this sample provides response times that take less than half of the time compared to the imperative stack:
- Reactive: 793 ms
- Imperative: 1956 ms.
You can deep dive further by reading Efficient Reactive Programming.
Supported Kubernetes Environments
For all components and services, there are scripts that deploy and configure everything. For example, if you have Minikube installed, the setup shouldn’t take longer than 10 minutes.
- IBM Cloud Kubernetes Service
- OpenShift 4.3 on the IBM Cloud
As this tutorial demonstrates, Quarkus offers many current and future benefits to developers, it breathes new life into Java, and brings an older technology into the future.