A custom Camel Processor is very easy to write and use within a route, and gives you full access to all parts of the exchange being processed. This is the ultimate functional element within Camel as you can create, and reuse, custom message processors that can do anything you can imagine doing with Java.
This recipe will show you how to create you own Camel Processor implementation that can be used, and shared, within your Camel integration routes.
The Java code for this recipe is located in the org.camelcookbook.extend.processor
package. The Spring XML files are located under src/main/resources/META-INF/spring
and prefixed with processor
.
In order to use a custom processor within your route, perform the following steps:
org.apache.camel.Processor
interface:import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.Processor; public class MyProcessor implements Processor { @Override public void process(Exchange exchange) throws Exception { //... } }
exchange.getIn()
. If your processor needs to modify the message, most often you should just modify the in
message directly (see the How it works... section of this recipe for more discussion):public void process(Exchange exchange) throws Exception { String result = "Unknown language"; final Message inMessage = exchange.getIn(); final String body = inMessage.getBody(String.class); final String language = inMessage.getHeader("language", String.class); if ("en".equals(language)) { result = "Hello " + body; } else if ("fr".equals(language)) { result = "Bonjour " + body; } inMessage.setBody(result); }
In the XML DSL, this is written as:
<beans
xmlns="http://www.springframework.org/schema/beans"...>
<bean id="myProcessor"
class="org.camelcookbook.extend.processor.MyProcessor"/>
<camelContext
xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:start"/>
<process ref="myProcessor"/>
<to uri="mock:result"/>
</route>
</camelContext>
</beans>
In the Java DSL, the same thing is expressed as:
import org.apache.camel.builder.RouteBuilder;
public class MyProcessorRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:start")
.process(new MyProcessor())
.to("mock:result");
}
}
}
The Camel Processor is a fundamental building block within Camel, and provides complete access to all of the data associated within the message being processed, including the message body, any headers, and any properties associated with the message.
Your custom processor has the ability to modify the message, and add or modify headers and properties associated with the message. It is typically used whenever you want to perform multiple operations in one routing step, such as setting multiple related message headers as well as modifying the message body.
In the preceding example, your custom processor is being accessed as a singleton meaning that multiple messages (threads) are calling it concurrently. So you need to think about thread safety in the coding of your process method.
Even though the Java DSL variant had a new MyProcessor()
for when your processor is referenced, that code within the configure()
method is only called once when your route is first added to the Camel context. As such, it is still a singleton. The fact that configure()
is only called once, versus for each message, is a common source of confusion.
Generally processors just modify the in
message. There is an out
message on the exchange that makes it possible to return both the original message (request) and processed message (response). If setting the out
message you need to be very careful to preserve all appropriate headers and properties associated with the message.
In the following code snippet, the copyFrom
method copies the body, headers, and properties from the source message. The ExchangeHelper.isOutCapable()
checks the message exchange pattern of the provided exchange
, and returns true
if it is InOut
, which indicates that the calling route expects a response to be returned. In practice, it is rare that you should do more than just modify the in
message. See the Camel Processor FAQ for more discussion on modifying the in
versus out
message:
if (ExchangeHelper.isOutCapable(exchange)) { exchange.getOut().copyFrom(exchange.getIn()); exchange.getOut().setBody("<modified body>"); } else { exchange.getIn().setBody("<modified body>"); }
Within the Java DSL, you can inline your processor as an anonymous inner class as part of the route definition. In general, you would only want to do this if the body of your process()
method is short.
If your processor involves a lot of code, you are much better off putting it into a separate class that you can test independently, and that does not distract the reader from the overall integration route flow.
public class MyProcessorInlineRouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { from("direct:start") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { // Some quick Java code }) .to("mock:result"); } }
3.22.77.63