conditional fileName expression in file endpoint - apache-camel

Is there any way to have a conditional expression in the fileName parameter of the file:// endpoint in Apache Camel?
I am using Java DSL (can't change this) to build the route, and the definition below does not seem to work
myroute.to("file://my-file-out?fileName=${header[myheader] eq 'EXPECTED_VALUE' ? 'EXPECTED' : 'UNEXPECTED'}")
Unfortunately I have to accomplish this in a single .to() method invocation as I am using a predefined (custom) application framework.

You can do it like this
myroute
.choice()
.when(header("myHeader").isEqualTo("EXPECTED_VALUE"))
.to("file://my-file-out?fileName=EXPECTED_VALUE")
.otherwise()
.to("file://my-file-out?fileName=UNEXPECTED")
.endChoice();
Another slightly different approach
myroute
.choice()
.when(header("myHeader").isEqualTo("EXPECTED_VALUE"))
.setHeader("finalFileName", simple("EXPECTED_VALUE"))
.otherwise()
.setHeader("finalFileName", simple("UNEXPECTED"))
.endChoice()
.to("file:///tmp?fileName=${header.finalFileName}")
.end()
;

The filenname value can refer to a header or property that in turn could be a expression. I have not tried it before, but maybe the formula could be in any of the available expression languages eg Groovy. Could this be a solution within the bounds you have?

Related

Access Camel exchange property in XML DSL

Assuming I have set a Camel exchange property in a Processor ...Example
exchange.setProperty(LASTPROCESSED, sortedBody[0].attribute6)
What would be the proper way of referencing this property in my XML based route ?
I tried ${property:LASTPROCESSED} and ${exchangeProperty:LASTPROCESSED}
I have no trouble referencing exchange Headers ( i.e. ${headers.xxx} )
Yes ...I have trolled through countless answers here without finding a solution.
I am running Camel 3.x
Turns out I had an issue elsewhere in the Route ...the proper way to access appears to be ${exchangeProperty.xxx}

Apache Camel - Mybatis select with parameters and useIterator

I'm trying to use Apache Camel (version 2.20.0) with mybatis component.
More specifically, I have to export a large set or record from database to file.
I'd like to prevent memory issues so I want to use the option consumer.useIterator. My route is:
from("mybatis:selectItemsByDate?statementType=SelectList&consumer.useIterator=true")
.split()
.body()
.process(doSomething)
to(file:my-path-file);
but my query has in input a parameter (the starting date to get data). How should I set this parameter?
In many example on internet I saw the parameter in the body or in the header of the Exchange message but I think is possibile only if the mybatis endpoint is in a "to" method. But the option "consumer.useIterator" is working only when the enpdoint is in a "from" method.
Please help me to understand how I can set the input for my query or if this is not supported yet (in this case if you can give some hint how to implement would be great)
thank you.
Then you need to start your route from something else, like a timer or direct endpoint, and then call the mybatis endpoint in a to, where you have set that information in the message body/header you use in the mybatis query so its dynamic.
Also you should set the splitter to be in streaming mode so it walks the iterator it gets from mybatis on-demand.

Camel Restlet - Binding query parameters to message headers

Looking through Camel docs I couldn't find any way that allow me to bind the query parameters within the headers. For example :
Let's say I have an endpoint like that
http://localhost:8080/services/resource?filter=xxx
End I want to get that parameter from the header
exchange.getIn.().getHeaders().get('filter')
The query parameter 'filter' is not returned in the header. Anyone of you knows if this feature is coming by default in camel? I know I can build the binding by myself, but i am just looking for choose among camel-servlet (apparently that binding is implemented by default) and camel-restlet.
If you choose camel-restlet you can use the
restletBinding=#refName
to convert the query string parameters to headers.
The #refName is the bean ID of a RestletBinding object in the Camel Registry.

SpEL for URI Evaluation in Apache Camel

Is it possible to use SpEL when specifying a URI in a route? I've tried this a few ways but doesn't seem to be working.
Would like to do something like:
<from uri="jms:queue:#{ ${mq.dynamic.switch} ? '$mq.dynamic.queue' : '$mq.static.queue'}?connectionFactory=#connectionFactory" />
I'm essentially trying to evaluate a property to determine what queues to leverage when configuring a JMS route.
No that is not possible in <from>. Howerver you can use Camel's property placeholders:
http://camel.apache.org/using-propertyplaceholder.html
And in Camel routes such as <to> you can use "dynamic-to" which allows to use any of the scripting languages such as SpEL also:
http://camel.apache.org/how-to-use-a-dynamic-uri-in-to.html
http://camel.apache.org/languages.html

How to use $header in routes

I'm creating a route using the Java DSL in Camel.
I'd like to perform a text substitution without creating a new processor or bean.
I have this:
.setHeader(MY_THING,
constant(my_template.replace("{id1}", simple("${header.subs_val}").getText())))
If I don't add 'constant' I get type mismatch errors. If I don't put getText() on the simple() part, I get text mismatch answers. When I run my route, it replaces {id} with the literal ${header.subs_val} instead of fetching my value from the header. Yet if I take the quotes off, I get compile errors; Java doesn't know the ${...} syntax of course.
Deployment takes a few minutes, so experiments are expensive.
So, how can I just do a simple substitution. Nothing I am finding on the web actually seems to work.
EDIT - what is the template? Specifically, a string (it's a URL)
http://this/that/{id1}/another/thing
I've inherited some code, so I am unable to simply to(...) the URL and apply the special .tof() (??) formatting.
Interesting case!
If you place my_template in a header you could use a nested simple expression(Camel 2.9 onwards) like in the example below. I am also setting a value to subs_val for the example, but I suppose your header has already a value in the route.
.setHeader("my_template", constant("http://this/that/{id1}/another/thing"))
.setHeader("subs_val",constant("22"))
.setHeader("MY_THING",simple("${in.header.my_template.replaceAll(\"\\{id1.?\",${in.header.subs_val.toString()})}"))
After this step header MY_THING has the value http://this/that/22/another/thing.
1)In this example I could skip to_String() but I do not know what's the type of your header "subs_val" .
2) I tried first with replaceAll(\"\{id1\"}\") but it didn't work with } Probably this is a bug...Will look at it again. That's why in my regex I used .?
3) When you debug your application inside a processor, where the exchange is available you can use SimpleBuilder to evaluate a simple expression easily in your IDE, without having to restart your app
SimpleBuilder.simple("${in.header.url.replaceAll(\"\\{id1.?\",${in.header.subs_val.toString()})}").evaluate(exchange, String.class);
Hope it helped :)

Resources