Apache Camel JMS - Exceptions are not returned to the request / response subscriber

I created a simple request / response installation with Apache Camel and JMS. Everything works fine - calls are sent to the server service, and the results are returned to the client. Only if there is an exception on the server side will this exception not be returned to the caller. An exception appears on the server and the client receives a timeout. I would like to get an exception on the client side.

As far as I understand the available documents, what I want should be the default. I also played with the onException clause or set up another route for postback, but all of this did not help. So my question is what am I missing in my setup to get the exceptions returned to the caller?

Here are the details (the code is simplified):

  • The JMS queue for communication is deployed in a stand-alone JBoss (7.1.1.FINAL)
  • JNDI is used to search Factory to create queue connections
  • The client is currently a Spring web application running on Jetty
  • The server is currently a simple standalone Java application configured with Spring
  • Spring version 3.1.2.RELEASE
  • Apache Camel 2.10.2

DTOs / Exception are exchanged between the client and server:

public class RequestDTO implements Serializable { String payload; ... } public class ResponseDTO implements Serializable { String payload; ... } public class RmtServiceException extends Exception implements Serializable { public RmtServiceException() { super("Exception in service."); } } 

Interface for the service called through JMS:

 public interface RmtService { ResponseDTO doSomething(RequestDTO request) throws RmtServiceException; } 

Implementation for the service:

 @Component("rmtService") public class RmtServiceImpl implements RmtService { public ResponseDTO doSomething(RequestDTO request) throws RmtServiceException { // Return a ResponseDTO if processing is successful, // otherwise throw an RmtServiceException } } 

Client Configuration:

 <bean id="remoteJndiTemplate" class="org.springframework.jndi.JndiTemplate"> <property name="environment"> <props> <prop key="java.naming.factory.initial">org.jboss.naming.remote.client.InitialContextFactory</prop> <prop key="java.naming.provider.url">remote://localhost:4447</prop> <prop key="java.naming.security.principal">JNDI_USER</prop> <prop key="java.naming.security.credentials">JNDI_PASSWORD</prop> </props> </property> </bean> <bean id="remoteJmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiTemplate" ref="remoteJndiTemplate"/> <property name="jndiName" value="jms/RemoteConnectionFactory"/> </bean> <bean id="authenticatedJmsConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter"> <property name="targetConnectionFactory" ref="remoteJmsConnectionFactory"/> <property name="username" value="JMS_USER"/> <property name="password" value="JMS_PASSWORD"/> </bean> <bean name="hq" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory" ref="authenticatedJmsConnectionFactory"/> </bean> <camel:camelContext id="APIContext" autoStartup="true"> <camel:endpoint id="queue" uri="hq:queue:test.queue"/> </camel:camelContext> <camel:proxy id="rmtServiceProxy" serviceInterface="RmtService" serviceUrl="hq:queue:test.queue"/> 

Server Configuration:

 <bean id="remoteJndiTemplate" class="org.springframework.jndi.JndiTemplate"> <property name="environment"> <props> <prop key="java.naming.factory.initial">org.jboss.naming.remote.client.InitialContextFactory</prop> <prop key="java.naming.provider.url">remote://localhost:4447</prop> <prop key="java.naming.security.principal">JNDI_USER</prop> <prop key="java.naming.security.credentials">JNDI_PASSWORD</prop> </props> </property> </bean> <bean id="remoteJmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiTemplate" ref="remoteJndiTemplate"/> <property name="jndiName" value="jms/RemoteConnectionFactory"/> </bean> <bean id="authenticatedJmsConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter"> <property name="targetConnectionFactory" ref="remoteJmsConnectionFactory"/> <property name="username" value="JMS_USER"/> <property name="password" value="JMS_PASSWORD"/> </bean> <bean name="hq" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory" ref="authenticatedJmsConnectionFactory"/> </bean> <camel:camelContext id="APIContext" autoStartup="true"> <camel:endpoint id="queue" uri="hq:queue:test.queue"/> <camel:route> <camel:from ref="queue"/> <camel:to uri="bean:rmtService"/> </camel:route> </camel:camelContext> 

Observed behavior when there is an exception on the server side:

The following output appears in the server logs:

 ERROR: org.apache.camel.processor.DefaultErrorHandler - Failed delivery for (MessageId: ID-XXX-49296-1352104153517-0-8 on ExchangeId: ID-XXX-49296-1352104153517-0-7). Exhausted after delivery attempt: 1 caught: org.apache.camel.RuntimeCamelException: RmtServiceException: Exception in service. org.apache.camel.RuntimeCamelException: RmtServiceException: Exception in service. at org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:1270) at org.apache.camel.component.bean.BeanInvocation.invoke(BeanInvocation.java:87) at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:130) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:99) at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:73) at org.apache.camel.impl.ProcessorEndpoint.onExchange(ProcessorEndpoint.java:101) at org.apache.camel.impl.ProcessorEndpoint$1.process(ProcessorEndpoint.java:71) at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) at org.apache.camel.processor.SendProcessor$2.doInAsyncProducer(SendProcessor.java:122) at org.apache.camel.impl.ProducerCache.doInAsyncProducer(ProducerCache.java:298) at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:117) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:73) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) at org.apache.camel.processor.interceptor.TraceInterceptor.process(TraceInterceptor.java:91) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) at org.apache.camel.processor.RedeliveryErrorHandler.processErrorHandler(RedeliveryErrorHandler.java:334) at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:220) at org.apache.camel.processor.RouteContextProcessor.processNext(RouteContextProcessor.java:45) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) at org.apache.camel.processor.interceptor.DefaultChannel.process(DefaultChannel.java:303) at org.apache.camel.processor.RouteContextProcessor.processNext(RouteContextProcessor.java:45) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) at org.apache.camel.processor.UnitOfWorkProcessor.processAsync(UnitOfWorkProcessor.java:150) at org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:117) at org.apache.camel.processor.RouteInflightRepositoryProcessor.processNext(RouteInflightRepositoryProcessor.java:48) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:73) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:99) at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:86) at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:104) at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:562) at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:500) at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:468) at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:326) at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:264) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1071) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1063) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:680) Caused by: RmtServiceException: Exception in service. at RmtServiceImpl.doSomething(...) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.camel.component.bean.BeanInvocation.invoke(BeanInvocation.java:83) ... 48 more WARN : org.apache.camel.component.jms.EndpointMessageListener - Execution of JMS message listener failed. Caused by: [org.apache.camel.RuntimeCamelException - RmtServiceException: Exception in service.] ... (Same stacktrace again) 

And the client gets a timeout:

 WARN : org.apache.camel.component.jms.reply.TemporaryQueueReplyManager - Timeout occurred after 20000 millis waiting for reply message with correlationID [ID-XXX-49307-1352104250851-0-13]. Setting ExchangeTimedOutException on (MessageId: ID-XXX-49307-1352104250851-0-15 on ExchangeId: ID-XXX-49307-1352104250851-0-14) and continue routing. 2012-11-05 10:03:11.964:WARN:oejs.ServletHandler:/app/some/action java.lang.reflect.UndeclaredThrowableException at $Proxy45.doSomething(Unknown Source) at ... Caused by: org.apache.camel.ExchangeTimedOutException: The OUT message was not received within: 20000 millis due reply message with correlationID: ID-XXX-49307-1352104250851-0-13 not received. Exchange[Message: BeanInvocation public abstract ResponseDTO RmtService.doSomething(RequestDTO) throws RmtServiceException with [ RequestDTO@... ]]] at org.apache.camel.component.jms.reply.ReplyManagerSupport.processReply(ReplyManagerSupport.java:133) at org.apache.camel.component.jms.reply.TemporaryQueueReplyHandler.onTimeout(TemporaryQueueReplyHandler.java:61) at org.apache.camel.component.jms.reply.CorrelationTimeoutMap.onEviction(CorrelationTimeoutMap.java:53) at org.apache.camel.component.jms.reply.CorrelationTimeoutMap.onEviction(CorrelationTimeoutMap.java:30) at org.apache.camel.support.DefaultTimeoutMap.purge(DefaultTimeoutMap.java:203) at org.apache.camel.support.DefaultTimeoutMap.run(DefaultTimeoutMap.java:159) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439) at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:680) 

So again: everything else works as expected, only exceptions are not returned to the caller. Any help on this is greatly appreciated! Thanks in advance.

+6
source share
1 answer

See the transferException parameter that you must enable to serialize the exception and return as a response. The option is documented on the JMS document page at: http://camel.apache.org/jms

+7
source

All Articles