How to Aspect a whole camel route - java

Essentially, I'd like to aspect a whole camel route, so that I can grab the payload at the start and the end.
Now, I know I can just aspect the main "doing" class in the middle, not pulling it from a queue and placing it on the disk at the end. And this is fine for a simple route, not one that has many "doing" classes.
But is there a way to tie up the start and end of a route, without putting this into the route?
I have got a lot of routes and I'd like to keep them as clean of logging code as possible.

Use the interception possibilities of Camel as described here:
intercept that intercepts each and every processing step while routing an Exchange in the route.
interceptFrom that intercepts incoming Exchange in the route.
interceptSendToEndpoint that intercepts when an Exchange is about to be sent to the given Endpoint.
In your case the second and third possibility may be of interest.

I think you've got two choices:
Add a wiretap at the start and end of each route. See http://camel.apache.org/wire-tap.html. This obviously means editing the routes but is simple easy and it only two lines per route.
Use RouteDefinition.adviceWith to dynamically add an interceptor. See http://camel.apache.org/advicewith.html. I've not seen this used outside testing but I don't see any reason why you can't use it in live code.

Related

Best way handle partitioned data with AMQP?

I have several similar systems which are authoritative for different parts of my data, but there's no way I can tell just from my "keys" which system owns which entities.
I'm working to build this system on top of AMQP (RabbitMQ), and it seems like the best way to handle this would be:
Create a Fanout exchange, called thingInfo, and have all of my other systems bind their own anonymous queues to that exchange.
Send a message out to the exchange: {"thingId": "123abc"}, and set a reply_to queue.
Wait for a single one of the remote hosts to reply to my message, or for some timeout to occur.
Is this the best way to go about solving this sort of problem? Or is there a better way to structure what I'm looking for? This feels mostly like the RPC example from the RabbitMQ docs, except I feel like using a broadcast exchange complicates things.
I think I'm basically trying to emulate the model described for MCollective's Message Flow, but, while I think MCollective generally expects more than one response, in this case, I would expect/require precisely one or, preferably, a clear "nope, don't have it, go fish" response from "everyone" (if it's really possible to even know that in this sort of architecture?).
Perhaps another model that mostly fits is "Scatter-Gather"? It seems there's support for this in Spring Integration.
It's a reasonable architecture (have the uninterested consumers simply ignore the message).
If there's some way to extract the pertinent data that the consumers use to decide interest into headers, then you can gain some efficiency by using a topic exchange instead of a fanout.
In either case, it gets tricky if more than one consumer might reply.
As you say, you can use a timeout if zero consumers reply, but if you think that might be frequent, you may be better off using arbitrary two-way messaging and doing the reply correlation in your code rather than using request/reply and tying up a thread waiting for a reply that will never come, and timing out.
This could also deal with the multi-reply case.

Re-Route Requests without sending Redirect to client

I have a pretty simple purpose
URIs of form ->/random/* go to /*. For example /random/users goes to /users.
I don't wish to use redirect() to solve the problem.
I have a tried a few ways but not sure about implementation -
Intercept the request before it reaches the router. And change the URI somehow. I am trying to Override the onRequest method, but unable to proceed as I don't know the implementation. (possible issue with: should routing really be here?)
Have an entry in routes which is like /random/*, make it point to a controller method. From inside the controller call the router method again with the modified URI. Again here unable to proceed as stuck with implementation.
Double the routes file or put a regex in routes file. For each entry, copy it and append /random to it. I dont want to do this, since it makes the file difficult to manage. Last resort really.
Please help regarding how to implementation Point 1 or Point 2.
If there is any other much simpler way please help..
Add a new Random-controller and create an action which forwards the calls to the proper controllers.
Use the following route:
GET /random/:controller controllers.Random.handleRandom(controller:String)
Let the handleRandom-action forward the calls accordingly (with or without redirect). You can either do some reflection-magic to forward the call to other controllers, or use a if-then-else- or switch-clause.

Camel: Implementing Polling and Non-Polling Consumer within the same component

I am implementing my own custom component and I have found that I am going to need two use cases for consumers:
The first one would be trying to get N number of available messages every so often (Polling Consumer)
The second one would be a subscriber consumer that gets messages when they are available.
My main question is if it possible to implement these two types. I have been trying to write some code, but it seems that if you are developing a PollingConsumer you cannot implement another type. Also, if it is possible, is there any example, article or guide about how to do this? I have been looking for it for nothing came up.
Thanks!
There is two consumer kind in Camel (eg from the EIP book)
Consumer
PollingConsumer
Its the former that is used in the Camel routes. And the latter is used when you use it explicit or when using ConsumerTemplate, to use the receive methods.
A Camel component is able to adapt a Consumer to a PollingConsumer out of the box.
So it depends if you want to build a Camel component that are used in routes, you can just create a consumer. And have it able to do both poll and subscribe. When you have the data, then create an Exchange and call the processor to route it.
For documentation then check the Camel website, and/or chapter 11 in the Camel in Action book which covers creating custom components.

Apache Camel - Issue a HTTP-Request from within a Processor

a similar, but more general question has been asked here:
Business logic in Camel processors vs service endpoints.
Now consider the following flow (E1 and E2 represent processors, they are not endpoints as in camel flows), which I trigger with parameters (p,q):
Route: E1 -> E2
E1 itself issues an HTTP-request with parameters (p,q), receives the response-data d (sync) and forwards this to E2, which continues processing based on (p,q,d). So it essentially enriches the input with additional data.
The endpoint, which is called contains the data that is to be integrated, i.e. this will not change and needs not to be configurable in the future.
I tried two solutions, both of which seem kind of wrong to me:
use http4:url endpoints and piggyback the (p,q) in the header of the messages (or alternatively properties of the exchange).
use a processor that explicitly/programmatically issues the http-request, processes the response and forwards the expected (p,q,d). For convenience, I did this with a producerTemplate being sent to http4:url inside the camel-context.
Problem with the first is that it adds a lot of boilerplate procducers etc and make the actual route really obscure. The second approach allows to offload processing into a new class (and not mix it into the routes) but still requires the camel-context and depends on this.
What is the recommendation for this. I couldn't find anything around except more abstract statements like "do not mix business logic with wiring" etc.
* added real use-case *
E1 gets two dates (a time-span) and a department name, fetches all names that have been in the specified department over the specified time-span. Then (above I ignored this detail) the names are splitted and for every single name, all data is fetched that has been saved in the specified date-span. For this last step the dates from the input of the first is needed (so these need to be passed through the entire route).
thanks,
markus
Thanks to Claus:
You can enrich the message anyhow you like. Camel doesn't really care. If you use a processor / pojo its just java code and you can do whatever you want. If you use the enrich / pollEnrich DSL then they uses an AggregationStrategy to "merge" the enrichment.
I enriched the original input of the route by the result of the http4:url endpoint. This way I could separate the "fetching" of data from the acual business logic, which now happens in the Processor/AggregationStreategy bean that is independent of the rest (of camel in particular).
thanks
markus

Re-route dynamically for Camel Routes

I am trying to figure out how to re-route dynamically for a camel route. I currently calculate the route in a processor based on some inputs. The route is then put into the message header. I thought I'd be able to re-route dynamically using
.routingSlip(header("myHeader").toString())
or something like it, but I have not had any luck so far.
Any help is appreciated...
You should not use the .toString(), it should simply be
.routingSlip(header("myHeader"))
As documented in the Camel documentation
http://camel.apache.org/routing-slip
Then "myHeader" should just contain 1..n endpoints where the message should be routed. If you have multiple endpoints then separate them with comma.
We, during our processor, set a property:
exchange.setProperty("sendTo", blah);
then, instead of routingSlip, use recipientList like:
.recipientList(property("sendTo"));
...which works great. I don't think a full example is necessary for this?

Categories