Today, I tried to simulate a scenario where in the camel "to" tag I supplied a mis-spelt queue name(which was not there) Camel or RabbitMq instead of throwing an exception back continued to finish the route flow.
Intrgigued I did write a sample program to send a message using "channel.basicPublish" with a wrong queue name. I never got any exception thrown back from rabbit mq client.
however if the exchange name was wrong, I did get an exception back. Is this expected behaviour?
I tried adding return listener, confirm listener,exception handler, etc., but none of them got invoked.
Any clues?
Messages are published to exchanges, so the exchange must be there when publishing messages. At publish time RabbitMQ doesn't care about queues, unless the mandatory flag is provided, or the channel is in confirm mode.
Related
Bit of a Camel newbie but here goes.
I have the following route:
from("activemq:queue:outputQueue").inputType(HelloWorld.class)
.to("log:stream")
.marshal().json(JsonLibrary.Jackson, HelloWorld.class)
.to("http:localhost:5000/messageForYouSir?bridgeEndpoint=true");
This retrieves messages from the queue and sends them to the HTTP endpoint as JSON. Fine.
But what if there is an error? Say a HTTP error code of 400? Then I want the message to stay on the queue. I have tried looking into not acknowledging the message, but have not been able to make it work.
Also I have made an Exception handler
onException(HttpOperationFailedException.class)
.handled(false)
.setBody().constant("Vi fekk ein feil");
But still the messages are gone from the queue. Is there some magic spell that can make Camel not acknowledge the messages when there is some error?
You have to consume transacted from the queue to be able to do a rollback. This is configured on the connection configuration to the broker.
Take a look at the Camel JMS docs (the ActiveMQ component extends the JMS component), especially the sections about cache levels and transacted consumption.
The most simple setup is using broker transactions by simply set transacted = true and lazyCreateTransactionManager = false on the JmsConfiguration. This way no Spring TX manager is required.
If transacted consumption is in place and the HTTP server returns an error (basically if an Exception occurs in the Camel Route), Camel does automatically a rollback (if you don't catch the error).
I am trying to setup a camel context that polls a weblogic jms queue, consumes the message and sends it to a webservice endpoint. Incase any error occurs in the transaction or the target system is unavailable, I need to redeliver the same message without losing sequence/ordering.
I have set up a camel jms route with single consumer and enabled transacted attribute as per https://camel.apache.org/transactional-client.html and set the redelivery as unlimited.
When the transaction fails with messageA, the jms message consumption from weblogic queue is rollbacked and the messageA is marked for redelivery (state string is marked delayed) in weblogic. But during this time if another message reaches the weblogic queue, the camel route picks the messageB and forwards it to the target endpoint although the messageA is still in retrying mode. This distorts the whole ordering of the messages.
The transaction client is used to ensure that messages are not lost while the application is shutdown during redelivery.
I expect that there are no message loss and the messages are always sent in the correct order as per generated into the weblogic queue to the target endpoint.
That a newly arrived message outpaces an existing message that has to be redelivered, sounds like a broker (Weblogic) issue or feature.
I never saw this behavior with ActiveMQ. A failed message that is redelivered, is redelivered immediately by the Apache broker.
It sounds like the message is "put aside" internally to redeliver it later. This can absolutely make sense to avoid blocking message processing.
Is there something like a "redelivery delay" set on Weblogic you can configure? I could imagine that a delayed redelivery is like an internal error queue with a scheduled consumer.
We have a camel route where we read a message from an input queue, process it, set some JMS Header( using Exchange.getIn().setHeader(...) ) and then route the message to some output queue. During MQ Failover scenario, the message is redelivered. However, while the message is redelivered the JMS Headers which I put earlier are lost.
Is there any way to preserve the JMS Headers even after redelivery ?
JMS redelivery
No, not if the message is redelivered from the input queue. Simply because it is the same original message you received before. The JMS broker does not know anything about the modifications you did in the Camel route.
However, this is normally not a problem. Because on a redelivery, the same consumer consumes the message again and does the same modifications again on the message.
As soon as you reach a "transaction boundary" in your route (that means, something has done that cannot be repeated or would yield a different result), you should put the modified message on another queue to "save" its current state.
From there you can continue with another consumer and so forth. If you build a processing chain like this, your system is a Pipes and Filter EIP.
Camel redelivery
Another possibility is to use the Camel ErrorHandler. It handles errors on a single route-step level. It can also do retries, but then you have to make sure the message is correctly handled if all Camel retries fail (for example send the message to an error queue).
As long as the broker redelivery is the last resort for your message, you should build your system with potential redelivery in mind.
I have this problem, too. i'm forced to convert my objects to json and save in headers of jms. and after i convert again to object. it's worked for me!
I referred below article and created dependencies and log4j properties
http://camel.apache.org/how-do-i-use-log4j.html
Here is my simple route
from("direct:start")
.routeId("LogEipInfoLevelRoute")
.log(LoggingLevel.INFO, "Displaying Something - ${body}")
.to("mock:result");
Once i deploy my route in servicemix, im checking service mix log. I couldnt find any such message logged. except the route creation message with specified id.
Am i checking it in the wrong place?
You need to send a message to the direct:start endpoint for anyting to happen.
If you just want to see something going on, then you can use a timer instead of direct, eg
from("timer:foo?period=5000")
to figure a new message every 5 seconds. Notice the message body is null from a timer.
I assume that you are using OSGI Based ServiceMix version
Please execute following command in karaf console:
karaf#root> log:display | grep Displaying
More about ServiceMix logging systems can be found under http://servicemix.apache.org/docs/4.4.x/users-guide/logging-system.html
You must pass something to direct:start for something to happen. You can read more here about using direct : http://camel.apache.org/direct.html
I would just suggest using a timer to kick off your route. Once your route is kicked off by the timer your log will be written out to your log file.
I’m stuck at one particular requirement in camel , I’m processing a set of files and when any exception occurs i send a message to an exception queue , and from the exception queue im sending an email about the failure , the functionality is working fine but I end up sending many mails, like if 10 files fail im sending 10 emails, is there a way to send only one mail , like I would want to wait for the entire route to finish , then go look the exception queue and send a single mail stating what has failed (by processing the exception queue )
I'm open for suggestions.
I had to do this scenario once (inversed though - mail on success). I had a handy MySQL database configured and ready, so I just added each event from the queue to the database. Then once every now and then, extracted all info (and deleted it)- simply select * from events; delete from events; from the database and created a mail.
You could process the error queue with the aggregator pattern, it is very nice for these tasks. http://camel.apache.org/aggregate-example.html . You still need to know WHEN the aggregator should fire off a message. If you can, trigger a "finish, send mail" event such as in the example in the link above.
The most simple way would be to time schedule these mail notifications. Take a look at: http://camel.apache.org/simplescheduledroutepolicy.html . You can set it to run your route for some good choice of time, then when it fires off, you set the aggreator to complete upon timeout, and make the timeout good enough to empty any reasonable queue size of errors, but not too large.
At least that's my suggestions to your issue