Comenzi Camel

Camel Read File Content

from("file://inputdir/").convertBodyTo(String.class)
*****************
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("queue:a").filter(header("foo").isEqualTo("bar")).to("queue:b");
from("queue:c").choice()
.when(header("foo").isEqualTo("bar")).to("queue:d")
.when(header("foo").isEqualTo("cheese")).to("queue:e")
.otherwise().to("queue:f");
}
};
CamelContext myCamelContext = new DefaultCamelContext();
myCamelContext.addRoutes(builder);

Selecteaza doar fisierele cu o anumita extensie
from("file:data/inbox?recursive=true&include=*.txt").
public void configure() {
from("ftp://rider.com/orders"
+ "?username=rider&password=secret")
.to("jms:incomingOrders");
}

ADDING A PROCESSOR
process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("We just downloaded: "
+ exchange.getIn().getHeader("CamelFileName"));
}
}).
to("jms:incomingOrders");
public void configure()
{
from("file:src/data?noop=true").to("jms:incomingOrders");
from("jms:incomingOrders")
.choice()
.when(header("CamelFileName").endsWith(".xml")).to("jms:xmlOrders")
.when(header("CamelFileName").endsWith(".csv")).to("jms:csvOrders");
from("jms:xmlOrders").process(new Processor() {
public void process(Exchange exchange) throws Exception {

System.out.println("Received XML order: "+ exchange.getIn().getHeader("CamelFileName"));
}
});

from("jms:incomingOrders")
.choice()
.when(header("CamelFileName").endsWith(".xml"))
.to("jms:xmlOrders")
.when(header("CamelFileName").regex("^.*(csv|csl)$"))
.to("jms:csvOrders");

from("jms:incomingOrders")
.choice()
.when(header("CamelFileName").endsWith(".xml"))
.to("jms:xmlOrders")
.when(header("CamelFileName").regex("^.*(csv|csl)$"))
.to("jms:csvOrders")
.otherwise()
.to("jms:badOrders");

ROUTING AFTER A CBR
The CBR may seem like it’s the end of the route; messages are routed to one of several
destinations, and that’s it. Continuing the flow means you need another route, right?
Well, there are several ways you can continue routing after a CBR. One is by using
another route, like you did in listing 2.4 for printing a test message to the console.
Another way of continuing the flow is by closing the choice block and adding another
processor to the pipeline after that.
You can close the choice block by using the end method:
from("jms:incomingOrders")
.choice()
.when(header("CamelFileName").endsWith(".xml"))
.to("jms:xmlOrders")
.when(header("CamelFileName").regex("^.*(csv|csl)$"))
.to("jms:csvOrders")
.otherwise()
.to("jms:badOrders")
.end()
.to("jms:continuedProcessing");
Here, the choice has been closed and another to has been added to the route. Now,
after each destination with the choice, the message will be routed to the continued-
Processing queue as well.

Using message filters

The filter looks like
this:
from("jms:xmlOrders").filter(xpath("/order[not(@test)]"))
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("Received XML order: "
+ exchange.getIn().getHeader("CamelFileName"));

This will output the following on the command line:
Received XML order: message1.xml

Using multicasting
Often in enterprise applications you’ll need to send a copy of a message to several different
destinations for processing. When the list of destinations is known ahead of
time and is static, you can add an element to the route that will consume messages
from a source endpoint and then send the message out to a list of destinations. Borrowing
terminology from computer networking, we call this the Multicast EIP.

With Camel, you can use the multicast method in the Java DSL to implement this
solution:
from("jms:xmlOrders").multicast().to("jms:accounting", "jms:production");

PARALLEL MULTICASTING
Sending messages in parallel using the multicast involves only one extra DSL method:
parallelProcessing. Extending the previous multicast example, you can add the
parallelProcessing method as follows:

from("jms:xmlOrders")
.multicast().parallelProcessing()
.to("jms:accounting", "jms:production");

This will set up the multicast to distribute messages to the destinations in parallel.
A default thread pool size of 10 is used if you don’t specify anything else. If you
want to change this default, you can set the underlying java.util.concurrent.ExecutorService
that’s used to launch new asynchronous message sends by using the
executorService DSL method. Here’s an example:
ExecutorService executor = Executors.newFixedThreadPool(16);

from("jms:xmlOrders")
.multicast().parallelProcessing().executorService(executor)
.to("jms:accounting", "jms:production");

This code increases the maximum number of threads to 16, in order to handle a
larger number of incoming requests. For more information on the Camel threading
model and thread pools, please see chapter 10.
By default, the multicast will continue sending messages to destinations even if one
fails. In your application, though, you may consider the whole process as failed if one
destination fails. What do you do in this case?

STOPPING THE MULTICAST ON EXCEPTION
Our multicast solution at Rider Auto Parts suffers from a problem: if the order failed
to send to the accounting queue, it might take longer to track down the order from
production and bill the customer. To solve this problem, you can take advantage of
the stopOnException feature of the multicast. When enabled, this feature will stop
the multicast on the first exception caught, so you can take any necessary action.
To enable this feature, use the stopOnException method as follows:
from("jms:xmlOrders")
.multicast().stopOnException()
.parallelProcessing().executorService(executor)
.to("jms:accounting", "jms:production");
To handle the exception coming back from this route, you’ll need to use Camel’s
error-handling facilities, which are described in detail in chapter 5.

Using recipient lists
For example, the following route will take the list of recipients from a header named
recipients, where each recipient is separated from the next by a comma:
from("jms:xmlOrders")
.recipientList(header("recipients"));
This is useful if you already have some information in the message that can be used to
construct the destination names—you could use an expression to create the list. In
order for the recipient list to extract meaningful endpoint URIs, the expression result
must be iterable. Values that will work are java.util.Collection, java.util.Iterator,
Java arrays, org.w3c.dom.NodeList, and, as shown in the example, a String with
comma-separated values.

from("jms:xmlOrders")
.setHeader("customer", xpath("/order/@customer"))
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
String recipients = "jms:accounting";
String customer =exchange.getIn().getHeader("customer", String.class);
if (customer.equals("honda")) {
recipients += ",jms:production";
}
exchange.getIn().setHeader("recipients", recipients);
}
})
.recipientList(header("recipients"));

The processor now sets the recipients header to "jms:accounting, jms:production"
only if the customer is at the gold level of support. The check for gold-level support
here is greatly simplified—ideally you’d query a database for this check. Any
other orders will be routed only to accounting, which will send them to production
after the checks are complete.

RECIPIENT LIST ANNOTATION
Rather than using the recipientList method in the DSL, you can add a @Recipient-
List annotation to a method in a plain Java class (a Java bean). This annotation tells
Camel that the annotated method should be used to generate the list of recipients
from the exchange. This behavior only gets invoked, however, if the class is used with
Camel’s bean integration.
For example, replacing the custom processor you used in the previous section with
an annotated bean results in a greatly simplified route:
from("jms:xmlOrders").bean(RecipientListBean.class);
Now all the logic for calculating the recipients and sending out messages is captured
in the RecipientListBean class, which looks like this:
public class RecipientListBean {
@RecipientList
public String[] route(@XPath("/order/@customer") String customer) {
if (isGoldCustomer(customer)) {
return new String[] {"jms:accounting", "jms:production"};
} else {
return new String[] {"jms:accounting"};
}
}

private boolean isGoldCustomer(String customer) {
return customer.equals("honda");
}
}

Using the wireTap method
Often in enterprise applications it’s useful and necessary to inspect messages as they
flow through a system. For instance, when an order fails, you need a way to look at
which messages were received to determine the cause of the failure.
You could use a simple processor, as you’ve done before, to output information
about a incoming message to the console or append it to a file. Here is a processor
that outputs the message body to the console:

from("jms:incomingOrders")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("Received order: " +
exchange.getIn().getBody());
}
})

Output:
Received order: GenericFile[E:\Inputfolder\instructiuni_camel.txt]
We just downloaded: Pe strada Mantuleasa.azw3
We just download azw3 filePe strada Mantuleasa.azw3
Received order: GenericFile[E:\Inputfolder\Pe strada Mantuleasa.azw3]
We just downloaded: Pe strada Mantuleasa.doc
We just download doc filePe strada Mantuleasa.doc
Received order: GenericFile[E:\Inputfolder\Pe strada Mantuleasa.doc]

Using a Processor to translate from a custom format to CSV format
public class OrderToCsvProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
String custom = exchange.getIn()
.getBody(String.class);
String id = custom.substring(0, 9);
String customerId = custom.substring(10, 19);
String date = custom.substring(20, 29);
String items = custom.substring(30);
String[] itemIds = items.split("@");
StringBuilder csv = new StringBuilder();
csv.append(id.trim());
csv.append(",").append(date.trim());
csv.append(",").append(customerId.trim());
for (String item : itemIds) {
csv.append(",").append(item.trim());
}
exchange.getIn().setBody(csv.toString());
}
}

First you grab the custom format payload from the exchange B. It’s a String type, so
you pass String in as the parameter to have the payload returned as a String. Then
you extract data from the custom format to the local variables C. The custom format
could be anything, but in this example it’s a fixed-length custom format. Then you
map the CSV format by building a string with comma-separated values D. Finally, you
replace the custom payload with your new CSV payload E.
You can use the OrderToCsvProcessor from listing 3.1 in a Camel route as follows:

You can use the OrderToCsvProcessor from listing 3.1 in a Camel route as follows:
from("quartz://report?cron=0+0+6+*+*+?")
.to("http://riders.com/orders/cmd=received&date=yesterday")
.process(new OrderToCsvProcessor())
.to("file://riders/orders?fileName=report-${header.Date}.csv");

sau

TRANSFORMING USING BEANS
Using beans is a great practice because it allows you to use any Java code and library
you wish. Camel imposes no restrictions whatsoever. Camel can invoke any bean you
choose, so you can use existing beans without having to rewrite or recompile them.
Let’s try using a bean instead of a Processor

public class OrderToCsvBean {
public static String map(String custom) {
String id = custom.substring(0, 9);
String customerId = custom.substring(10, 19);
String date = custom.substring(20, 29);
String items = custom.substring(30);
String[] itemIds = items.split("@");
StringBuilder csv = new StringBuilder();
csv.append(id.trim());
csv.append(",").append(date.trim());
csv.append(",").append(customerId.trim());
for (String item : itemIds) {
csv.append(",").append(item.trim());
}
return csv.toString();
}
}

The first noticeable difference between listings 3.1 and 3.2 is that listing 3.2 doesn’t
use any Camel imports. This means your bean is totally independent of the Camel API.
The next difference is that you can name the method signature in listing 3.2—in this
case it’s a static method named map.
the mapping output C.
You can use OrderToCsvBean in a Camel route as shown here:
from("quartz://report?cron=0+0+6+*+*+?")
.to("http://riders.com/orders/cmd=received&date=yesterday")
.bean(new OrderToCsvBean())
.to("file://riders/orders?fileName=report-${header.Date}.csv");
TRANSFORM CSV to XML

public class MyTransform implements Processor{
public void process(Exchange exchange) throws Exception {
String myString = exchange.getIn().getBody(String.class);
String[] lineSeparator = myString.split(System.getProperty("line.separator"));
StringBuffer sb = new StringBuffer();
sb.append("<Employees>");
for (String lineData : lineSeparator)
{
String [] commaSeparator=lineData.split(",");
sb.append("<Employee>");
sb.append("<EmployeeID>"+commaSeparator[0].toString()+"</EmployeeID>");
sb.append("<Name>"+commaSeparator[1].toString()+"</Name>");
sb.append("<Salary>"+commaSeparator[2].toString()+"</Salary>");
sb.append("</Employee>");
}
sb.append("</Employees>");
System.out.println("MyProcessor complete");
exchange.getIn().setBody(sb.toString());
}
}
clasa de main
import org.apache.camel.builder.RouteBuilder;
public class CSVToXMLTransformation {
public static void main(String[] args) throws Exception {
CamelContext _ctx=new DefaultCamelContext();
_ctx.addRoutes(new RouteBuilder(){
public void configure() throws Exception
{
from("file:D:\\ApacheCamel\\Demo1\\IN")
.process(new MyTransform())
.to("file:D:\\ApacheCamel\\Demo1\\OUT?fileName=emp.xml");
}
});
_ctx.start();
Thread.sleep(4000);
_ctx.stop();
}
}

TRANSFORMING USING THE TRANSFORM() METHOD FROM THE JAVA DSL

Transform() is a method in the Java DSL that can be used in Camel routes to transform
messages. By allowing the use of expressions, transform() permits great flexibility,
and using expressions directly within the DSL can sometimes save time. Let’s look
at a little example.

Suppose you need to prepare some text for HTML formatting by replacing all line
breaks with a <br/> tag. This can be done with a built-in Camel expression that
searches and replaces using regular expressions:
from("direct:start")
.transform(body().regexReplaceAll("\n", "<br/>"))
.to("mock:result");
What this route does is use the transform() method to tell Camel that the message
should be transformed using an expression. Camel provides what is know as the
Builder pattern to build expressions from individual expressions. This is done by
chaining together method calls, which is the essence of the Builder pattern.

The Direct component
The example here uses the Direct component (http://camel.apache.org/direct) as the
input source for the route (from("direct:start")). The Direct component provides
direct invocation between a producer and a consumer. It only allows connectivity from
within Camel, so external systems can’t send messages directly to it. This component
is used within Camel to do things such as link routes together or for testing.

Camel also allows you to use custom expressions. This is useful when you need to be in
full control and have Java code at your fingertips. For example, the previous example
could have been implemented as follows:
from("direct:start")
.transform(new Expression() {
public <T> T evaluate(Exchange exchange, Class<T> type) {
String body = exchange.getIn().getBody(String.class);
body = body.replaceAll("\n", "<br/>");
body = "<body>" + body + "</body>";
return (T) body;
}
})
.to("mock:result");

Transforming XML
Camel provides two ways to perform XML transformations:
■ XSLT component—For transforming an XML payload into another format using
XSLT stylesheets
■ XML marshaling—For marshaling and unmarshaling objects to and from XML
Both of these will be covered in following sections.
Transforming XML with XSLT
XSL Transformations (XSLT) is a declarative XML-based language used to transform
XML documents into other documents. For example, XSLT can be used to transform
XML into HTML for web pages or to transform an XML document into another XML
document with a different structure. XSLT is powerful and versatile, but it’s also a
complex language that takes time and effort to fully understand and master. Think
twice before deciding to pick up and use XSLT

Using the XSLT component is straightforward because it’s just another Camel component.
The following route shows an example of how you could use it; this route is also
illustrated in figure 3.5.
from("file://rider/inbox")
.to("xslt://camelinaction/transform.xsl")
.to("activemq:queue:transformed")
The file consumer picks up new files and routes them to the XSLT component, which
transforms the payload using the stylesheet. After the transformation, the message is
routed to a JMS producer, which sends the message to the JMS queue. Notice in the
preceding code how the URL for the XSLT component is defined: xslt://camelinaction/
transform.xsl. The part after the scheme is the URI location of the stylesheet
to use. Camel will look in the classpath by default.

Prefixes supported by the XSLT component for loading stylesheets
<none> xslt://camelinaction/
transform.xsl
If no prefix is provided, Camel loads the
resource from the classpath
classpath: xslt://classpath:com/mycompany/transform.xml ->Loads the resource from the classpath
file: xslt://file:/rider/config/transform.xml ->Loads the resource from the filesystem
http: xslt://http://rider.com/styles/transform.xsl->Loads the resource from an URL
Transforming XML with object marshaling

In Camel, this marshaling process is provided in ready-to-use components known
as data formats. We’ll cover data formats in full detail in section 3.4, but we’ll take a
quick look at the XStream and JAXB data formats here as we cover XML transformations
using marshaling.
TRANSFORMING USING XSTREAM
XStream is a simple library for serializing objects to XML and back again. To use it,
you need camel-xstream.jar on the classpath and the XStream library itself.
Suppose you need to send messages in XML format to a shared JMS queue, which is
then used to integrate two systems. Let’s look at how this can be done.

When using the XML DSL, you can declare the data formats used at the top B of the
<camelContext>. By doing this, you can share the data formats in multiple routes.
In the first route, where you send messages to a JMS queue, you use marshal C,
which refers to the id from B, so Camel knows that the XStream data format is
being used.
You can also use the XStream data format directly in the route, which can shorten
the syntax a bit, like this:
<route>
<from uri="direct:foo"/>
<marshal><xstream/></marshal>
<to uri="activemq:queue:foo"/>
</route

The same route is a bit shorter to write in the Java DSL, because you can do it with one
line per route:
from("direct:foo").marshal().xstream().to("uri:activemq:queue:foo");

Yes, using XStream is that simple. And the reverse operation, unmarshaling from XML
to an object, is just as simple:
<route>
<from uri="activemq:queue:foo"/>
<unmarshal ref="myXstream"/>
<to uri="direct:handleFoo"/>
</route>