Setting multiple headers in camel route - apache-camel

Is it possible to set multiple exchange headers in camel route using single call to setHeader.
Something like this
<from uri="file://inputdir/?delete=true" />
<!-- need to set multiple headers at once(as a comma separated list)-->
<setHeader headerName="headername">
<constant>headerval</constant>
</setHeader>
<to uri="mock:end"/>
Or should I create a custom processor for this?

No you cant set multiple headers at once as far as I am aware. In your case a custom processor will probably be more effective.
You might want to look at the simple expression language here here is that you can OGNL notation in your camel route xml file. OGNL will allow you to specify a chain of methods in the expression.
For example suppose you have a message that contains an Employee object that has a getSalaryGrade() method you could set a header to this value by using the following syntax:
<setHeader headerName="SalaryGrade">
<simple>${body.getSalaryGrade()}</simple>
</setHeader>
You could for example create a simple class that returns a list and store the list in the header and then access the list via simple in the route. The following code is untested but should give you a idea.
public class ListCity {
public List<String> ListCities()
{
ArrayList< String> list = new ArrayList<String>();
list.add("New York");
list.add("JOhannesburg");
list.add("HoChiMinh");
return list;
}
}
Declare the list city bean in your xml. You can then set this list into a header by using something like this:
<setHeader headerName="CityList">
<simple>${listCity.ListCities()}</simple>
</setHeader>

Related

Add a new column and row to existing CSV data in Apache Camel

I am trying to add the new column and row/content to the existing CSV data but unable to achieve this in Apache Camel
I have used camel-csv component in the code and below is the snippet for the same.
<unmarshal>
<csv delimiter="|" useMaps="true" lazyLoad="true" />
</unmarshal>
When unmarshalling, getting "org.apache.camel.dataformat.csv.CsvUnmarshaller$CsvIterator" as class name but unable to get the exchange or cast to any type to this class as this is abstract class.
Let me know if we can use bean component and solution to add the column and content to the existing CSV data.
I can suggest an alternative solution. You can use BeanIO Data Format.
E.g :
BeanIODataFormat dataFormat = new BeanIODataFormat("classpath:beanio/mappings.xml", "ContactsCSV");
from("direct:convert-to-csv")
.marshal(dataFormat)
.to("file:xxxx")
.end();
You can find check data format details in docs. There is an examples file in there as well.

Apache Camel: Set 'description' for Processor using Java DSL

I can add a custom id and description to a <log> or most other types of processor in XML like this:
<log message="Hello" id="logId">
<description>Description of logging</description>
</log>
I've tried to do a similar thing with Java DSL:
from("direct:1")
.log("Hello")
.id("logId")
.description("Description of logging")
But the description is applied to the route, not the processor. (The routeId() method is provided to apply the id to the route instead of the processor.)
Looking through the Camel source code, ProcessorDefinition's definition of id() has a bunch of code to apply it to the last block or output, preceded by this comment:
// set it on last output as this is what the user means to do
// for Block(s) with non empty getOutputs() the id probably refers
// to the last definition in the current Block
There is no similar definition of description() in ProcessorDefinition, so this simpler method is inherited from OptionalIdentifiedDefinition:
public T description(String text) {
if (text != null) {
if (description == null) {
description = new DescriptionDefinition();
}
description.setText(text);
}
return (T) this;
}
It seems to me that the Java DSL does not provide a way to set the description for log or other processors. Is this true, or did I miss something?
(If it is true, should I work on a patch to improve the DSL?)

use uuid on the move option on Camel File route

how can I use uuid
<bean id="uuid" class="org.apache.camel.impl.SimpleUuidGenerator" />
on the move option on Camel File route ? in order to add a uuid string on the file name when moving it
The ExchangeId is a UUID, so you can simply reference the '${exchangeId}' from Simple language without having to mess with setting up the bean.
If you really want to use your own Uuid generator, reference the bean name in the parameter:
${bean:uuid.generateid}
Where 'uuid' is your bean id and generateid is the method name example here: File language

Camel check file's last modified date frequently using scheduling service

I want to use camel in my project to check a file's last modified date every xx minutes using camel's scheduling/timer service.
I read the document for file component it seems there is a polling function, however there is also a timer component for camel.
Anyone has some code example if i want to do with the requirement?
I would use the file consumer end point.
Something like this:
file:c:/foldername?delay=5000
This will scan the folder every 5 seconds for files and for each file send a message on the route.
You would probably need to store the previous times somewhere such as a text file or database and then compare the modified variable passed in the message to the modified one stored in the database or file.
A rough example of this would look like follows:
<route id="CheckFileRoute">
<from uri="file:d:/RMSInbox?delay=5000&readLock=changed/>
<log message="${ file:modified }/>
<bean ref="CompareDates"/>
</route>
The file consumer will place a lot of information regarding the file in the header such as modified date. Go read this link for more details on the variables in the header http://camel.apache.org/file2.html
The compare dates bean would be java class that acts like a processor which would have a structure like this:
public class CompareDates {
#Handler
public void CheckDates
(
#Body Object msgbody
, #Headers Map hdr
)
{
Date newDate = (Date)hdr.get("CamelFileLastModified");
Date oldDate = readfromfileorDatabase
if(newDate>oldDate)
{
//the date has changed look busy
}
}
Hope this gets you going.

Replace GString tags in a file

i've got a word document saved in xml format. In this document, there are some GString Tag like $name.
In my groovy code, i load the xml file to replace this GString tag like this:
def file = new File ('myDocInXml.xml')
def name = 'myName'
file.eachLine { line ->
println line
}
But it doesn't works. The GString Tag doesn't be replaced by my variable 'name'.
Could anyone help me ?
THX
Better to use a templating here. Load the xmml file as a template and create a binding to replace the placeholders. A simple example could be like
def xml='''
<books>
<% names.each { %>
<book>
$it
</book>
<%}%>
</books>
'''
def engine=new groovy.text.SimpleTemplateEngine()
def template=engine.createTemplate(xml)
def binding=[names:['john','joe']]
template.make(binding)
Currently templating is the approach. But you might want to keep an eye on this issue in JIRA GROOVY-2505. It is a feature request to convert a String to a GString in cases when the string is read from an external source:
Several times it has been asked on the
mailing list on how to either convert
a String to a GString or to evaluate a
String as a GString. The need arises
when a String comes in from an
external source and contains a GString
expression, for example an XML file or
a Configuration file. Currently one
needs to either invoke the GroovyShell
or the SimpleTemplateEngine to
accomplish the task. In both cases
this takes several lines of code and
is not intuitively obvious. One could
ether add a GDK method to String such
as "evaluate" (which in my humble
opinion would be the nicest) or
provide a conversion of the form
"String as GString"
Pretty old question, however, issue http://jira.codehaus.org/browse/GROOVY-2505 still not solved...
There is a nice workaround, which behaves almost like GString substitution, by using Apache StrSubstitutor class. For me it is more comfortable than creating templates - you can use GStrings in XML files:
import org.apache.commons.lang.text.StrSubstitutor
strResTpl = new File(filePath + "example.xml").text
def extraText = "MY EXTRA TEXT"
map = new HashMap();
map.put("text_to_substitute", "example text - ${extraText}")
def result = new StrSubstitutor(map).replace(strResTpl);
XML file:
<?xml version="1.0" encoding="UTF-8"?>
<eample>
<text_to_substitute>${text_to_substitute}</text_to_substitute>
</example>
Result:
<?xml version="1.0" encoding="UTF-8"?>
<eample>
<text_to_substitute>example text - MY EXTRA TEXT</text_to_substitute>
</example>

Resources