The Camel Processor is a key building block of Camel, and gives you full access to the message being transferred including the message body, any headers, and any properties associated with the message. By creating a Processor you can modify any of those elements, for example you can alter the body of the message transforming it from XML to CSV or you can add custom properties or headers to it. Let’s see how to build a custom Processor which transforms the body of a Message.
Built in processors
Camel already provides many built-in processors that you can use for a variety of tasks. For example:
- bean: Processes the current exchange by invoking a method on a Java object (or bean).
- convertBodyTo: Converts the In message body to the specified type.
- filter: Uses a predicate expression to filter incoming exchanges.
- log: Logs a message to the console.
- marshal: Transforms into a low-level or binary format by using the specified data format.
- unmarshal: Transforms the In message body from a low-level or binary format to a high-level format, by
using the specified data format. - setBody: Sets the message body of the exchange’s In message.
- setHeader: Sets the specified header in the exchange’s In message.
- removeHeaders: Removes the headers matching the specified pattern from the exchange’s In message.
Besides, you can create a Custom Processor by creating a Class which extends org.apache.camel.Processor interface with a custom code to change the Message Exchange.
Creating a custom Processor
In the following class, we are creating a custom Processor named myProcessor which receives as input the files contained in /var/data/in and format them as CSV files. The files are then transferred to /vr/data/out :
package com.sample; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.main.Main; public class ProcessorExample { public static void main(String[] args) throws Exception { Main main = new Main(); main.enableHangupSupport(); main.addRouteBuilder(new MyRoute()); main.run(args); } } class MyRoute extends RouteBuilder { @Override public void configure() throws Exception { System.out.println("My Routing Started"); from("file:/var/data/in?noop=true").process(new MyProcessor()).to("file:/var/data/out"); System.out.println("My Routing complete"); } }
And here is the implementation of MyProcessor:
package com.sample; import org.apache.camel.Exchange; import org.apache.camel.Processor; public class MyProcessor implements Processor { public void process(Exchange exchange) throws Exception { String myString = exchange.getIn().getBody(String.class); String[] myArray = myString.split(System.getProperty("line.separator")); StringBuffer sb = new StringBuffer(); for (String s : myArray) { sb.append(s).append(","); } System.out.println("MyProcessor complete"); exchange.getIn().setBody(sb.toString()); } public MyProcessor() {} }
Defining the Processor within the Camel Route
You can also define a custom Processor within your Route. See this example:
import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; public class FileRouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { from("file:input?noop=true") .process(new Processor() { public void process(Exchange exchange) throws Exception { String body = exchange.getIn().getBody(String.class); String timestamp = Long.toString(System.currentTimeMillis()); String newBody = timestamp + ":" + body; exchange.getIn().setBody(newBody); } }) .to("file:output"); } }
In this example, we’re using a Processor to add a timestamp to the message. The process() method of the Processor takes an Exchange object as input, which contains the message to be transformed. We’re getting the message body as a String, adding a timestamp to it, and setting the new message body on the Exchange object.
Note that the from() endpoint reads files from the “input” directory using the noop=true option, which means the files are not deleted after being processed. The to() endpoint writes the transformed message to the “output” directory.
Using Fluent Processor builders to modify the body
Camel provides fluent builders, such as ProcessorDefinition
, to create and configure routes and processors in a more concise and readable manner. These builders allow you to chain methods and configure the components of your routes in a fluent style.
Here is an example:
public class MyRouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { from("direct:start") .process(exchange -> { // Custom processing logic String body = exchange.getIn().getBody(String.class); String modifiedBody = "Processed: " + body; exchange.getIn().setBody(modifiedBody); }) .to("mock:result"); } }
In this example, we define a Camel route using ProcessorDefinition
to configure the route components. Within the process
method of the ProcessorDefinition
, we can provide a lambda function or an anonymous class to define the custom processing logic. Here, we modify the incoming message body by appending the string “Processed: ” to it.
Using a Processor in an XML Route
On the other hand, if you prefer using XML DSL, then you can achieve the same result by defining the Processor within the XML file. For example:
<routes xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="file:input?noop=true"/> <process> <bean class="com.example.MyProcessor"/> </process> <to uri="file:output"/> </route> </routes>
Conclusion