2009-06-27

On the road to Camel 2.0 - OnCompletion

Its time to write a new blog entry on another new feature in Apache Camel 2.0 - on completion.

On completion allows you to do additional routing when an exchange has been completed.

Imagine you need to register a special log entry when a particular route is complete. What you could do at first sight was just to add a processor at the end of the route that would log the entry.

But now the processor is part of the original route and it could potential affect the outcome. For instance lets say the processor could not log the entry and fails, or it accidently changed or altered the payload, or it was time consuming. All affecting the original route.

So how can we avoid this? What we want to do is to execute our processor after the original route is complete. With the new onCompletion DSL you can do this.

Lets look at a little sample to help understand how its setup and works.

First we define a route as below:
from("file://inbox")
.to("bean:validateFile")
.to("activemq:queue:inbox");

And then we want to do run our custom processor FileCompletionProcessor when the route is complete. So what we do is to register an onCompletion on this route.

This is done by adding our onCompletion
.onCompletion()
.process(new FileCompletionProcessor())
.end()

... to the route as shown below:

from("file://inbox")
.onCompletion()
.process(new FileCompletionProcessor())
.end()
.to("bean:validateFile")
.to("activemq:queue:inbox");

Notice: We need to declare an end() on the onCompletion route to indicate the end of this one. What it means is that the onCompletion is a first class route on its own. So you can do all the DSL in this route as you like. You can do content based routing, filtering, invoking additional processors or beans etc. For Camel its just another route.

What happens is that when the original route is complete, e.g. the file content have been send to the activemq queue and the route is complete. Then the onCompletion kicks in. What Camel does internally is that it starts a new route in another thread that has a copy of the original exchange, that is routed in the onCompletion route. So the original route continues to run in its own thread to complete immediately. This ensures that the onCompletion route will not affect the original route.

The sample above was a basic example. What if you only want to do special work in case the original route failed? Well Camel supports DSL to specify:
- onFailureOnly
- onCompleOnly

For instance we want to invoke a bean registered with the id failureService in case the route failed. We can do this as:
.onCompletion().onFailureOnly()
.beanRef("failureService", "fileFailed")
.end()

And just like other functions in Camel onCompletion also supports scopes:
- global
- route

And the onWhen predicate that you might have seen as well.

Take a look at the documentation for further details and sample. It provides XML samples as well.

No comments: