Apache Camel JMS-исключения не возвращаются вызывающему абоненту с запросом / ответом

Я создал простую настройку запроса / ответа с Apache Camel и JMS. Все работает нормально-вызовы отправляются в службу на стороне сервера, а результаты возвращаются клиенту. Только тогда, когда есть исключение на стороне сервера, это исключение не будет возвращено. Исключение появляется на сервере и клиент получает тайм-аут. Я хотел бы получить исключение на стороне клиента.

насколько я понял доступные документы, что я хочу должно быть поведение по умолчанию. Я также играл с предложением onException или настраивал другой маршрут для обратной передачи, но все это не помогло. Итак, мой вопрос: что мне не хватает в моей настройке, чтобы получить исключения, возвращенные вызывающему абоненту?

вот подробности (упрощенный код):

  • очередь JMS для связи развертывается в автономном JBoss (7.1.1.Финал)
  • JNDI используется для поиска фабрики для создания соединений с очередь
  • в настоящее время клиент является весенним веб-приложением, работающим на причале
  • сервер в настоящее время является простым автономным приложением Java, настроенным с Spring
  • Весна версия 3.1.2.Отпустите
  • Apache Camel 2.10.2

DTOs / Exception обмениваются между клиентом и сервером:

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.");
    }
}

интерфейс для службы, вызываемой через JMS:

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

реализации Обслуживание:

@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
    }
}

конфигурация клиента:

<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"/>

конфигурация сервера:

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

наблюдаемое поведение, когда на стороне сервера есть исключение:

в логах сервера появляется следующий вывод:

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

и клиент получает время ожидания:

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

Итак, еще раз: все остальное работает так, как ожидалось, только исключения не возвращаются вызывающему. Любая помощь в этом очень ценится! Спасибо заранее.

1 ответов


см. параметр transferException, который необходимо включить для сериализации исключения и возврата в качестве ответа. Вариант описан на ОМС док страницы: http://camel.apache.org/jms