Bean method invocation: dynamic way - apache-camel

I'd like to dynamically invoke bean method depending on some header value:
This seems doesn't work: <to uri="bean:myBean?method=${in.header.methodName}&multiParameterArray=true"/>
Any ideas?

You can just set the method name in the header called "CamelBeanMethodName" and route your message to "bean" without specifying any method.

See this FAQ
http://camel.apache.org/how-to-use-a-dynamic-uri-in-to.html
From Camel 2.16 its easier as you can use <toD .. which is the dynamic-to. In older releases you can use the recipient list EIP. Its all explained in that FAQ.

Related

In Apache Camel what does "route()" do in a restful declaration?

Trying to google "route" in relation to Camel is like trying to google "the". Browsing the docs and can't find it either, only an interface called Route.
Inherited some code that looks like
rest("/someRoute")
.description("Some description")
.consumes("text/plain")
.produces("text/plain")
.post()
.route()
.to("direct:toSomewhere");
What does route() do? I have tried with and without route() and it doesn't seem to do anything.
Using .route allows you to define new route(s) within your rest-definition. It can be handy if your route is short or if you just want to process/transform/validate the message in someway before sending it to your actual consumer endpoint.
For example
rest("/someRoute")
.id("someRoute")
.description("Some description")
.post()
.consumes("text/plain")
.produces("text/plain")
.route()
.routeId("someRoutePost")
.process(new SomeMessageProcessor())
.to("direct:toSomewhere")
.end()
.endRest()
.get()
.route()
.routeId("someRouteGet")
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(405))
.setBody(constant("GET not allowed on this route"))
.end()
.endRest()
But if you just want to call direct consumer endpoint and do this stuff there instead you can do that.
it is up to ones preference really.
thanks, I see if I wanted to say call .log() I would have to put .route() first
Yes. Camel uses method-chaining with its Java-DSL where something like this is often required. When defining Rest most methods return RestDefinition but if you look closely .route method returns RouteDefition instead.
To get back to RestDefition from route one can use .endRest() as the .end() in the example doesn't really do anything other than make it easier to see where to RouteDefition block ends.
Update: Note that this example is for Camel 3.14.0. In Newer versions of Camel route() and endRest() methods have been Removed from RestDefition class. Example for Camel 3.18.1 can be found here.

toD() - Dynamic URI formation in camel 2.23 scheduled via Quartz

I'm newbie to Apache camel and wanted to Implement the toD() which is to dynamically frame the URI and add request params values from Beans..
Code snippet below -
from("quartz2://timer?cron=0+0/1+++*+?")
.noAutoStartup().routeId(ROUTE_ID).log("Route Started")
.toD(http://localhost:3420/contextpath?from=${bean:bean.from} "+ "&size=${bean:bean.size}")
.process(processor)
Seems like, on every hit via Quartz the same URL is being triggered and hence I see duplicate values saved to DB.
Please suggest why Dynamic uri is not working as expected.
Am calling the processor, computing and setting the Bean values which i get from Response of Endpoint. But when the next time Quartz hits the url, the bean values are not updated and takes the default value
. Bean definition is usual getter setter, and registration is I have used Simple registry
SimpleRegistry simpleRegistry = new SimpleRegistry ();
// create CamelContext
context = new DefaultCamelContext (simpleRegistry);
simpleRegistry.put("bean", bean);
Thanks in Advance
In order to use dynamic URI on a camel-route you must include your variable inside a Simple expression.
Since Camel 2.16.0 release endpoint implementation toD() supports the Simple expression language so you can define a dynamic-URI as message-endpoint:
from("quartz2://timer?cron=0+0/1+++*+?")
.noAutoStartup()
.routeId(ROUTE_ID)
.log("Route Started")
.toD( "http://localhost:3420/contextpath?from=${bean:bean.from}&size=${bean:bean.size}" );
So the expressions ${bean:bean.from} and ${bean:bean.size} should get directly interpolated by using Bean language inside your URI-string. This bean-component bean: tells Camel to get the bean registered with your specified name bean and call the specified methods from and size.
Apache Camel: Rest DSL, section Using Dynamic to() has also a note:
Note: we need to use .endRest() to tell Camel where the route ends, so we can go back to the Rest DSL and continue defining REST services.
Otherwise you could implement that dynamic endpoint using simple inside your regular to(). See Apache Camel: How to use a dynamic URI in to().

How to call a method with parameters in Apache Camel using Java DSL

How to call a method in Camel Route using Java DSL? I want to get a compile time error in Eclipse if I am using the wrong signature for method.
.bean(Foo.class, "setDetails("1", "Camel")")
Here I won't get compile time error for the wrong method signature as method was defined in string.
This is, as far as I know, not possible because Camel calls the method through reflection API.
What you can do, is to create constants in Foo.class with the method names and then use the constants in the bean calls instead of the hard-coded method name Strings.
But even then, you are of course able to rename a method in the bean without adapting the constant. The functionality would be broken but the compiler would be still happy.
If the bean is dedicated to Camel routes and under your control, the best you can do is to refactor the bean.
Remove the method parameters, set them on the message exchange and inject them with #Header, #Property
Split the bean into very small beans with only one method to get rid of the method names
Try this
.bean(Foo.class, "setDetails(1, 'Camel')")
If your first parameter is of type int just put the number without quotes
Second parameter is String, so you should put String to single quotes.
According to the docs, from camel 2.9 onwards, you can do pass in an integer and a string as parameters in a method call (using your example) like this:
.bean(Foo.class, "setDetails(1, 'camel')")
OR
.to("bean:Foo?method=setDetails(1, 'camel')")
If I understand the question correctly, you want a compile-time error about something that is evaluated at runtime. This is simply not possible.

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.

Camel content based router with a lot of conditions

I have a message with a certain value (e.g. 100, 101) in header and I need to take a specific action depending on that value.
I know I can write a route with when / otherwise branches for content-based routing.
My question is: what if I have about 400 different cases? Is there a best practice in these cases to manage the routing?
Yes use recipient list instead which can compute the endpoint dynamically - eg its a dynamic to. See this FAQ link for further details: http://camel.apache.org/how-do-i-use-dynamic-uri-in-to.html
another option is to use a ProducerTemplate to send messages to any endpoint from a POJO class, just need to inject/pass in a handle to the CamelContext, etc.

Resources