Apache Camel Components Example
Applications communicate with each other using Messages via Message Channels.
The end points of a message channels either consume or send messages. The components that model these end points are called ‘Endpoints’ and the factory that creates these endpoints are called Camel Components.
In this article, we will see an example of registering a component using spring as well as manually. We will also know some example of camel core components.
m the bean is sent to console.
Before we start with our example, Let’s look into the setup details.
This example uses the following frameworks:
- Maven 3.2.3
- Apache Camel 2.15.1
- Spring 4.1.5.RELEASE
- Eclipse as the IDE, version Luna 4.4.1.
1. Dependencies
I will be showing you some examples of camel components so you need to add the following dependencies:
camel-core
– basic module of apache camel.camel-stream
– We will use this to send output to the console.camel-jms
andactivemq-camel
– ActiveMQ JMS components.spring-context
andcamel-spring
– Since we be configuring our camel context in spring.slf4j-api
andslf4j-log4j12
– This is for the log component. It relies onslf4j
for the logger API andlog4j
as the logger implementation
pom.xml
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacodegeeks.camel</groupId> <artifactId>camelHelloWorld</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-core</artifactId> <version>2.15.1</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-stream</artifactId> <version>2.15.1</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jms</artifactId> <version>2.15.1</version> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-camel</artifactId> <version>5.6.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring</artifactId> <version>2.15.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency> </dependencies> </project>
2. Camel Component
A class which implements org.apache.camel.Component
is called a Camel component is simple. Since it is a factory Endpoint
objects, you must implement the below method. Of there are other methods which sets the context and configures the endpoint.
Endpoint createEndpoint(String uri) throws Exception;
One can implement a camel component and add it to the context. Assuming MyComponent
is our custom component, we can add it to the context as shown below:
CamelContext camelContext = new DefaultCamelContext(); camelContext.addComponent("someUriScheme", new MyComponent());
As you can see a camel component helps creating a new endpoint, thus a new producer/consumer of messages and this is how a Camel component helps in extending Camel’s behavior.
3. Camel Core Components
The camel-core
module ships in with some built-in components. We have listed few important ones below:
- Bean – Invokes a Java bean in the registry.
- Direct – Allows you to synchronously call another endpoint with little overhead.
- File – Allows you to work with files, to reads or write to files.
- Log – Logs messages to a number of different logging providers.
- Mock – Tests that messages flow through a route as expected.
- SEDA – Allows you to asynchronously call another endpoint in the same
CamelContext
- Timer – Sends out messages at regular intervals
4. Example of Bean Component
The bean
component binds beans to Camel message exchanges.
Its URI format is bean:beanName[?options]
where beanName can be any string which is used to look up the bean in the Registry.
Let’s register a bean and invoke its method. You can do it using by binding your bean with JndiContext
or registering your bean in spring.
Greeting:
package com.javacodegeeks.camel; import java.util.ArrayList; import java.util.List; public class Greeting { private List messages = new ArrayList(); public String hello(String msg) { String helloMsg = "Hello " + msg; messages.add(helloMsg); return helloMsg; } public String toString() { return messages.toString(); } }
CamelBeanExample:
package com.javacodegeeks.camel; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.util.jndi.JndiContext; public class CamelBeanExample { public static final void main(String[] args) throws Exception { JndiContext jndiContext = new JndiContext(); jndiContext.bind("greetingBean", new Greeting()); CamelContext camelContext = new DefaultCamelContext(jndiContext); try { camelContext.addRoutes(new RouteBuilder() { public void configure() { from("direct:exampleName").to("bean:greetingBean?method=hello"); } }); ProducerTemplate template = camelContext.createProducerTemplate(); camelContext.start(); template.sendBody("direct:exampleName", "This is bean example"); System.out.println(jndiContext.lookup("greetingBean")); } finally { camelContext.stop(); } } }
Output:
16:14| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[direct://exampleName] 16:14| INFO | DefaultCamelContext.java 2453 | Total 1 routes, of which 1 is started. 16:14| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.281 seconds [Hello This is bean example] 16:14| INFO | DefaultCamelContext.java 2660 | Apache Camel 2.15.1 (CamelContext: camel-1) is shutting down
5. Example of Direct Component
The direct component provides synchronous invocation of a route. Its URI is direct:someName
.
Using direct:
, we can reuse a routing logic. In the below example, we have two routes. The first route consumes messages from an activeMq queue, and passed them to Greeting
bean for further processing which in turn posts the messages to direct:greetings
. This is where the second route starts. The messages from direct:greetings
are consumed and sent to the console.
Both the routes happen one after the other synchronously. If we want asynchronous version, we should use the seda:
component which will be our next example.
directExampleApplicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="vm://localhost?broker.persistent=false" /> </bean> <bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent"> <property name="connectionFactory" ref="connectionFactory" /> </bean> <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="activemq:queue:test.queue" /> <to uri="bean:greeting?method=hello"/> <to uri="direct:greetings" /> </route> <route> <from uri="direct:greetings" /> <to uri="stream:out" /> </route> </camelContext> <bean id="greeting" class="com.javacodegeeks.camel.Greeting"/> </beans>
If you have observed, we have used a JMS here. We have added an activemq
Camel component. In camel you need two things to configure JMS. Add ConnectionFactory
and activemq
component.
CamelDirectExampleUsingSpring:
package com.javacodegeeks.camel; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.spring.SpringCamelContext; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class CamelDirectExampleUsingSpring { public static final void main(String[] args) throws Exception { ApplicationContext appContext = new ClassPathXmlApplicationContext( "applicationContext.xml"); CamelContext camelContext = SpringCamelContext.springCamelContext( appContext, false); try { ProducerTemplate template = camelContext.createProducerTemplate(); camelContext.start(); template.sendBody("activemq:queue:test.queue", "Direct example"); Thread.sleep(2000); } finally { camelContext.stop(); } } }
Output:
16:15| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[activemq://queue:test.queue] 16:15| INFO | DefaultCamelContext.java 3164 | Route: route2 started and consuming from: Endpoint[direct://greetings] 16:15| INFO | DefaultCamelContext.java 2453 | Total 2 routes, of which 2 is started. 16:15| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.622 seconds 16:15| INFO | DefaultCamelContext.java 2418 | Apache Camel 2.15.1 (CamelContext: camel-1) is starting 16:15| INFO | DefaultCamelContext.java 2453 | Total 2 routes, of which 2 is started. 16:15| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.000 seconds Hello Direct example 16:15| INFO | DefaultCamelContext.java 2660 | Apache Camel 2.15.1 (CamelContext: camel-1) is shutting down
6. Example of SEDA
The Direct component provides synchronous invocation of any consumers when a producer sends a message exchange whereas seda component provides an asynchronous solution.
sedaExampleApplicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="vm://localhost?broker.persistent=false" /> </bean> <bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent"> <property name="connectionFactory" ref="connectionFactory" /> </bean> <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="activemq:queue:test.queue" /> <to uri="bean:greeting?method=hello" /> <to uri="seda:greetings" /> <transform> <simple>${in.body} processed</simple> </transform> </route> <route> <from uri="seda:greetings" /> <to uri="stream:out" /> <to uri="mock:result"/> </route> </camelContext> <bean id="greeting" class="com.javacodegeeks.camel.Greeting" /> </beans>
CamelSedaExampleUsingSpring:
package com.javacodegeeks.camel; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.spring.SpringCamelContext; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class CamelSedaExampleUsingSpring { public static final void main(String[] args) throws Exception { ApplicationContext appContext = new ClassPathXmlApplicationContext( "sedaExampleApplicationContext.xml"); CamelContext camelContext = SpringCamelContext.springCamelContext( appContext, false); try { ProducerTemplate template = camelContext.createProducerTemplate(); camelContext.start(); Object out = template.requestBody("activemq:queue:test.queue", "Seda Example"); System.out.println("Response: " + out); } finally { camelContext.stop(); } } }
Output:
16:16| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[activemq://queue:test.queue] 16:16| INFO | DefaultCamelContext.java 3164 | Route: route2 started and consuming from: Endpoint[seda://greetings] 16:16| INFO | DefaultCamelContext.java 2453 | Total 2 routes, of which 2 is started. 16:16| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.615 seconds 16:16| INFO | DefaultCamelContext.java 2418 | Apache Camel 2.15.1 (CamelContext: camel-1) is starting 16:16| INFO | DefaultCamelContext.java 2453 | Total 2 routes, of which 2 is started. 16:16| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.000 seconds Hello Seda Example Response: Hello Seda Example processed 16:16| INFO | DefaultCamelContext.java 2660 | Apache Camel 2.15.1 (CamelContext: camel-1) is shutting down
7. Example of File Component
The File component provides access to file systems, we can use it to send messages to a file or poll a file or directory. Its URI format is file:directoryName[?options]
.
The first route writes to the file where as the second route polls the file, processes the content and sends it to the bean. The returned value from the bean is sent to console.
CamelFileExample:
package com.javacodegeeks.camel; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.Processor; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.util.jndi.JndiContext; public class CamelFileExample { public static final void main(String[] args) throws Exception { JndiContext jndiContext = new JndiContext(); jndiContext.bind("greetingBean", new Greeting()); CamelContext camelContext = new DefaultCamelContext(jndiContext); try { camelContext.addRoutes(new RouteBuilder() { public void configure() { from("direct:fileContent").to( "file:target/?fileName=out.txt").to("stream:out"); from("file://target/?fileName=out.txt&move=processed") .process(new Processor() { public void process(Exchange exchange) throws Exception { Message in = exchange.getIn(); in.setBody(in.getBody(String.class) + "(polling)"); } }).to("bean:greetingBean").to("stream:out"); } }); ProducerTemplate template = camelContext.createProducerTemplate(); camelContext.start(); template.sendBody("direct:fileContent", "This is file example"); Thread.sleep(3000); } finally { camelContext.stop(); } } }
Output:
16:17| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[direct://fileContent] 16:17| INFO | DefaultCamelContext.java 3164 | Route: route2 started and consuming from: Endpoint[file://target/?fileName=out.txt&move=processed] 16:17| INFO | DefaultCamelContext.java 2453 | Total 2 routes, of which 2 is started. 16:17| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.294 seconds This is file example Hello This is file example(polling) 16:17| INFO | DefaultCamelContext.java 2660 | Apache Camel 2.15.1 (CamelContext: camel-1) is shutting down
8. Example of Log Component
The camel-core comes with a log component that let you inspect the message. Its URI format is log:loggingCategory[?options]
. loggingCategory is the name of the logging category to use. You can append the logging level using the level option, for example, log:com.javacodegeeks.camel?level=INFO
.
Camel uses sfl4j as the logging API layer. In our example, we will configure log4j as the logging implementation.
CamelLogExample:
package com.javacodegeeks.camel; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.util.jndi.JndiContext; public class CamelLogExample { public static final void main(String[] args) throws Exception { JndiContext jndiContext = new JndiContext(); jndiContext.bind("greetingBean", new Greeting()); CamelContext camelContext = new DefaultCamelContext(jndiContext); try { camelContext.addRoutes(new RouteBuilder() { public void configure() { from("direct:exampleName") .to("bean:greetingBean?method=hello") .to("log:com.javacodegeeks.camel?level=INFO&showBody=true"); } }); ProducerTemplate template = camelContext.createProducerTemplate(); camelContext.start(); template.sendBody("direct:exampleName", "This is log example"); } finally { camelContext.stop(); } } }
Output:
15:20| INFO | DefaultCamelContext.java 2418 | Apache Camel 2.15.1 (CamelContext: camel-1) is starting 15:20| INFO | ManagedManagementStrategy.java 187 | JMX is enabled 15:20| INFO | DefaultTypeConverter.java 56 | Loaded 186 type converters 15:20| INFO | DefaultCamelContext.java 2633 | AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn this option off as it may improve performance. 15:20| INFO | DefaultCamelContext.java 2643 | StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html 15:20| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[direct://exampleName] 15:20| INFO | DefaultCamelContext.java 2453 | Total 1 routes, of which 1 is started. 15:20| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.266 seconds 15:20| INFO | MarkerIgnoringBase.java 95 | Exchange[ExchangePattern: InOnly, BodyType: String, Body: Hello This is log example] 15:20| INFO | DefaultCamelContext.java 2660 | Apache Camel 2.15.1 (CamelContext: camel-1) is shutting down 15:20| INFO | DefaultShutdownStrategy.java 184 | Starting to graceful shutdown 1 routes (timeout 300 seconds) 15:20| INFO | DefaultShutdownStrategy.java 647 | Route: route1 shutdown complete, was consuming from: Endpoint[direct://exampleName] 15:20| INFO | DefaultShutdownStrategy.java 247 | Graceful shutdown of 1 routes completed in 0 seconds 15:20| INFO | DefaultCamelContext.java 2745 | Apache Camel 2.15.1 (CamelContext: camel-1) uptime 0.328 seconds 15:20| INFO | DefaultCamelContext.java 2746 | Apache Camel 2.15.1 (CamelContext: camel-1) is shutdown in 0.008 seconds
9. Example of Timer
The timer:
component is used to generate message exchanges when a timer fires. You can only consume events from this endpoint. Its URI format is timer://name
where name is the name of the Timer object.
CamelTimerExample:
package com.javacodegeeks.camel; import org.apache.camel.CamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.util.jndi.JndiContext; public class CamelTimerExample { public static void main(String[] args) throws Exception { JndiContext jndiContext = new JndiContext(); jndiContext.bind("greetingBean", new Greeting()); CamelContext camelContext = new DefaultCamelContext(jndiContext); try { camelContext.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { from("timer://timerExample?period=2000") .setBody() .simple("This is timer example ${header.firedTime}") .to("bean:greetingBean") .to("stream:out"); ; } }); camelContext.start(); Thread.sleep(10000); } finally { camelContext.stop(); } } }
Output:
16:00| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[timer://timerExample?period=2000] 16:00| INFO | DefaultCamelContext.java 2453 | Total 1 routes, of which 1 is started. 16:00| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.282 seconds Hello This is timer example Wed Apr 29 16:00:09 IST 2015 Hello This is timer example Wed Apr 29 16:00:11 IST 2015 Hello This is timer example Wed Apr 29 16:00:13 IST 2015 Hello This is timer example Wed Apr 29 16:00:15 IST 2015 Hello This is timer example Wed Apr 29 16:00:17 IST 2015 16:00| INFO | DefaultCamelContext.java 2660 | Apache Camel 2.15.1 (CamelContext: camel-1) is shutting down
10. Camel Mock Example
Mock component is used in the testing of distributed and asynchronous processing.
When a test is run involving one or more routes, we can use the mock endpoint to assert whether
- The correct number of messages are received on each endpoint.
- The correct payloads are received, in the right order.
The URI format is mock:name[?options]
, name can be any string that uniquely identifies the endpoint.
CamelMockExample:
package com.javacodegeeks.camel; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.util.jndi.JndiContext; public class CamelMockExample { public static void main(String[] args) throws Exception { JndiContext jndiContext = new JndiContext(); jndiContext.bind("greetingBean", new Greeting()); CamelContext camelContext = new DefaultCamelContext(jndiContext); try { camelContext.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { from("direct:in").to("bean:greetingBean").to("mock:out"); } }); camelContext.start(); Thread.sleep(1000); ProducerTemplate template = camelContext.createProducerTemplate(); template.sendBody("direct:in", "This is mock example"); MockEndpoint resultEndpoint = camelContext.getEndpoint("mock:out", MockEndpoint.class); resultEndpoint.expectedMessageCount(1); System.out.println("Message received: " + resultEndpoint.getExchanges().get(0).getIn().getBody()); resultEndpoint.expectedBodiesReceived("Hello This is mock example"); } finally { camelContext.stop(); } } }
Output:
18:06| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[direct://in] 18:06| INFO | DefaultCamelContext.java 2453 | Total 1 routes, of which 1 is started. 18:06| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.319 seconds Message received: Hello This is mock example 18:06| INFO | DefaultCamelContext.java 2660 | Apache Camel 2.15.1 (CamelContext: camel-1) is shutting down
11. Adding a custom component
We can manually add a camel component using the CamelContext.addComponent
method against the URI scheme as key. For example, in the below class, we add a seda component against “activemq” scheme.
CamelAddingComponentExample:
package com.javacodegeeks.camel; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.seda.SedaComponent; import org.apache.camel.impl.DefaultCamelContext; public class CamelAddingComponentExample { public static void main(String[] args) throws Exception { CamelContext camelContext = new DefaultCamelContext(); try { camelContext.addComponent("activemq", new SedaComponent()); camelContext.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { from("direct:in").to("activemq:someQueue"); from("activemq:someQueue").to("stream:out"); } }); camelContext.start(); ProducerTemplate template = camelContext.createProducerTemplate(); template.sendBody("direct:in", "Adding camel component"); } finally { camelContext.stop(); } } }
Output:
18:29| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[direct://in] 18:29| INFO | DefaultCamelContext.java 3164 | Route: route2 started and consuming from: Endpoint[activemq://someQueue] 18:29| INFO | DefaultCamelContext.java 2453 | Total 2 routes, of which 2 is started. 18:29| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.1 (CamelContext: camel-1) started in 0.276 seconds 18:29| INFO | DefaultCamelContext.java 2660 | Apache Camel 2.15.1 (CamelContext: camel-1) is shutting down 18:29| INFO | DefaultShutdownStrategy.java 184 | Starting to graceful shutdown 2 routes (timeout 300 seconds) 18:29| INFO | DefaultShutdownStrategy.java 606 | Waiting as there are still 1 inflight and pending exchanges to complete, timeout in 300 seconds. Adding camel component 18:30| INFO | DefaultShutdownStrategy.java 647 | Route: route2 shutdown complete, was consuming from: Endpoint[activemq://someQueue] 18:30| INFO | DefaultShutdownStrategy.java 647 | Route: route1 shutdown complete, was consuming from: Endpoint[direct://in]
12. Download the Eclipse Project
This was an example about Camel Components.
You can download the full source code of this example here: camelComponentsExample.zip