Producing multiple outputs from a Camel Processor/Component - java

I am trying to implement a Camel Component/Processor that takes one input and produces multiple output messages, similar to a Splitter. Like Splitter, the output should go to the next processor/endpoint in the route.
I have looked at Splitter & MulticastProcessor classes in the hope that I can reuse them or use similar logic. The idea, as I understood, is to create an new Exchange for each output and emit them. To do this, I need to provide the endpoint to which output is written to. This works, if I dynamically create the end point within the Processor class; my requirement is to send the output to the end point configured in the route. That is in the route below, mycomponent needs to write (multiple times) to file:output.
<route>
<from uri="file:input"/>
<to uri="mycomponent:OrderFlow?multi.output=true"/>
<to uri="file:output" />
</route>
In case of Splitter, it is instantiated by SplitDefinition class which has access to the output Processor/Endpoint.
a) From within a Processor is it possible to access the configured Output Processor/Endpoint?
b) If not, should I be writing a ProcessorDefinition class for my processor? Any pointers on this would help.
Two solutions suggested below by Petter are,
a) Inject a Producer template
b) Use Splitter component with a method call instead of writing a new component.

I assume you have read this page.
Yes, you can send multiple exchanges from a custom processor, but not really to the next processor in the flow. As in the link above, you can decouple the component implementation by injecting a producer template with a specific destination. You can cut your route into several parts using the direct or seda transport and make your component send the messages there. This way, you can reuse the code in several routes.
This is, as you point out, done in the splitter component (among others) in Camel core. Take a look at the multicastprocessor baseclass for example. However, there processors are aware of the following processors in the route, thanks to the route builder. You custom processor is not that lucky.
You can, non the less, extract that information from the CamelContext. Get hold of your route and there you can find the processors in the route. However, that seems like overcomplicating things.
UPDATE:
Instead of trying to alter the DSL, make use of the already existing DSL and components.
.split().method("mycomponent", "OrderFlow")
Instead of emitting new exchanges, your OrderFlow method just needs to create a List<..> with the resulting messages.

Related

Camel: route messages based on the contents of a map

Currently, my code for routing messages in Camel according to a JMS message header field looks like this:
// MyRouteBuilder.java
#Override
public void configure() {
from(...)
.choice()
.when(header("type").isEqualTo("A"))
.to("proc_a:1")
.when(header("type").isEqualTo("B"))
.to("proc_b:1", "proc_b:2", "proc_b:3")
.when(header("type").isEqualTo("C"))
.to("proc_c:1", "proc_c:2")
.when(...)
.to(...) // ~15 more branches to follow
.otherwise()
.to("proc_default");
}
Dependend on the value of the type header field, there is a specific pipeline of processors that should be used in each case. As you can see, the code is not only repetitive, but also cumbersome to maintain.
There already is a dynamically created Map<String, String[]> which maps types to processors, e.g. the key B returns ["proc_b:1", "proc_b:2", "proc_b:3"]. However, I don't know how to make use of it in the scenario shown above.
I also read about the dynamic router. However, the given example didn't really help me and I don't want to add more complexitiy by having to manage the state of my routing logic or to ensure thread safety.
I'm grateful for any solution. The only requirements are that I'm stuck with Camel 2.15 and that I'm not allowed to adapt the existing processors (this especially means that the routing logic should not remove any header fields since they are needed later on).
Use dynamic to (eg toD), where you use some java method to compute the url to route to: http://camel.apache.org/how-to-use-a-dynamic-uri-in-to.html and here as well about dynamic to: http://camel.apache.org/message-endpoint.html

How to send a message using Apache Camel?

I am trying to create a sample application hosted at "mina:tcp://localhost:9991" that sends a very simple message to a server hosted at "mina:tcp://localhost:9990".
Now admittedly I have some problems understanding how to do this. My first approach was to create a class called Message, that has two fields: String order and String host. However, I am terribly confused on how to do this.
First I tried to follow the loadbalancer-example basing myself on the ReportGenerator and create a MessageGenerator class that could create a message and return it:
http://camel.apache.org/loadbalancing-mina-example.html
However, there is a problem, I need parameters to create my Message, something that doesn't happen when creating the Report from the example:
//Message constructor
public Message(String order, String host){
//constructor stuff
}
By reading Camel in Action I know how to use beans to call methods that have no parameters, however I still do not understand how I should use them to call a method that has several parameters (Am I forced to use processors?)
Then i realized that perhaps I am complicating things a little bit and there is an easier way to send messages. So I tried another approach that resulted in a small sample of code that does not work as well. I have created a separate question for that matter:
Apache camel send a simple message
Obviously I am doing something wrong and I don't get what. So, I have 2 questions:
Manning's Camel in Action defines an Easy way and a Hard way to use beans, but I did not understand the easy way of using beans with parameters. Can someone provide an example of it?
Is there a way to send a message composed of several fields in Camel (an easy way, without processors) that does not involve using beans? If so, how?
There are several ways to sends Messages in Camel. According to the help provided in the Camel forums, the two best are:
Using beans linked to POJOS and routes (example: http://camel.apache.org/loadbalancing-mina-example.html)
Using the Producer Template (docs: http://camel.apache.org/producertemplate.html)
Hope it helps someone one day.

How to build pipes-and-filters eip pattern with apache-camel

I'm trying to do a PoC in order to implement the pipes and filters eip pattern with Apache Camel.
From Camel documentation, I'm assuming that each filter must be implemented as an Endpoint ("With Camel you can split your processing across multiple independent Endpoint instances which can then be chained together.")
So, if I understood correctly, the Authenticate filter (from the example) must implement the Endpoint interface.
The "problem" is that I don't want to "re-invent the wheel". So instead of implementing the interface from the scratch, I'm almost sure that I can use an already implemented one. And the one is the BeanEndpoint.
Is that right?
I found a few examples of pipes and filters patterns (like this one) but none of then show how to implement the beans.
Can someone provide a bean implementation example?
TIA,
Bob
First of all, although I get where you're coming from when you say "camel implements filters as endpoints", I wouldn't strictly classify them as endpoints. More like message transformer/translators in my opinion.
So, in case you need to implement a custom filter as per your requirement, use the processor interface.
Basically, write a class(say, CustomProcessor) that implements Camel's Processor and write your custom filter strategy. Then, call it in your route as to("CustomProcessor").
The Processor page will surely clear all your concerns, so please have a look.
Also I assume you're aware of the camel message-filter pattern.
Thank you.
The Camel EIPs is listed here, and they all have examples and whatnot
http://camel.apache.org/eip
So for the pipes and filters you can find it on that link and see some examples
http://camel.apache.org/pipes-and-filters.html
And it seems you are new to Camel. Then I suggest to read this intro article to get your heads around Camel: http://java.dzone.com/articles/open-source-integration-apache

Does onCompletion() order matter in camel DSL?

I am trying to set some headers on a message that is manipulated as it passes through the processors references in my camel DSL. The very first thing I have, however, is a processor for .onCompletion, which is supposed to read the message from the exchange, get the headers and log them.
Does that have to come last in my DSL? It appears that my finaly .process() processor can see all of the new header values I added through the rest of the code, but when I go to log them all at .onCompletion, the values for those headers is null. it's almost like it has a stale version of the message or exchange or something. Why else would this be happening?
Yes you should configure things like
onCompletion
onException
intercept
errorHandler
transacted
policy
etc
In the start of your route. However the DSL is Camel 2.x is very open, and thus you can in some places configure this elsewhere (eg not in the start). But the rule of thumb is to do this first. And then after that, you regular route.
Side note: Mind that Camel also allows you to configure these kind on global level (aka context scope) instead of route. Eg you can have
a context scoped error handler. And then only in a special route
override and have a route special error handler.
In Camel 3.0 onwards we will make the DSL more strict, so we enforce configuration in the start. This also reduces the number of methods you would see in the code assistance list (eg pressing ctrl + space) in the regular routes. As those configurations would then no longer be listed.
The reason why they show up, is that they inheirt the same base class which is the corner stone in the DSL. And we don't wanna break this in the current 2.x line as then some people may get affected.
the order shouldn't matter...it should be using a copy of the Exchange when the route has completed regardless...post your route and we can perhaps help more

Camel Routes and Endpoints

I've been poring over the Apache Camel docs trying to get a concrete understanding of two of its most basic concepts (endpoints and routes), and although these terms are used everywhere throughout the docs, I can find no reference that actually defines what they are and what they are used for. And although their names are fairly obvious-sounding, and I think I understand what they are, I've now been assigned to a task that has landed me neck-deep in Apache Camel Land, and its absolutely vital that I understand what these mechanisms are.
My guess is that an "endpoint" is just a bean - one that can be configured in a config file like any other - that maps a name to a URI/port combo (this taken from the W3C docs). In the context of Apache Camel, my guess is that endpoints are used to connect components together, so that "routes" (connections/maps) can be formed between them. So when Component A living at Endpoint 1 wants to communicate with Component B living at Endpoint 2, so long as there is a mapping from 1 to 2, Camel will be able to transmit messages between these two.
Please stop me and correct me if I am wrong here!
So now, I've seen examples where it looks like routes can be configured in Java:
from("endpointA").routeId("someMessage").to("endpointB");
And I've seen examples where it looks like routes can be configured in XML:
<route id="">
<from .../>
<to .../>
</route>
Are these two methods for configuring routes, or are they different concepts altogether?
Finally, what is the format of the messages that can be routed between endpoints? If it has to be XML, for example, what is the XSD/schema of these routed messages? If it has to be a Java object, what bounds/restrictions apply to the objects that Camel can send?
It seems like you are getting a decent grasp of the concept.
I think it helps to think about endpoints in more abstract terms. The camel documentation is not much help here. Endpoints can be thought of as interfaces to a component. Each component can have 1 or more endpoints configured. It helps me to think about endpoints within the context of a route. A simple route can go from Endpoint A (This could be a JMS Queue, tcp socket, file or any camel component) and go to Endpoint B (which can be any camel component). You can of course have processors in the route too that transform the data.
The two examples of route creation you give are just that, two ways to create a route. They are the examples of the same concept. The first being Java DSL and the second using XML.
The format of the messages is typically XML, and the XML can be any valid XML and does not need to be tied to an XSD. The message can also be any Java object. As long as it is staying in the JVM (ie, not going over a socket) it doesn't need to be serializeable.
Route is an ordered combination of processing steps
Endpoint represents the beginning or end of a route (for the most part), that other routes might connect to as their beginning/end or might back onto an external system (e.g. JMS, email, etc.)

Categories

Resources