Routes tips, tricks and gotchas

Best practices

Compartmentalize route logic

The Direct component makes it easy to create sub-routines within a given context allowing you to separate the logic of your route in different chunks.

In the following example, we create a route that queries information from a database and treats each row of the results in a separate sub-routine.

Route using direct
<routes xmlns="http://camel.apache.org/schema/spring" xmlns:u="http://www.systar.com/aluminium/camel-util">
	<route>
		<from uri="timer://foo?repeatCount=1"/>		
		<to uri="jdbc:issuesQuery"/>
		<!-- We execute a query against a database that stores information for a bug-tracking application -->	
		<split>
			<simple>${body}</simple>  
			<to uri="direct:row"/>
		</split>
	</route>
	<route>
		<from uri="direct:row"/>
		<setHeader headerName="issueId" >
			<simple>body[issueId]</simple>
		</setHeader>
		<!-- Do some computing on the values retrieved from the database -->
		<to uri="tnd-absorption:createIssues"/>		
	</route>
</routes>

Tips

Comparing Comparable objects in simple predicates

Example of Comparable types: java.util.Date or org.joda.time.ReadableInstant

Simple predicates automatically use the compareTo methods for the <><= and >= operators. The second object will be converted to the type of the first one.

<choice>
    <when>
        <simple>${body['first date']} < ${body['second date']}</simple>
        ...
    </when>
</choice>

SEDA and VM endpoint

The SEDA endpoint and VM endpoint rely on an in-memory queue to store the message between producer and consumer. When producer is faster than consumer the queue is growing. Since the default configuration doesn't limit the queue size it may lead to consuming too much memory and OutOfMemoryError may appear. To avoid that, always configure SEDA or VM endpoint in order to limit the queue size. This is done by setting the following properties:

  • size=xxx – Indicates the maximum number of messages to be queued.
  • blockWhenFull=true – When the queue is full, the default behavior is to fail and throw an exception. Most of the time, it is not the expected behavior, it is recommended to wait to have some place in the queue.

Both parameters must be set on the both sides (ie to and from). For example (given for SEDA only, the same can be applied to VM endpoint):

Producer side
<route>
    ....
    <to uri="seda:message?size=16&amp;blockWhenFull=true" />
</route>
Consumer side
<route>
    <from uri="seda:message?size=16&amp;blockWhenFull=true" />
    ...
</route> 

 

If the processing of the message queue needs to be multithreaded, the SEDA consuming route can specify the number of processing thread with the property concurrentConsumers:

Consumer side
<route>
    <from uri="seda:message?size=16&amp;blockWhenFull=true&amp;concurrentConsumers=4" />
    ...
</route>

Gotchas

Default file producer component suspicious performance

Description

            <to uri="file://{{DataPath}}/Shifted?charset=UTF-8&amp;fileName=${header.NewFileName}&amp;fileExist=Append"/>

can have awfully slow writing performance _ at least under "low" end laptop

Workaround

Use the forceWrites = false option.

            <to uri="file://{{DataPath}}/Shifted?charset=UTF-8&amp;fileName=${header.NewFileName}&amp;fileExist=Append&amp;forceWrites=false"/>

Evaluating a value inside a <simple> tag inside a <setHeader> tag does not work

Description

<setHeader headerName="EvaluateMe">
  <simple type="java.lang.Boolean">${body['SomeValue']} == 0</simple>
</setHeader>

The above code produces a String, no matter what... For instance, if body['SomeValue'] is set to 0, the above code sets the header EvaluateMe to "0 == 0" instead of true.

Workaround

To work around the limitation, you can use a choice tag:

<choice>
  <when>
    <simple>${body['SomeValue']} == 0</simple>
    <setHeader headerName="EvaluateMe">
      <simple type="java.lang.Boolean">true</simple>
    </setHeader>
  </when>
  <otherwise>
    <setHeader headerName="EvaluateMe">
      <simple type="java.lang.Boolean">false</simple>
    </setHeader>
 </otherwise>
</choice>

or a groovy script (slower to run, but more concise):

<setHeader headerName="EvaluateMe">
  <groovy>request.body['SomeValue'] == 0 ? true : false</groovy>
</setHeader>

Related Links