Camel...Evaluating a java expression - java

I have a camel flow which routes from an activemq to another activemq. However, I need to evaluate an expression and set it as a header. How do I achieve that.
<from uri="jms:queue:Q.activemq1"/>
<setHeader headerName="EVENT_KEY">
<simple>${java.util.UUID.randomUUID().toString()}</simple>
</setHeader>
<to uri="jms:queue:Q.activemq2"/>
But the header is not being set correctly?
How do I set java.util.UUID.randomUUID().toString() value to the header?
pls advise

Use the Groovy expression language for that. The simple language is ok for concatenating strings and comparing parts of the payload, but for more logic, groovy is a swiss army knife.
<from uri="jms:queue:Q.activemq1"/>
<setHeader headerName="EVENT_KEY">
<groovy>java.util.UUID.randomUUID().toString()</groovy>
</setHeader>
<to uri="jms:queue:Q.activemq2"/>
You need to add a dependency to camel-groovy to make it work.

Related

Is it possible to call the header value as a parameter for the method applied to the same object in simple interpreter, Spring DSL for Apache Camel?

Is it possible to call something like this in Apache Camel's Spring DSL
<setHeader headerName="timestampPart3"><simple>${header.timestampPart2.substring(0, ${header.timestampPart2.length()} - 2)}</simple></setHeader>
or like this
<setHeader headerName="timestampPart3"><simple>${header.timestampPart2.substring(0, header.timestampPart2.length() - 2)}</simple></setHeader>
For the second attempt it identifies .length() - 2 as a single method name call
You can increment and decrement with simple, so...
I wouldn't recommend, but for example:
<setHeader headerName="timestampPart2_1">
<simple>${header.timestampPart2.length()}--</simple>
</setHeader>
<setHeader headerName="timestampPart2_1">
<simple>${header.timestampPart2_1}--</simple>
</setHeader>
<setHeader headerName="timestampPart3">
<simple>${header.timestampPart2.substring(0, ${header.timestampPart2_1})}</simple>
</setHeader>
I had to use groovy instead of simple for doing that.
<setHeader headerName="timestampPart3"><groovy>
request.headers.get('timestampPart2').split("\\.")[0]
</groovy></setHeader>

Conditionally Exit Camel Loop

I'll start off by saying that I'm using Camel 2.14, upgrading is simply not in the cards at the moment. So I miss out on the doWhile option which came in 2.17.
I have a scenario in which I need to be able to have the routing repetitively attempt to deliver to a service instance when it is ready. Once this succeeds then I need to exit the loop. So far I have been able to look a specified number of times. However, that loop continues even after success.
I've searched through and it appears I don't have many options. Or I'm still too new at the Camel realm to recognize my options.
<route>
<from uri="activemq:queue:myQueue" />
<loop>
<simple>100</simple>
<when>
<simple>${bean:myService?method=isReady}</simple>
<to uri="bean:myService?method=doWork" />
</when>
</loop>
</route>
You can write that in a java bean where you combine isReady and doWork method, instead of the Camel loop. Also mind about looping is not a good idea if you need to loop for a very long time. If you are not ready its better to not consume from the AMQ queue but leave the messages in the store.
So you can instead use a route policy that is controlling the route to suspend/resume depending on the ready status.
You can then from the route policy periodically check the isReady and then either suspend/resume the route accordingly.
http://camel.apache.org/routepolicy.html
I was facing a similar situation, and addressed it by a self recursive route. I don't know whether there are some down sides for this approach.
<route>
<from uri="activemq:queue:myQueue" />
<to uri="direct:loopingRoute"/>
</route>
<route>
<from uri="direct:loopingRoute"/>
<choice>
<when>
<method ref="myService" method="isReady"/>
<bean ref="myService" method="doWork"/>
</when>
<otherwise>
<to uri="direct:loopingRoute"/>
</otherwise>
</choice>
</route>
This was the apporach used by me. While answering the question, one point came into my mind. Does it cause stack overflow if recursion is beyond a limit?

Using controlBus from spring DSL with parameters

I need to control my routes and I am using spring DSL for Camel.
I need to exposed a service which will perform thoses actions to the routeId given in paramaters.
The following code does not work (the body contain the routeId)
<route id="stopRoute">
<from uri="direct:stopRoute"/>
<log message="about to stop a route"/>
<to uri="controlbus:route?routeId=${body}&action=stop"/>
<to uri="controlbus:route?routeId=${body}&action=status"/>
</route>
I also tried with simple language but I can't figure out the correct syntax
See this FAQ
http://camel.apache.org/how-to-use-a-dynamic-uri-in-to.html
Use <toD> to make the to dynamic.

Camel XML routes: can I give a "uri" attribute in a <from> element the value of a Java constant?

If I have a String Java constant com.example.Constants.MY_URI, can I somehow use it to assign the value of a uri attribute in a Camel XML file?
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="aaa" /> <-- how to use MY_URI here?
<to uri="bbb"/>
</route>
</camelContext>
In particular, is there a way to use one of the Camel languages for this?
Many thanks!
edit
After more work with camel and better know. It is possible to use one of the camel languages to define where message shold go, using recipient-list. But you can't use it as a replacement of from - it must be hardcoded or taken from properties file as I described below.
end edit
I don't know if that is possible, but there is another option:
you can use propertyPlaceholder:
<camelContext ...>
<propertyPlaceholder id="properties" location="com/mycompany/myprop.properties"/>
</camelContext>
and you need to put your constans into myprop.properties files:
example.from.property.name=direct:start
then you can use that property inside from:
<from uri="{{example.from.property.name}}" />

Dynamic to(URI) in Camel

I'd like configure a Camel route where the to(uri) can be specified at runtime.
I tried the following:
public class Foo extends RouteBuilder {
#Override
public void configure() {
// the URI can point to different hosts
from("direct:start").to(${someUri}");
}
}
and then
ProducerTemplate pt = camelContext.createProducerTemplate();
pt.requestBodyAndHeader("direct:start", "someUri", "http://example.com");
However the above doesn't work (Camel complains about not having a default Endpoint).
What's the best way to go about this?
Although this question has already been answered, I wanted to share this other option to achieve what you're looking for, in case someone else still wonders how to do it:
There is a new method since Camel 2.16 called "toD" wich basically means a "dynamic to". Here is the official reference documentation.
from("direct:start")
.toD("${someUri}");
In this case, the toD method resolves the argument using the Simple language wich means you can use any property that the language supports.
You can also take a look at this other StackOverflow answer, about that same topic.
see these links for reference:
http://camel.apache.org/how-do-i-use-dynamic-uri-in-to.html
http://camel.apache.org/recipient-list.html
for an example, see this unit test
https://svn.apache.org/repos/asf/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RecipientListTest.java
I simply used curly braces without the '$' before it. Here is what I did:
{headers.reQueueName} instead of ${headers.reQueueName} for the uri and it worked :
<to id="requeue" uri="jmsamq:queue:{headers.reQueueName}"/> here is my implementation :
<route id="_throttleRoute">
<from id="throttleRouteStarter" uri="direct:throttleRouteService"/>
<log id="_Step_5" message="Camel throttle Route Started"/>
<log id="_Step_5_1" message="Camel throttle Route is ${headers.next}"/>
<to id="restThrottleCall" uri="restlet:http://host:port/path"/>
<process id="throttleRouteProcess" ref="throttleServiceProcessor"/>
<choice id="_choice2">`enter code here`
<when id="_when3">
<simple>${headers.next} == 'requeue'</simple>
<to id="requeue" uri="jmsamq:queue:{headers.reQueueName}"/>
<log id="_Step_wait1" message="ReQueue sending to ${headers.reQueueName}"/>
</when>
<when id="_when4">
<simple>${headers.next} == 'process'</simple>
<log id="_logNext" message="Invoking Next Work Unit ${headers.next}"/>
<process id="jBPMRouteProcess" ref="jBPMRouteProcessor"/>
</when>
<otherwise id="_otherwise2">
<log id="_log5" loggingLevel="WARN" message="Next for orderId: ${headers.orderid} not found"/>
</otherwise>
</choice>
</route>

Categories

Resources