I'm trying to wrap my head around Apache Camel, and after spending some time this morning reading both the online Camel docs as well as the Javadocs, I have some questions that I can't seem to find answers for.
Is it true that all endpoints are either consumers or producers (or both)? Is it true that all processors are endpoints? Are there
any endpoints that are not processors?
What's the difference between a Message header and an Exchange? An exchange is considered to be a "message container", but how is that different from the metadata that a header would contain?
Is it typical to implement your own Message/Exchange? If so, what would be an example of doing so, and "straying" from the typical DefaultMessage and DefaultExchange?
Thanks in advance.
First things first: A good suggestion is to read the book Camel in Action, it explains most of the basic concepts. There is a free first chapter available online which explains the kind of questions you ask http://manning.com/ibsen/
An endpoint references a component and some component specific options, such as addresses etc. The endpoint can then (depending on the component) function as either consumer (ex. "servlet:path/to/web/service") or producer (ex. "http://localhost/path/to/web/service") or both of them (ex. "jms:queue:orderQueue").
There are headers in Camel messages as well. An exchange outlives an entire route, and exchange properties will also stay for the entire route. Message headers in Camel are a bit different concept. They are often closely mapped to the component used - i.e. a HTTP endpoint might set/change headers (for instance COOKIES etc.) while HTTP headers has no influence on exchange properties as these are for use within the camel route and camel logic only. The exchange also wrapps other non message specific things, such as exceptions.
It is quite uncommon to develop new message implementations. There could be a point in extending DefaultMessage when you have implemented your own component/protocol and need to keep instances of helper objects around in the message or whatnot. It's typically not done even when developing components. I have never heard of any custom implementation of an Exchange, and you should typically not do so without good reasons.
#DirtyMikeAndTheBoys you wrote:
Is it true that all processors are endpoints? Are there any endpoints
that are not processors?
This is not true. 'Processors' in Camel terminology are callbacks which are part of some pattern (like Aggregator, Message Channel or RoutingSlip). Processors receive the messages when they are flowing within a route and do something on messages. Messages are wrapped within Exchanges.
An Endpoint is where a route will receive messages (consumer endpoint) and where it will send the processed messages (To endpoint). So when you see the 'from' clause in a route, Camel engine is using a 'Consumer' instance associated with the endpoint instance defined in 'from' clause. It really depends on the endpoint implementation whether a new consumer instance is created/reused every where that given endpoint appears in a 'from' clause in your camel context.
Similarly when the same endpoint is mentioned in a 'To' clause, a Producer instance will be used (either created/reused) and will remain associated with the endpoint instance.
Related
I have a camel cxf-rs endpoint that splits the requests into two main parts.
form("cxfrs:bean:rsServer")
.when(isForward()).to("cxfrs:http://example.com")
.otherwise().process(myCustomDispatcher) // i want to get rid of this custom dispatcher
The first part is straight forwarded to a different service.
For the second part i would like to dispatch/call classes/methods that have jaxrs annotation. Currently i have a custom processor myCustomerDispatcher that duplicates the logic from the annotations and dispatches manually to classes and methods. Especially #Path and #PathParams are duplicated.
I tried:
to("bean:MyJaxRsImplemantion") this will work for beans with a single method matching the parameters in the camel exchange, but does not consider jax-rs annotations.
Serveral combinations with to("cxfrs:bean:cxfEndpoint?resourceClasses=MyJaxRsImplemantion"). it either requires a forwarding address, or acts on a new endpoint creating camel exchanges. I couldn't find a way to call the actual implementation.
The ProduceTemplates all seem to handle singular paths or situations.
Question:
How can i write a camel route that actually calls jax-rs resource methods without forwarding to a new service?
This is actually a really tough question. For one, even when you google it you don't get any straight answers. After an eternity of web surfing, it feels like it's the law of the land for camel routes to call jx-rs resource methods by forwarding to a new service.
And yes, it's almost like to("bean:MyJxRsImplemantion") is DESIGNED to ignore jax-rs annotations. So I've decided that it's impossible. Sorry.
I'm just getting into Spring (and Java), and despite quite a bit of research, I can't seem to even express the terminology for what I'm trying to do. I'll just explain the task, and hopefully someone can point me to the right Spring terms.
I'm writing a Spring-WS application that will act as middleware between two APIs. It receives a SOAP request, does some business logic, calls out to an external XML API, and returns a SOAP response. The external API is weird, though. I have to perform "service discovery" (make some API calls to determine the valid endpoints -- a parameter in the XML request) under a variety of situations (more than X hours since last request, more than Y requests since last discovery, etc.).
My thought was that I could have a class/bean/whatever (not sure of best terminology) that could handle all this service discovery stuff in the background. Then, the request handlers can query this "thing" to get a valid endpoint without needing to perform their own discovery and slow down request processing. (Service discovery only needs to be re-performed rarely, so it would be impactful to do it for every request.)
I thought I had found the answer with singleton beans, but every resource says those shouldn't have state and concurrency will be a problem -- both of which kill the idea.
How can I create an instance of "something" that can:
1) Wake up at a defined interval and run a method (i.e. to check if Service discovery needs to be performed after X hours and if so do it).
2) Provide something like a getter method that can return some strings.
3) Provide a way in #2 to execute a method in the background without delaying return (basically detect that an instance property exceeds a value and execute -- or I suppose, issue a request to execute -- an instance method).
I have experience with multi-threaded programming, and I have no problem using threads and mutexes. I'm just not sure that's the proper way to go in Spring.
Singletons ideally shouldn't have state because of multithreading issues. However, it sounds like what you're describing is essentially a periodic query that returns an object describing the results of the discovery mechanism, and you're implementing a cache. Here's what I'd suggest:
Create an immutable (value) object MyEndpointDiscoveryResults to hold the discovery results (e.g., endpoint address(es) or whatever other information is relevant to the SOAP consumers).
Create a singleton Spring bean MyEndpointDiscoveryService.
On the discovery service, save an AtomicReference<MyEndpointDiscoveryResults> (or even just a plain volatile variable). This will ensure that all threads see updated results, while limiting them to a single, atomically updated field containing an immutable object limits the scope of the concurrency interactions.
Use #Scheduled or another mechanism to run the appropriate discovery protocol. When there's an update, construct the entire result object, then save it into the updated field.
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
In my app I have, for example, 3 logical blocks, created by user in such order:
FirstBlock -> SecondBlock -> ThirdBlock
This is no class-inheritance between them (each of them doesn't extends any other), but logical-inheritance exists (for example Image contains Area contains Message). Sorry, I'm not strong in terms - hope you'll understand me.
Each of blocks sends requests to server (to create infromation about it on server side) and then handles responses independently (but using same implementation of http client). Just like at that image (red lines are responses, black - requests).
http://s2.ipicture.ru/uploads/20120121/z56Sr62E.png
Question
Is it good model? Or it's better to create a some controller-class, that will send requests by it's own, and then handle responses end redirect results to my blocks? Or should implementation of http client be controller itself?
P.S. If I forgot to provide some information - please, tell me. Also if there a errors in my English - please, edit question.
Here's why I would go with a separate controller class to handle the HTTP requests and responses:
Reduce code duplication (do you really need three separate HTTP implementations?)
If/when the communication protocol between your app and server changes, you have to rewrite all your classes. Say for example you add another field to your response payload and your app isn't built to handle it, you now have to rewrite FirstBlock, SecondBlock, and ThirdBlock. Not ideal.
Modify your Implementation of HTTP client controller class such that:
All HTTP requests/responses go through it
It is responsible for routing the responses to the appropriate class.
Advantages?
If/when you change the communication protocol, all the relevant code is in this controller class and you don't have to touch FirstBlock, SecondBlock, or ThirdBlock
Debugging your HTTP requests!
I would suggest that your 3 blocks not deal with HttpClient directly. They should each deal with some interface which handles the remote connection sending of the request and processing of the results. For example:
public interface FirstBlockConnector {
public SomeResultObject askForSomeResult(SomeRequestObject request);
}
Then the details of the HTTP request and response will be in the connector implementations. You may find that you only need one connector that implements all 3 RPC interfaces. Once you separate out the RPC mechanisms then you can find common code in the implementations that actually deal with the HttpClient object. You can also swap out HTTP with another RPC mechanism without changing your block code.
In terms of controllers, I think of them being a web-server side term and not for the client but maybe you meant a connector like the above.
Hope this helps.
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.)