How to handle an exception in an exception block in apache camel - apache-camel

I am trying to handle an exception within apache camel in onException. Can someone guide me if it is possible?
I have written another onException which will handle all Exceptions, but the flow is not transferred to that exception block
onException(SchemaValidationException.class)
.to("xslt:stylesheet/example/TransformErrorBlock.xsl?saxon=true")
.log("Validation error in received message, response sent: ${body}")
.handled(true);
My expectation is if there is an exception in this block, it should be caught in another onException block

You cannot do this as its by design that Camel only allows onException block to handle exceptions, otherwise you can end up with endless looping when onException A is handled by onException which causes a new exception that may then be handled by onException A again, and so endless looping in circles.

Related

Camel: Routing from queue to HTTP

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).

Persisting JMS Message Headers during Message Redelivery

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!

CAMEL - Channel Closed exception not caught using onException

I am opening this question as I didn't find any answer to problem in the web.
I have used camel to implement a TCP/IP server and I have defined a route like this:
from("netty4:tcp://0.0.0.0:3510")
.to("file:target/outbox");
and I have a client which sends data to this server. When I disconnect this client I can see in my logs this exception:
[Camel (camel-client) thread #0 - NettyEventExecutorGroup] WARN o.a.c.component.netty4.NettyConsumer - Closing channel as an exception was thrown from Netty. Caused by: [java.io.IOException - an existing connection was forcibly closed by the remote host]
My problem is that I am not able to catch this exception using onException clause.
onException(IOException.class)
.log("Exception: ${body}")
.handled(true)
.process(new ExceptionProcessor());
The program does not stop but I want to catch it to handle when the client is disconnected.
Note that I can catch other exceptions which are thrown inside my route.
You cannot handle it as exception, because exception is already catched in netty and logged. This exception is not propagated from netty to netty component.
The solution is a bit tricky. You can extend SimpleChannelInboundHandler and override method channelInactive as described in How can I detect network disconnection in Apache Camel?.
In this custom handler you can set custom properties on exchange with additional information, which is relevant in your application.

move messages between ActiveMQ queues in Camel w/o deserializing

I'm running Camel embedded in ActiveQM 5.11.1. I have some Java serialized messages that I need to move between queues with a simple Camel route...
<route>
<from uri="activemq:A"/>
<to uri="activemq:B"/>
</route>
as expected, I get this error...
WARN | Execution of JMS message listener failed. Caused by:
[org.apache.camel.RuntimeCamelException - Failed to extract body due
to: javax.jms.JMSException: Failed to build body from content.
Serializable class not available to broker. Reason:
java.lang.ClassNotFoundException: com.test.MyMessage. Message:
ActiveMQObjectMessage
I know this is because Camel/AMQ doesn't know about MyMessage and I can add it to AMQ's classpath to get around this...but that isn't an option in my case.
Instead, can I just tell Camel/AMQ to not try to deserialize it and just move it? I tried the jmsMessageType options, but they didn't get around this error...
You can turn of mapping from JMS to Camel Message using the mapJmsMessage=false option.
And then set jmsMessageType=Object so when sending to the queue, Camel will not try to guess the message type, but use object as configured, then the message is sent as-is.

Closing session as an exception was thrown from MINA

I keep getting this message
[Mina2Consumer] Closing session as an exception was thrown from MINA
but no other information or exception is logged - the mina2 code suggests it is throwing a Camel Exception but is not getting logged anywhere.
I am using Camel 2.11.0 and Mina2 2.0.7
any help will be great.
There was this improvement recently in camel-mina2 to ensure the root cause is included in the exception if a write failure happened: https://issues.apache.org/jira/browse/CAMEL-6970
Maybe applying that patch to your Camel to see if that helps you. Or wait for that fix to be released and upgrade Camel etc.

Resources