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.
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 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.
I have:
Camel route (transacted=true), consuming from an MQ Queue
Using Spring's WebSphereUowTransactionManager
Transactionality works
Running on IBM Liberty
But, I get this message:
Setup of JMS message listener invoker failed for destination 'MY.QUEUE' - trying to recover.
Cause: Local JMS transaction failed to commit; nested exception is com.ibm.msg.client.jms.DetailedIllegalStateException:
MQJCA1020: The session is closed.
The application attempted to use a JMS session after it had closed the session.
Modify the application so that it closes the JMS session only after it has finished using the session.
This appears to be related to this other Stack Overflow question, but I've tried changing the configuration in server.xml, with no success.
You can try setting cacheLevelName=CACHE_CONSUMER which allows to re-use the JMS consumer and avoids endless of creation/destruction of JMS resources, as indicated by the error message may be the cause.
You can see more about the importanse of cache levels on the Camel JMS documentation: http://camel.apache.org/jms
I'm having some troubles trying to catch an error on OSB when I put a message on queue and JMS Server is down, I have a proxy service calling a business service that have a jms configured.
My proxy service already have Transaction Required and Same Transaction For Response enabled.
The error on Admin log:
Destination unreachable; nested exception is:
java.net.ConnectException: Connection refused: connect; No available
router to destination
But the exception don't catch on ErrorHandler :(
I found the error, the problem is that I was using Publish instead of Routing, after I changed everything worked.
Yes that correct , Publish thread is like fire and forget(completely asynchronous) while a Route or ServiceCallout will latch on to the exception in ErrorHandler
Publish is fire-and-forget, by default with no wait for an answer. This comes from the fact, that default QualityOfService=BestEffort for publish action. You can change that, by using RoutingOptions block, and setting QualityOfService=ExactlyOnce. OSB will then wait for action to execute, hence will be also able to catch potential errors.
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.