Activemq timeToLive from camel route not being applied until queue is visited - apache-camel

We are configuring timeToLive for messages in a a queue using a camel route from a topic as follows:
<route errorHandlerRef="BrokerErrorHandlerEvents">
<description>MQTT Events</description>
<from uri="ourbroker:topic:events.>"/>
<setHeader headerName="myUser">
<simple>${headers.JMSXUserID}</simple>
</setHeader>
<setHeader headerName="myTopic">
<simple>ssc.${headers.JMSDestination}</simple>
</setHeader>
<setHeader headerName="msgReceived">
<simple>${headers.JMSTimestamp}</simple>
</setHeader>
<to uri="ourbroker:queue:ourqueue.ourbroker_events?
timeToLive=600000"/>
</route>
Then we are sending a few test message from the ActiveMQ web interface. After the timeToLive (10 minutes), we expect the messages to go to the DLQ. The message stays in its queue after that time. Funny enough, if we visit the queue contents from the web interface all the messages seem to be "processed" and sent to the DLQ at this point of time (as if the checking was triggered by our visit).
Why is this just happening when we visit the queue from the web interface? Are we missing some configuration parameter to schedule the check of the expiration messages? (note: we have schedulerSupport="true" in the broker)

Related

How can I implement a route about multicast?

I have the scenario below.
Request Web Services from client system. This request is that the file will be copied.
Receive request by cxf component in application.
Response the return code that means success after receiving request immediately.
After send response, the application will fetch the file.
So, I implemented route.
<route>
<from uri="cxf:bean:FileTransferServiceEndPoint"/>
<multicast parellelProcessing="true">
<toD uri="direct:bean"/>
<toD uri="direct:fetchFile"/>
</multicast>
</route>
<route>
<from uri="direct:bean"/>
<bean method="process" ref="returnMsg"/>
<end>
</route>
<route>
<from uri="direct:fetchFile"/>
<pollEnrich>
<simple>file:/test/inBox</simple>
</pollEnrich>
<toD uri="file:/test/outBox"/>
</route>
I faced to have some problem.
Originally, I think that response will be return by returnMsg Bean.
But Response Message was not respond until the file is completely processed.
I want the message delivered immediately to the client. And at the same time, I want the files to be processed.
How should I implement a route to fulfill my scenario?
Please let me know this solution.
Thank you.
Consider using SEDA component (take a look at the option waitForTaskToComplete) or WireTap EIP (it makes a "lite" copy of the message but you can customize its behavior) to fetch the file.
PS 1.: Caution with the usage of pollEnrich without setting a timeout.
PS 2.: Depending upon the way you receive the body message, you may face a stream closed issue by using it more than once, as you end up doing in multicast.
If you want your "direct" routes to be executed independently of each other, consider to use wireTap
<route>
<from uri="cxf:bean:FileTransferServiceEndPoint"/>
<wireTap uri="direct:bean"/>
<to uri="direct:fetchFile"/>
</route>
from the "Camel in Action" book:
By using the wireTap method in the Java DSL, you can send a copy of the exchange
to a secondary destination without affecting the behavior of the rest of the route

How to get the message back to the queue if the http request failed?

I use apache camel with activemq and camel-http, after the message is sent to the endpoint and the request fails, I still lose the message from the queue.
It is necessary that the message is not lost if the request failed. How can I do this?
<route>
<from uri="activemq://db_record_rows"/>
<to uri="http://localhost:3000" />
</route>
You can mark your consumer as transacted, so it will be handled by the transaction manager of your context.
from("activemq://db_record_rows?transacted=true")
.to("http://localhost:3000")

Camel-netty4: how to wait response before send next request

I have created route that accept request from multiple producers and send to a remote server by using netty4 with request-response. However, when camel is sending a request to remote server and waiting for response, next incoming request is received and want to send to remote server but got IOException as camel cannot receive response.
So, how to set Camel-Netty4 send request and wait for response before send next.
The route configuration:
from("direct:DirectProcessOut?block=true")
.to("netty4:tcp://192.168.1.2:8000?sync=true&synchronous=true&reuseChannel=true")
I actually ran into a similar issue trying to send out several messages at a time based on rows in a database table. The calls wouldn't wait for each other to complete and essentially stepped on each other and either hung or blew up.
The solution I eventually found was to use a message queue. Take in your requests and route them into a single activemq route.
So something like:
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<route>
<from uri="direct:direct:DirectProcessOut"/>
<to uri="activemq://processOutQueue"/>
</route>
</camelContext>
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<route>
<from uri="activemq://processOutQueue"/>
<to uri="netty4:tcp://192.168.1.2:8000?sync=true&synchronous=true&reuseChannel=true"/>
</route>
</camelContext>
My case was a little different, so I'm not sure if this will preserve your message you want to send. But hopefully it gives you a place to start.

Clarification about Camel direct component

I can see that many Camel route examples are initiated with a "direct" component. For example:
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route id="myroute">
<from uri="direct:start"/>
<setBody>
<simple>Hello World!</simple>
</setBody>
<log message="${body}"/>
<to uri="mock:result"/>
</route>
</camelContext>
However, by running a route like this (mvn camel:run) the route is not started and Camel keeps hanging forever. Is it not meant to be used directly this kind the direct component?
Thanks
Its not hanging. You need to send a message to the direct endpoint before its routed. eg like in java code to do a direct method invocation from a client by calling a java method.
Instead of direct you can use a timer if you want to route a message automatic every X time etc.
To send a message to the direct endpoint (or any other Camel endpoint) then read about the producer template. For example from the getting started guide: http://camel.apache.org/walk-through-an-example.html

Apache Camel VM queue between servlets

I'm trying to setup simple VM queue test between two servlets without success. The problem is that the request always timeouts as there is no response, OUT message, within expected timeframe.
"org.apache.camel.ExchangeTimedOutException: The OUT message was not received within: 30000 millis."
The servlets are running in Tomcat and are both deploying Apache Camel. Both apps are defining camel context and simple routes. The basic setup should be fine as simple routes like following are working:
<route>
<from uri="servlet:///hello?servletName=app1" />
<transform>
<simple>Hello world</simple>
</transform>
</route>
<route>
<from uri="servlet:///hello?servletName=app2" />
<transform>
<simple>Hello world</simple>
</transform>
</route>
First of all I'm not sure if the message ever reaches the app2 as the same timout happens even if the requested route wouldn't be even defined (the app2 would be missing the VM route). So the problem could be in how to define the route between two servlets using VM queue.
If the route between the servlets is fine then the problem should be in the missing/incorrect reply. I do understand that the receiving end should return the reply as the incoming requst from web server is inOut type, but I don't know how to achieve that.
The route in app1 receiving the web request:
<route>
<from uri="servlet:///test?servletName=app1" />
<to uri="vm:test">
</route>
and the other end in servlet app2:
<route>
<from uri="vm:test" />
// Tested here: output with <simple>, 'To', 'inOut'... the result is always timeout
</route>
As I'm new with Apache Camel the root cause is most likely very simple. Any help would be highly appreciated.
The question is simply, how to setup VM queue between two servlet apps?
The vm component works in the same classloader, eg kinda what we say on the vm documentation page: http://camel.apache.org/vm.html
This component differs from the SEDA component in that VM supports
communication across CamelContext instances - so you can use this
mechanism to communicate across web applications (provided that
camel-core.jar is on the system/boot classpath).
So if you use Apache Tomcat, you need to have camel-core JAR as shared JAR. Such as in the boot classpath somewhere.

Resources