Writing a custom Camel Processor

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.

Getting ready

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.

How to do it...

In order to use a custom processor within your route, perform the following steps:

  1. Create your processor class that implements the 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 {
        //...
      }
    }
  2. Implement the process method. The incoming message is contained within 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);
    }
  3. Reference your custom processor in your route:

    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");
        }
      }
    }

Note

Typically you will use the process directive when referencing custom Processors. You can also use the to directive to reference your custom processor like a bean if you've registered it in the Camel Registry. For example:

<to uri="bean:myProcessor?method=process"/>

How it works...

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.

Note

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>");
}

Tip

The use of the out message was more common in earlier versions of Camel. In newer versions of Camel, you can always just use the in message and you will be fine.

There's more...

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");
  }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.77.63