Let's have a look at what's new in Camel 3 with an example project which shows how to run a Camel 3 standalone via the built-in Main class. This example also demonstrates how you can configure the Camel application via Camel built-in dependency-injection that supports binding via the @BindToRegistry and @PropertyInject annotations.
Apache Camel 3 is a new family of products which include:
- Camel 3: The core integration framework
- Camel K: A lightweight Serverless Integration Platform Camel on Kubernetes & Knative
- Camel Quarkus: Camel extensions for Quarkus Optimized JVM & Native compiled Java (GraalVM)
camel-core:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
</dependency>
This contains all camel core dependencies (33 jars) and it's what you will probably need when migrating from Camel 2.x
camel-core-engine:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core-engine</artifactId>
</dependency>
This contains only the core camel dependencies (12 jars).
Creating a sample project.
Apache Camel is distributed with the following archetypes: https://camel.apache.org/manual/latest/camel-maven-archetypes.html
We will be using the camel-archetype-java to generate a sample project:
mvn archetype:generate \ -DarchetypeGroupId=org.apache.camel.archetypes \ -DarchetypeArtifactId=camel-archetype-java \ -DarchetypeVersion=3.0.0 \ -DgroupId=com.mastertheboss.camel \ -DartifactId=camel-demo \ -Dversion=1.0-SNAPSHOT
The project will be created with some sample classes. In our example, we will however make it a bit more interesting by adding some Property Injection and we will also use Camel Main to run it. First of all, let's add a Route to the Project:
package com.mastertheboss.camel;
import org.apache.camel.builder.RouteBuilder;
public class MyRouteBuilder extends RouteBuilder {
public void configure() {
from("quartz:foo?cron={{myCron}}").bean("greetingBean", "hello").process((exchange) -> {
exchange.getIn().setBody(exchange.getIn().getBody(String.class).toUpperCase());
}).log("${body}");
}
}
This route will a Cron-based route, where the Message is constructed from the GreetingBean's hello method and the final result is uppercased.
Below we include the GreetingBean class:
package com.mastertheboss.camel;
public class GreetingBean {
private String hi;
public GreetingBean(String hi) {
this.hi = hi;
}
public String hello() {
return hi + " how are you?";
}
}
Then, in order to create an instance of the GreetingBean, we will be using a Configuration class which injects the property "hi" from the configuration into the Bean:
package com.mastertheboss.camel;
import org.apache.camel.BindToRegistry;
import org.apache.camel.PropertyInject;
public class CustomConfiguration {
@BindToRegistry
public GreetingBean greetingBean(@PropertyInject("hi") String hi) {
// this will create an instance of this bean with the name of the method (eg myBean)
return new GreetingBean(hi);
}
public void configure() {
// this method is optional and can be removed if no additional configuration is needed.
}
}
Then, our Camel Main class, which also includes a main method so it can be run also from within your IDE:
package com.mastertheboss.camel;
import org.apache.camel.main.Main;
/**
* A Camel Application
*/
public class MainApp {
/**
* A main() so we can easily run these routing rules in our IDE
*/
public static void main(String... args) throws Exception {
// use Camels Main class
Main main = new Main();
main.addConfigurationClass(CustomConfiguration.class);
main.addRouteBuilder(MyRouteBuilder.class);
main.run(args);
}
}
In order to run this example, we will set the following properties in the configuration file application.properties:
camel.main.name = CamelHelloWorld # properties used in the route myCron = 0/2 * * * * ? # application properties hi = Hello
And finally, the dependencies needed to run the example:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mastertheboss.camel</groupId>
<artifactId>camel-demo</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>A Camel Route</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencyManagement>
<dependencies>
<!-- Camel BOM -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-parent</artifactId>
<version>3.0.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-main</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-quartz</artifactId>
</dependency>
<!-- logging -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<scope>runtime</scope>
</dependency>
<!-- testing -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- Allows the example to be run via 'mvn compile exec:java' -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.mastertheboss.camel.MainApp</mainClass>
<includePluginDependencies>false</includePluginDependencies>
</configuration>
</plugin>
<!-- Run 'mvn camel-main:generate' -->
<!-- generate autowire.properties file that can automatic detect resources
from the classpath to make convention over configuration for Camel components -->
<plugin>
<groupId>org.apache.camel</groupId>
<artifactId>camel-main-maven-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<logClasspath>false</logClasspath>
</configuration>
</plugin>
</plugins>
</build>
</project>
That's all. Provided that you have deleted the initial classes created by the archetype, you should end up with the following project tree:
src ├── main │ ├── java │ │ └── com │ │ └── mastertheboss │ │ └── camel │ │ ├── CustomConfiguration.java │ │ ├── GreetingBean.java │ │ ├── MainApp.java │ │ └── MyRouteBuilder.java │ └── resources │ ├── application.properties │ ├── log4j2.properties │ └── META-INF │ └── spring-configuration-metadata.json
Run the main class and verify that the Property is injected correctly and the Route is fired:
[duler-CamelHelloWorld_Worker-1] route1 INFO HELLO HOW ARE YOU? [duler-CamelHelloWorld_Worker-2] route1 INFO HELLO HOW ARE YOU?
Using type-safe DSL Routes
Camel end users would experience the problem if you made a configuration mistake in the endpoint, which then makes Camel fail on startup. Since Camel 3, there is a new type-safe DSL for endpoints which you can use in Java routes. In order to use type-safe DSL you need some adjustments to your code. First of all, you need to extend the class org.apache.camel.builder.endpoint.EndpointRouteBuilder. Here is a basic example without and with the endpoint DSL:
package com.mastertheboss.camel;
import org.apache.camel.builder.endpoint.EndpointRouteBuilder;
public class MyDSLRouteBuilder extends EndpointRouteBuilder {
public void configure() {
from(quartz("foo?cron={{myCron}}")).
bean("greetingBean", "hello").process((exchange) -> {
exchange.getIn().setBody(exchange.getIn().getBody(String.class).toUpperCase());
}).log("${body}");
}
}
Then, you need to add to your dependencies the camel-endpointdsl artifact:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-endpointdsl</artifactId>
</dependency>
You can find the source code for this tutorial here: https://github.com/fmarchioni/mastertheboss/tree/master/camel/camel-demo
FREE WildFly Application Server - JBoss - Quarkus - Drools Tutorials