Adding a varibale to the RouteDefination "from " in Apache camel - apache-camel

I am looking to amend the RouteDefination from in Apache Camel
I hav eproperties file as below
test1=test
queue1=queue
code as below
from( "activemq:queue:{{test1}}.{{queue1}}")
.transform()
.simple(" ${body} {{test1}}.{{queue1}}.hello ${date:now:yyyyMMdd}")
.to("stream:out");
this will become for route as
from( "activemq:queue:test1.queue")
i am looking to make it as
from( "activemq:queue:test1.queue_20170606")
which is ${date:now:yyyyMMdd}

This is not possible in Camel - the from endpoint is static.
However ActiveMQ supports queue wildcards which you can use to consume from multiple queues, and you can use JMS message selectors.
http://activemq.apache.org/wildcards.html
http://activemq.apache.org/selectors.html
The latter is not so performant as it needs to do a query on the queue.
If you want to do a route per yyyyMMdd, then you need to add/remove routes dynamic in Camel. See other questions on SO how to do that.

Related

Apache camel - How to use activemq Selective consumer using message body

I want two consumer with single activemq queue and wanted to filter while consuming. Selective is best option for me (please suggest if there is other). But sender does not sending me any header parameter or any property, selective only works with header or properties, now I wanted to filter message on message body . Is there any way to use selective with message body
My two messages body are differed by test and test2
{
"test":{
"abc":"123",
"cde":"123"
}
}
{
"test2":{
"abc":"321",
"cde":"321"
}
}
I want something like selective with message body
from("jms:selective?selector=" + java.net.URLEncoder.encode(${body.test})).
to("cxf:bean:replica01");
from("jms:selective?selector=" + java.net.URLEncoder.encode(${body.test2})).
to("cxf:bean:replica02");
Please suggest if there is any way to do so.
As the selector documentation for ActiveMQ 5.x points out, you can use XPath based selectors for messages which have XML bodies. However, the bodies of your messages aren't XML so there doesn't appear to be anyway to get the functionality you're looking for.
Keep in mind that as far as the broker is concerned the body of a message is just an array of bytes whereas message headers/properties are typed which allows for the kinds of comparison operations that make selectors viable.

Camel aggregation from two queues in Java DSL

I have two queues which having same type of objects in them. I want to aggregate them into a single queue through java DSL. Could anyone tell me if this is possible? If so, any code references?
If I understand your question correctly, it is possible to do such a thing.
If you need just to drive them into a single route (without any aggregations, enrichments, etc.) you can just proceed with this piece of code:
from('direct:queue1')
.to('direct:start');
from('direct:queue2')
.to('direct:start');
from('direct:start')
//there goes your processing
If you need to aggregate them later on, use Aggregator. Or you can use example from java-addict301's answer if it solves your case.
I believe this may be doable in Camel using the Content Enricher pattern.
Specifically, the following paradigm can be used to retrieve a message from one queue (where direct:start is) and enrich it with a message from the second queue (where direct:resource is). The combined message can then be built in your AggregationStrategy implementation class.
AggregationStrategy aggregationStrategy = ...
from("direct:start")
.enrich("direct:resource", aggregationStrategy)
.to("direct:result");
from("direct:resource")

change cxf ws-addressing properties in camel route

i am using cxf as a producer in an apache camel route with WS-Addressing.
I know that it is possible to set the SoapAction Header inside the route via (just as example might be wrong)
...
.setHeader("SoapAction").constant("anysoapactionwanted")
.to("cxf...
is it possible to the same with the WS-Addressing Action field? Because i noticed it is sent with the wrong value. There are 2 WS-Addressing Action values i need to put in and it is decided in the camel route which one to use.
You must be deciding the the required operation based on some value. In that case use Choice-When conditional block to derive correct action.

Handling incoming JMSCorrelationId in an Apache Camel route

I have an camel route consuming on a JMS (activemq) queue targeted to be called in a request/reply manner. Inside this route I split the message and invoke another activemq queue (also in a request/reply manner).
Heres a minimal route showing the situation
<route>
<from uri="activemq:A" />
<split>
<xpath>/root/subpart</xpath>
<inOut uri="activemq:B" />
</split>
</route>
The problem is that Camel does not set a new JMSCorrelationId (since there is already one from the incoming message). If nothing is done, you get responses with unknown correlationId's and the exchanges never end.
I didn't go into details but my guess is that the same temporaryQueue is used for the hole splitter but that it (logically) expects different correlation id's for each of the messages. All using the same, it recieves the first and does not know what to do with the others.
What would be the best solution to handle the situation ?
The one I've found working is to save in another header the incoming JMSCorrelationId (not sure I need to though), and removing it. This is not really as clean as I would want it to be, but I couldn't think of something else. Any ideas ?
Essentially, your case is described in this Jira issue It seems there will be an addition in 2.11 where you can ask Camel to create a new corr-id.
So, in the meantime, why don't you continue what you had working - to remove the JMSCorrelationId header <removeHeader headerName="JMSCorrelationId" /> before you send it to "activemq:B"? I guess that is the best solution for now.
You could, of course, play with the "useMessageIDAsCorrelationID" option as well on the second endpoint.

What's the difference between "direct:" and to() in Apache Camel?

The DirectComponent documentation gives the following example:
from("activemq:queue:order.in")
.to("bean:orderServer?method=validate")
.to("direct:processOrder");
from("direct:processOrder")
.to("bean:orderService?method=process")
.to("activemq:queue:order.out");
Is there any difference between that and the following?
from("activemq:queue:order.in")
.to("bean:orderServer?method=validate")
.to("bean:orderService?method=process")
.to("activemq:queue:order.out");
I've tried to find documentation on what the behaviour of the to() method is on the Java DSL, but beyond the RouteDefinition javadoc (which gives the very curt "Sends the exchange to the given endpoint") I've come up blank :(
In the very case above, you will not notice much difference. The "direct" component is much like a method call.
Once you start build a bit more complex routes, you will want to segment them in several different parts for multiple reasons.
You can, for instance, create "sub routes" that could be reused among multiple routes in your Camel context. Much like you segment out methods in regular programming to allow reusability and make code more clear. The same goes for sub routes using, for instance the direct component.
The same approach can be extended. Say you want multiple protocols to be used as endpoints to your route. You can use the direct endpoint to create the main route, something like this:
// Three endpoints to one "main" route.
from("activemq:queue:order.in")
.to("direct:processOrder");
from("file:some/file/path")
.to("direct:processOrder");
from("jetty:http://0.0.0.0/order/in")
.to("direct:processOrder");
from("direct:processOrder")
.to("bean:orderService?method=process")
.to("activemq:queue:order.out");
Another thing is that one route is created for each "from()" clause in DSL. A route is an artifact in Camel, and you could do certain administrative tasks towards it with the Camel API, such as start, stop, add, remove routes dynamically. The "to" clause is just an endpoint call.
Once starting to do some real cases with somewhat complexity in Camel, you will note that you cannot get too many "direct" routes.
Direct Component is used to name the logical segment of the route. This is similar process to naming procedures in structural programming.
In your example there is no difference in message flow. In the terms of structural programming, we could say that you make a kind of inline expansion to your route.
Another difference is Direct component doesn't has any thread pool, the direct consumer process method is invoked by the calling thread of direct producer.
Mainly its used for break the complex route configuration like in java we used to have method for reusability. And also by configuring threads at direct route we can reduce the work for calling thread .
from(A).to(B).to(OUT)
is chaining
A --- B --- OUT
But
from(A ).to( X)
from(B ).to( X)
from( X).to( OUT )
where X is a direct:?
is basically like a join
A
\____ OUT
/
B
obviously these are different behaviours, and with the second you could implement anylogic you wanted, not just a serial chain

Resources