Display all active routes in Apache Camel - apache-camel

I am using Apache camel to trigger various actions based on timer events. For timer events to trigger, I am using camel-quartz. And a sample trigger looks like this:
from("quartz://job_timers/customer_activation?cron=0+0+0+*+*+?+*&trigger.timeZone=America/Chicago")
.routeId("TrigCustActivation")
.log(LoggingLevel.INFO, "Triggered Customer Activation Job")
.to("direct://set/headers/activation")
.to("direct://customer/activation");
Over the period of time, the number of such triggers have increased a lot. And they will be increasing even more. So, instead of keeping a hard-copy of when which job will trigger, I was planning to create a web-route, so that when I perform a GET request, it would fetch all the active routes, and print their RouteIds (I will update all the RouteIds to have time as well. Say, the routeId for above flow will become "TrigCustActivation_00_00_CST_Daily").
I was able to print all the route at application startup, but failed to fetch those dynamically through a GET request.
Can we access other RouteIds from a running route? Is my approach feasible?

Yes there is API on CamelContext where you can fetch all the current routes, and you can then get their IDs etc. See the javadoc of this class.
http://static.javadoc.io/org.apache.camel/camel-core/2.21.0/org/apache/camel/CamelContext.html

Related

How to transfer messages, each at a specific time?

I have about 10K messages in a CSV file. Each message has an associated timestamp for it. When the time is reached, I want the message delivered to an MQ. The timestamps are not uniformly spread. Is this possible with Apache Camel?
As far as I know Apache Camel by default has no consumer endpoint components that you could configure to trigger with specific messages at specified times.
There is however a timer component that you can setup to trigger for example once a second. Then in the route you could use a processor to check if a list contains any messages that should be send at the given time and send them to the MQ.
You could also trigger route from java code using a ProducerTemplate that you can create using the CamelContext.
The list could be populated using your csv file and ordered by timestamp so you could use it like a stack and only check the first few entries instead of going through all 10K every second.
The real problem here would be persistence i.e to figure out which of the messages listed on the csv have already been sent if the application closes before all 10K messages have been sent.

Avoid duplicate inflight messages in Apache Camel

We are building a system where an external system sends us "Refresh" events. These events tell us to refresh the state of an item identified by the id provided in the RefreshEvent.
We handle these events through a Camel route.
The refresh may go wrong, though. If this is case the event is moved to a "Retry" SEDA queue with appropiate retry/backup setup. However, we may experience multiple "Refresh" event for the same item, while we are unable to fetch the new state.
Ideally we'd like to only have unique itemIds in the Retry queue. The inflight itemIds should be unique.
Is there a way to do this in Camel.
I have looked at the IdempotentConsumer, but that has a scope of all received exchanges, I'm only interested in the current inflight exchanges.
If you are not able to use the IndempotentConsumer pattern, you will have to implement the logic yourself and possible change the Seda endpoint to something more sophisticated.
You could use a message queue supporting JMS selectors or property filtering.
ActiveMQ, to name one, has some capabilities that could be used in implementing the solution you need.

ActiveMQ / Camel : spawn multiple routes, wait for all to be completed

I'm new to activeMQ / Camel, so please bear with me.
In a camel route, I use a splitter to spawn multiple sub routes. Each one of this routes will use some external APIs to do some job, and poll until job is done. I'm that far.
Now I need to trigger a last action to collect the result of all of these routes. How would I do that the Camel / AMQ way ?
I was thinking of posting a message in each sub-route to an AMQ queue, but I haven't found a way yet to wait for the N messages to be received in that queue before consuming it in my final Camel route.
Thank you.
If you need to collect all the results from the splitter sub-routes and execute some action on those results after all the sub-routes are completed then you can use an aggregation strategy(https://camel.apache.org/manual/latest/aggregate-eip.html) on the splitter.
By using an aggregation strategy, the Exchange after the split will contain the results of all the sub-routes.
Example using the Java DSL:
.split(expression, new GroupedExchangeAggregationStrategy())
...
.end()
The GroupedExchangeAggregationStrategy aggregates all split Exchanges into a list. You can use another predefined aggregation strategy if you need, or you can create a custom one by extending org.apache.camel.processor.aggregate.AggregationStrategy.

Removing camel route is not removing tibco queue receivers count

We have a stand alone application where we should be able to stand up JMS listeners using database configuration dynamically. If there is any change in the concurrentConsumers count in the database, then we need to update the listeners accordingly. We are using camel 2.16.2 and Tibco 6.3.0. Precisely, the below are our requirements.
Ability to add and remove JMS listeners dynamically.
To achieve this, we are creating our OwnRouteBuilder (which extends camel RouteBuilder) and adding it using camelContext.addRoutes(RouteBuilder) dynamically which is working as expected.
Ability to increase or decrease JMS listeners dynamically.
To achieve this, initially we tried to stop the route, update concurrentConsumers count, and then start route. It is working fine only when we increase the concurrentConsumers count. But its not working if we decrease( its not changing the concurrentConsumers count).We can still see the same receivers count from tibco console.
As an alternate solution , we tried with camelContext.stopRoute(routeId) and then camelContext.removeRoute(routeId) so that we can add a fresh route with updated concurrentConsumers count later. In this case also, though it is stopping the routes from consuming messages, it is not changing the receivers count from tibco console.
I tried with camelContext.removeEndpoints(endpointUri), camelContext.shutdownRoute(routeId), camelContext.removeRouteDefinition(routedefinition) methods.
But all these methods only stopping the routes from consuming messages, but not clearing those receivers count from tibco console.
The receivers count from tibco console is becoming zero only when we terminate the application.
Is there any way that we can make it from camel so that those receivers count from tibco console becomes zero.
You can change the concurrentConsumer counts dynamically at runtime using JMX to set the values on the JMX attribute on the endpoint. Then the route dont have to be stopped/removed/started etc.

Monitoring if camel routes work as aspected

I'm looking for a best practise how to monitor the functionality of camel routes.
I know there are monitoring tools like hawtio and camelwatch, but that's not exactly what I'm looking for.
I want to know if a route is "working" as aspected, for example you have a route which listens on a queue(from("jms...")). Maybe there are messages in the queue, but the listener is not able to dequeue them because of some db issues or something else(depends on the jms provider). With the monitoring tools mentioned above you just see inflight/failed/completed messages but you don't see if the listener is able to get the messages -> so the route is not "working".
I know there is also apache BAM, maybe I have to do some more research, but somehow it looks like BAM creates new routes and you can't monitor existing routes. I also don't want to implement/define such business cases for each route, I look for a more generic way. It's also mentioned on the camel 3.0 idea board that BAM wasn't touched for 5 years, so I think people don't use it that often(which means for me it doesn't fit their needs exactly).
I had similar requirement some time ago and at the end I developed a small Camel application for monitoring.
It run on timer, query different Camel applications installed in remote servers through JMX/Jolokia and if LastExchangeCompletedTimestamp of the route I am interested in is older than some time interval, send a mail to administrators.
Maybe this approach is too simple for your scenario, but could be an option.
(Edit: more details added)
Principal points:
Main routes queries DB for entities to control and spawns controlling routes
Controlling routes fires on quartz and http post the following url
.to("http://server:port/app/jolokia/?"+
"maxDepth=7&maxCollectionSize=500&ignoreErrors=true&canonicalNaming=false")
sending the following jsonRequest body
LinkedHashMap<String,Object> request=new LinkedHashMap<String,Object>();
request.put("type","read");
request.put("mbean","org.apache.camel:"+entity.getRouteId());
jsonRequest=mapper.writeValueAsString(request);
As response you get another JSON, parse it and get LastExchangeCompletedTimestamp value

Resources