Apache Camel and Quarkus on Red Hat OpenShift

Camel Quarkus is a subproject in the Apache Camel community that enables Camel to run on Quarkus. Apache Camel is the most popular open source community project aimed at solving all things integration. Quarkus is a Java framework tailored for OpenJDK HotSpot and GraalVM, boasting lightning-fast boot times and low memory utilization.

This article explains how Camel has evolved over time and why it is now embracing Quarkus. I've included a quick getting started guide that will show you how easy it is to create a Camel Quarkus project and experience the significant performance benefits for yourself.

Why Apache Camel is special

Apache Camel has been around for several years and predates the containers and Kubernetes era. The great advantage of Apache Camel against other integration technologies is that it was always kept very lightweight. To put it simply, it's a small Java library you include in a Java project.

Its lightness has allowed it to adjust to emerging trends quickly and fit into different runtimes (e.g., web containers, Java EE servers, OSGi, Spring Boot). Apache Camel keeps evolving and improving and shows how exceptionally well it withstands the test of time. It brings the enormous advantage of offering proven functionality built and polished over many years.

While other integration technologies were born, found initial success, and stagnated, the Apache Camel community keeps sailing ahead, reading changes in the winds well, keeping the boat tidy, and evolving new hulls and propellers when necessary (Figure 1).

Apache Camel's sailing boat navigating changes.
Figure 1. Apache Camel's sailing boat navigating changes.

Java memory usage in containers

Before Kubernetes and containers, it made sense to bundle services together inside a running JVM. Many Java engines (some known as enterprise service buses or ESBs) aggregated many integration processes to economize on infrastructure and memory consumption.

With the emergence of containers, integrations started moving from large integration servers to independent running applications and known as microservices. This was all well and good, but developers soon realized that the new approach was, among other challenges, very memory-hungry.

New languages appeared to help minimize the memory footprint but did not bring the rich functionality and libraries that Java has collected over time. If Java was the preference in the enterprise, but memory usage was problematic, it made sense to do something about it.

Welcome to Camel Quarkus

Camel Quarkus brings the Camel core library (Camel framework) and its rich collection of connectors (known as Camel components) to Quarkus. While boosting the use of Java in cloud-based applications, Quarkus also allows non-Kubernetes users to run applications with maximum performance on bare metal.

The mission of Quarkus is to run Java on minimal memory with super startup speed, thus optimizing execution on container-based platforms and reducing running costs. The following subsections explore these goals.

Performance leap

Quarkus gives Apache Camel a big performance leap and outperforms any other cloud-based Java runtime where Camel runs. Among Camel Quarkus's improvements are:

  • Subsecond startup times.
  • Low memory footprint.
  • No warmup needed.
  • Serverless characteristics.
  • Foundations for Camel K, which deploys Camel applications on Kubernetes.

Figure 2 compares the startup time of various Java deployments for two operations: a basic RESTful API call and a RESTful API call plus database access. Quarkus with native compilation is practically instantaneous. Quarkus with the regular Java just-in-time (JIT) compiler is still much faster than traditional Java. Quarkus in native mode stands out, taking just a few hundredths of a second to start up for a sample REST service.

Quarkus in native mode shows subsecond boot-up time.
Figure 2. Quarkus in native mode shows subsecond boot-up time.

Figure 3 shows memory footprints for the same operations. Quarkus in native mode again lowers consumption to very economic levels.

Quarkus's memory footprint is also much smaller than traditional runtimes.
Figure 3. Quarkus's memory footprint is also much smaller than traditional runtimes.

Live coding

An essential aspect of efficient development is feeling comfortable and productive while coding and testing—also known as developer joy. One of the key benefits of developing integrations with Camel on Quarkus is its live coding mode. In this mode, iterative trial-and-error no longer means slow cycles of compile, package, startup, then try again. Live coding mode allows you to run the build engine and make live code changes that are instantly picked up and applied, allowing you to fail and try again quickly. For example, live code updates are very helpful when you're new to Apache Camel and are still figuring things out. Live coding will accelerate the learning process.

Figure 4 illustrates how live coding mode works when coding and updating an Apache Camel route.

Under Quarkus's live coding mode, each code update triggers a rerun of the new code.
Figure 4. Under Quarkus's live coding mode, each code update triggers a rerun of the new code.

The Quarkus community has applied great expertise to simplifying code creation, which also helps developers be more productive. For example, if you're implementing an integration service, and you need to provide different configurations for different environments, Camel Quarkus allows you to define properties in one single configuration file to cover all environments.

Let's say your Camel route needs to integrate with a backend service. Define the Camel instruction with the following XML configuration, which indicates the target host through a parameter defined between curly braces:

<to uri="http:{{api.backend1.host}}/camel/subscriber/details"/>

Then, to configure your endpoint, specify the following properties in your configuration file. The first property defines the default (production) configuration value, and the second one sets the same property for the dev environment, which is activated by default when you enable live coding mode:

api.backend1.host = end1:8080
%dev.api.backend1.host = localhost:9000

Camel Quarkus on Camel 3

Camel Quarkus was born with Camel 3, the latest evolution of Apache Camel. At that point, Camel became a family of projects:

  • Camel 3: The core framework and Swiss Army knife of integration
  • Camel Quarkus: The Camel extensions for Quarkus
  • Camel K: The lightweight serverless integration platform for Kubernetes

One of the main drivers for upgrading Camel from version 2 to version 3 was to give life to Camel Quarkus and Camel K, which are, as you can already guess, oriented to running Camel on containers. Although Camel K is available only in Kubernetes environments, Camel Quarkus can run both in containers and standalone.

Camel 3 brings many internal improvements to allow it to run on Quarkus. Notably, a lot of work was done to eliminate the use of Java reflection so that Camel can run in native mode, exploited wonderfully by Quarkus, as we have seen. Another big piece of work was to modularize the core Camel framework, which allowed a significant memory footprint reduction, translating to faster startup times and execution speed.

Camel Quarkus example

Now that you understand what Camel Quarkus is, let's create an easy example and taste its enormous benefits. As usual, examples can range from simple demos to more sophisticated production-ready implementations. Here the intention is to keep things simple, walking you through the first steps into Camel Quarkus.

Prerequisites

To replicate the instructions in this section, ensure that the following requirements are installed on your system:

  • JDK 11+ (any distribution)
  • Maven 3.6.2+
  • Optional: GraalVM 21.3.0 for native compilation

Configure the generator

The Quarkus code generator is a great place to start. Filter entries using the camel tag as shown in Figure 5. The interface will automatically display all the Apache Camel extensions available for Quarkus.

Search for "camel" extensions in the Quarkus code generator.
Figure 5. Search for "camel" extensions in the Quarkus code generator.

We will create a dummy "hello world" example using the timer component and log a simple message on the screen. We will create a couple of Camel routes, one using the Java DSL (Camel's domain-specific language for Java) and the other using the XML DSL.

From the list, pick the Camel Timer and Camel XML extensions. The interface shows what you've selected (Figure 6). Click the red button labeled Generate your application to generate and download the project.

In the Quarkus code generator, select the Camel Timer and Camel XML extensions.
Figure 6. In the Quarkus code generator, select the Camel Timer and Camel XML extensions.

Work on the Camel code

Download the ZIP file, unpack the project, and add the following Java class definition containing a Camel Java DSL route to the src/main/java/org/acme/TimerRoute.java file:

package org.acme;
import org.apache.camel.builder.RouteBuilder;

public class TimerRoute extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("timer:java?period=1000").id("route-java")
        .log("Hello World from Java DSL");
    }
}

Then start the Camel Quarkus application in development mode by entering in your terminal:

mvn clean quarkus:dev

When Quarkus starts, you should see the following message, repeated over and over:

INFO [route-java] ... Hello World from Java DSL

Modify the code

Running the Quarkus Camel application in development mode allows you to make code modifications that Quarkus picks up and applies on the fly. Let's see how that works by including a second Camel route using the XML DSL. Add the following XML definition to src/main/resources/routes.xml:

<routes xmlns="http://camel.apache.org/schema/spring">

    <route id="route-xml">
        <from uri="timer:xml?period=1000"/>
        <log message="Hello World from XML DSL"/>
    </route>

</routes>

Edit src/main/resources/application.properties to add the following property, which tells Camel where to find XML route definition:

camel.main.routes-include-pattern = classpath:routes.xml

When you click Save, Quarkus detects the change and automatically restarts, adding the new Camel XML definition. The animated GIF in Figure 7 shows how the restart is triggered.

In live coding mode, Quarkus restarts on each code update with the new code definition
Figure 7. In live coding mode, Quarkus restarts on each code update with the new code definition.

You should see messages for both the Java and XML DSLs in your terminal:

INFO [route-java] ... Hello World from Java DSL
INFO [route-xml] ... Hello World from XML DSL

Measuring performance

If you look at the details in the logs, you can see how quickly Apache Camel and Quarkus restarted:

... Apache Camel 3.11.1 (camel-12) started in 4ms
...(powered by Quarkus 2.2.3.Final-redhat-00013) started in 0.544s.


But the true performance achievement of Quarkus is demonstrated when you build the project in native mode. Run the following command:

mvn clean package -Pnative

The build process takes a few minutes to complete. When done, run the native application with:

./target/*-runner

If you inspect the application output carefully, you'll see the time consumed upon startup. The following log extracts show the supersonic startup time of Camel Quarkus running in native mode:

... Apache Camel 3.11.1 (camel-1) started in 1ms
...(powered by Quarkus 2.2.3.Final-redhat-00013) started in 0.032s.


What about memory usage? Run the following command to inspect the resident set size (RSS), which reflects the memory allocation to the process in physical RAM:

ps -o rss,command

The output of this command should appear something like:

25148 ./code-with-quarkus-1.0.0-SNAPSHOT-runner


The number shown in bold indicates that my RSS usage almost reaches 25MB (1024KB = 1MB).

Conclusion

Quarkus is the new air wind harnessed by Apache Camel 3. Camel Quarkus is a key technological evolution that brings a new dimension to Apache Camel. Quarkus opens the doors to extremely fast and reactive cloud integrations, performance leaps, more developer joy, and the container-first ethos that Quarkus embodies.

Check out this Camel Quarkus article for a more advanced integration example deployed in Red Hat OpenShift

Camel Quarkus powers Camel K. Want to learn more about developing integrations with Camel K? Read this article about how to normalize web services with Camel K and AtlasMap.

Last updated: August 14, 2023