2009-04-28

On the road to Camel 2.0 - Interceptors

Camel 2.0 have the intercept mechanism but it comes in different flavors.

They have the same common goal to intercept an message while its being routed and allows to do some custom work or processing. 

Before digging into showing code we distill the two distinct flavors as:
1) the classic AOP interceptor that is applied at each step in the route path
2a) route interceptors that intercept incoming messages
  and its related
2b) endpoint interceptors that intercept message about to be sent to an endpoint

Ad 1)
The classic AOP interceptors is defined in the interface org.apache.camel.spi.InterceptStrategy that allows you to attach a custom org.apache.camel.Processor with the work you want to do. This interceptor is mostly used internally in Camel to apply needed work that each message must undergo before they are continued routed to the next node in the route path.

We are looking into adding some syntax sugar so you can attach your own code logic without using the Camel API, for instance to use POJO. Expect this are to improve in the future.

Ad 2a)
As the Camel wiki documentation for interceptor was a bit sparse in this area I did some work yesterday to improve it and add some samples.

This interceptor is used for intercepting any new messages coming into Camel (i.e. think it as all the from DSL being intercepted).

For instance to log all incoming messages you can do:
intercept().to("log:received");

from("jms:queue:neworder").to("bean:ordeService?method=newOrder").to("jms:queue:handleorder");

People that already is familiar with Camel could know that Camel have extensive Predicate support. And with intercept that is no exceptions. So what we can do is to attach a predicate to the intercept to only trigger for certain conditions.

For instance to do a bit of custom processing on test messages received, we can add an interceptor with a predicate to determine if whether its a test message. If so we route it to our custom processor where we can "fixup" the test message before we let the message continue being routed from the origin of interception

intercept()
    .when(header("usertype").isEqualTo("test"))
    .process(new MyTestServiceProcessor());

Well what if you wanted to filter our test message instead? Well Camel supports a stop DSL keyword allowing Camel to stop continue routing. So in the sample above we could just append stop() in the end of the route. 

intercept()
    .when(header("usertype").isEqualTo("test"))
    .stop();

As the intercept() is also just a route you have all the DSLs at your fingertips.

Ad 2b)
This is a new interceptor introduced in Camel 2.0m2. The idea is to allow interception before a message is sent to a given Endpoint. So for instance if we want to do some custom processing before we send a message to the neworder JMS queue we can do:

interceptSendToEndpoint("jms:queue:neworder")
    .process(new MyJmsNewOrderProcessor());

So when anyone using the Camel API to send a JMS message to that given endpoint jms:queue:neworder, the producer is intercepted and the message is routed to our MyJmsNewOrderProcessor where we can alter the message or whatever we want to do. And afterwards the message is send to the original intended endpoint. The default behavior is to afterwards send it to the intended endpoint. But if you want to skip this you can add the stop() DSL to the route. We use the stop() keyword as this interceptor shares the same code base with the other interceptor, and thus also DSL keywords. We might consider separating the code to introduce a skip() DSL keyword as its better expression what it does, skipping sending the message to the intended endpoint.

So we could use this to intercept sending to the handleorder JMS queue and e.g. store it in a file instead.

// notice: use stop() to skip sending to the intended endpoint.
interceptSendToEndpoint("jms:queue:handleorder")
    .to("file://output/orders").stop();

We have a few other wacky ideas that we are considering. For instance why not allow wildcards or reg exp expressions in the intercepted endpoint uri so you can intercept any JMS queue or a group of queues.

Well that's it for now. Just wanted to give a bit of update on the interceptor side in Camel.

No comments: