Chapter 4. Getting Started with Red Hat build of Apache Camel for Quarkus
This guide introduces Red Hat build of Apache Camel for Quarkus, the various ways to create a project and how to get started building an application using Red Hat build of Apache Camel for Quarkus:
4.1. Red Hat build of Apache Camel for Quarkus overview
Red Hat build of Apache Camel for Quarkus brings the integration capabilities of Apache Camel and its vast component library to the Quarkus runtime.
The benefits of using Red Hat build of Apache Camel for Quarkus include the following:
- Enables users to take advantage of the performance benefits, developer joy and the container first ethos which Quarkus provides.
- Provides Quarkus extensions for many of the Apache Camel components.
- Takes advantage of the many performance improvements made in Camel, which results in a lower memory footprint, less reliance on reflection and faster startup times.
4.2. Building your first project with Red Hat build of Apache Camel for Quarkus
4.2.1. Overview
You can use code.quarkus.redhat.com to generate a Quarkus Maven project which automatically adds and configures the extensions that you want to use in your application.
This section walks you through the process of creating a Quarkus Maven project with Red Hat build of Apache Camel for Quarkus including:
- Creating the skeleton application using code.quarkus.redhat.com
- Adding a simple Camel route
- Exploring the application code
- Compiling the application in development mode
- Testing the application
4.2.2. Generating the skeleton application with code.quarkus.redhat.com
You can bootstrap and generate projects on code.quarkus.redhat.com.
The Red Hat build of Apache Camel for Quarkus extensions are located under the 'Integration' heading.
If you need additional extensions, use the 'search' field to find them.
Select the component extensions that you want to work with and click 'Generate your application' to download a basic skeleton project.
You can also push the project directly to GitHub.
For more information about using code.quarkus.redhat.com
to generate Quarkus Maven projects, see Creating a Quarkus Maven project using code.quarkus.redhat.com in the Getting started with Red Hat build of Quarkus guide.
Procedure
In the code.quarkus.redhat.com website, select the following extensions:
-
camel-quarkus-rest
-
camel-quarkus-jackson
camel-quarkus-direct
NoteDo not compile the application on code.quarkus.redhat.com (in the final step of the procedure). Instead, use the compile command described in the Section 4.2.5, “Development mode” section below.
-
Navigate to the directory where you extracted the generated project files from the previous step:
cd <directory_name>
$ cd <directory_name>
Copy to Clipboard Copied!
4.2.3. Explore the application code
The application has two compile dependencies which are managed within the com.redhat.quarkus.platform:quarkus-camel-bom
that is imported in <dependencyManagement>
.:
pom.xml
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id> <quarkus.platform.group-id>com.redhat.quarkus.platform</quarkus.platform.group-id> <quarkus.platform.version> <!-- The latest 3.20.x version from https://maven.repository.redhat.com/ga/com/redhat/quarkus/platform/quarkus-bom --> </quarkus.platform.version> ... <dependency> <groupId>${quarkus.platform.group-id}</groupId> <artifactId>${quarkus.platform.artifact-id}</artifactId> <version>${quarkus.platform.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>${quarkus.platform.group-id}</groupId> <artifactId>quarkus-camel-bom</artifactId> <version>${quarkus.platform.version}</version> <type>pom</type> <scope>import</scope> </dependency>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>com.redhat.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>
<!-- The latest 3.20.x version from https://maven.repository.redhat.com/ga/com/redhat/quarkus/platform/quarkus-bom -->
</quarkus.platform.version>
...
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-camel-bom</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
For more information about BOM dependency management, see Developing Applications with Red Hat build of Apache Camel for Quarkus
The application is configured by properties defined within src/main/resources/application.properties
, for example, the camel.context.name
can be set there.
4.2.4. Adding a simple Camel route
In this example, we use the simple example from the camel-quarkus-examples repository. It consists of the two simple classes Fruit.java
, Legume.java
and the route definitions Routes.java
.
Procedure
-
Create a file named
Fruit.java
in thesrc/main/java/org/acme/
subfolder. Add the class as shown in the following code snippet:
Fruit.java
package org.acme.rest.json; import java.util.Objects; import io.quarkus.runtime.annotations.RegisterForReflection; /** * A REST entity representing a fruit. */ @RegisterForReflection // Lets Quarkus register this class for reflection during the native build public class Fruit { private String name; private String description; public Fruit() { } public Fruit(String name, String description) { this.name = name; this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public boolean equals(Object obj) { if (!(obj instanceof Fruit)) { return false; } Fruit other = (Fruit) obj; return Objects.equals(other.name, this.name); } @Override public int hashCode() { return Objects.hash(this.name); } }
package org.acme.rest.json; import java.util.Objects; import io.quarkus.runtime.annotations.RegisterForReflection; /** * A REST entity representing a fruit. */ @RegisterForReflection // Lets Quarkus register this class for reflection during the native build public class Fruit { private String name; private String description; public Fruit() { } public Fruit(String name, String description) { this.name = name; this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public boolean equals(Object obj) { if (!(obj instanceof Fruit)) { return false; } Fruit other = (Fruit) obj; return Objects.equals(other.name, this.name); } @Override public int hashCode() { return Objects.hash(this.name); } }
Copy to Clipboard Copied! -
Create a file named
Legume.java
in thesrc/main/java/org/acme/
subfolder. Add the class as shown in the following code snippet:
Legume.java
package org.acme.rest.json; import java.util.Objects; import io.quarkus.runtime.annotations.RegisterForReflection; /** * A REST entity representing a legume. */ @RegisterForReflection // Lets Quarkus register this class for reflection during the native build public class Legume { private String name; private String description; public Legume() { } public Legume(String name, String description) { this.name = name; this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public boolean equals(Object obj) { if (!(obj instanceof Legume)) { return false; } Legume other = (Legume) obj; return Objects.equals(other.name, this.name); } @Override public int hashCode() { return Objects.hash(this.name); } }
package org.acme.rest.json; import java.util.Objects; import io.quarkus.runtime.annotations.RegisterForReflection; /** * A REST entity representing a legume. */ @RegisterForReflection // Lets Quarkus register this class for reflection during the native build public class Legume { private String name; private String description; public Legume() { } public Legume(String name, String description) { this.name = name; this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public boolean equals(Object obj) { if (!(obj instanceof Legume)) { return false; } Legume other = (Legume) obj; return Objects.equals(other.name, this.name); } @Override public int hashCode() { return Objects.hash(this.name); } }
Copy to Clipboard Copied! -
Create a file named
Routes.java
in thesrc/main/java/org/acme/
subfolder. Add a Camel Rest route as shown in the following code snippet:
Routes.java
package org.acme.rest.json; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.model.rest.RestBindingMode; /** * Camel route definitions. */ public class Routes extends RouteBuilder { private final Set<Fruit> fruits = Collections.synchronizedSet(new LinkedHashSet<>()); private final Set<Legume> legumes = Collections.synchronizedSet(new LinkedHashSet<>()); public Routes() { /* Let's add some initial fruits */ this.fruits.add(new Fruit("Apple", "Winter fruit")); this.fruits.add(new Fruit("Pineapple", "Tropical fruit")); /* Let's add some initial legumes */ this.legumes.add(new Legume("Carrot", "Root vegetable, usually orange")); this.legumes.add(new Legume("Zucchini", "Summer squash")); } @Override public void configure() throws Exception { restConfiguration().bindingMode(RestBindingMode.json); rest("/fruits") .get() .to("direct:getFruits") .post() .type(Fruit.class) .to("direct:addFruit"); rest("/legumes") .get() .to("direct:getLegumes"); from("direct:getFruits") .setBody().constant(fruits); from("direct:addFruit") .process().body(Fruit.class, fruits::add) .setBody().constant(fruits); from("direct:getLegumes") .setBody().constant(legumes); } }
package org.acme.rest.json; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.model.rest.RestBindingMode; /** * Camel route definitions. */ public class Routes extends RouteBuilder { private final Set<Fruit> fruits = Collections.synchronizedSet(new LinkedHashSet<>()); private final Set<Legume> legumes = Collections.synchronizedSet(new LinkedHashSet<>()); public Routes() { /* Let's add some initial fruits */ this.fruits.add(new Fruit("Apple", "Winter fruit")); this.fruits.add(new Fruit("Pineapple", "Tropical fruit")); /* Let's add some initial legumes */ this.legumes.add(new Legume("Carrot", "Root vegetable, usually orange")); this.legumes.add(new Legume("Zucchini", "Summer squash")); } @Override public void configure() throws Exception { restConfiguration().bindingMode(RestBindingMode.json); rest("/fruits") .get() .to("direct:getFruits") .post() .type(Fruit.class) .to("direct:addFruit"); rest("/legumes") .get() .to("direct:getLegumes"); from("direct:getFruits") .setBody().constant(fruits); from("direct:addFruit") .process().body(Fruit.class, fruits::add) .setBody().constant(fruits); from("direct:getLegumes") .setBody().constant(legumes); } }
Copy to Clipboard Copied! For more information about this example, see camel-quarkus-examples repository.
4.2.5. Development mode
mvn clean compile quarkus:dev
$ mvn clean compile quarkus:dev
This command compiles the project, starts your application, and lets the Quarkus tooling watch for changes in your workspace. Any modifications you make to your project will automatically take effect in the running application.
You can check the application in your browser. (For example, for the rest-json
sample application, access http://localhost:8080/fruits
)
If you change the application code, for example, change 'Apple' to 'Orange', your application automatically updates. To see the changes applied, refresh your browser.
Refer to Quarkus documentation Development mode section for more details about the development mode.
../camel-extensions-development/proc-testing-your-first-camel-extensions-for-quarkus-project.adoc
4.2.6. Packaging and running the application
4.2.6.1. JVM mode
Procedure
Run
mvn package
to prepare a thinjar
for running on a stock JVM:mvn clean package ls -lh target/quarkus-app
$ mvn clean package $ ls -lh target/quarkus-app ... -rw-r--r--. 1 user user 238K Oct 11 18:55 quarkus-run.jar ...
Copy to Clipboard Copied! NoteThe thin
jar
contains just the application code. You also need the dependencies intarget/quarkus-app/lib
to run it.Run the jar as follows:
java -jar target/quarkus-app/quarkus-run.jar
$ java -jar target/quarkus-app/quarkus-run.jar ... [io.quarkus] (main) Quarkus started in 1.163s. Listening on: http://[::]:8080
Copy to Clipboard Copied!
The boot time should be around a second.
4.2.6.2. Native mode
Procedure
To prepare a native executable, do as follows:
Run the command
mvn clean package -Pnative
:mvn clean package -Pnative ls -lh target
$ mvn clean package -Pnative $ ls -lh target ... -rwxr-xr-x. 1 user user 46M Oct 11 18:57 code-with-quarkus-1.0.0-SNAPSHOT-runner ...
Copy to Clipboard Copied! NoteThe
runner
has no.jar
extension and has thex
(executable) permission set. You can run it directly:./target/*-runner
$ ./target/*-runner ... [io.quarkus] (main) Quarkus started in 0.013s. Listening on: http://[::]:8080 ...
Copy to Clipboard Copied! The application started in 13 milliseconds.
View the memory usage with the
ps -o rss,command -p $(pgrep code-with)
command :ps -o rss,command -p $(pgrep code-with)
$ ps -o rss,command -p $(pgrep code-with) RSS COMMAND 65852 ./target/code-with-quarkus-1.0.0-SNAPSHOT-runner
Copy to Clipboard Copied! The application uses 65 MB of memory.
See Producing a native executable in the Compiling your Quarkus applications to native executables guide for additional information about preparing a native executable.
Quarkus Native executable guide contains more details, including steps for creating a container image.