JmsTests.java非常有助于理解构造代码的方法。代码位于https://github.com/spring-projects/spring-integration-java-dsl/blob/master/src/test/java/org/springframework/integration/dsl/test/jms/JmsTests.java
但是,对于错误处理,我有点像我们一样搞清楚。是否有任何测试或参考代码显示构造错误通道或使用子流委派错误处理的好方法?
在问题中添加更多内容:
jmsMessageDrivenFlow()工作正常并打印消息。我希望只有在jmsMessageDrivenFlow期间出现错误时才会调用错误处理程序。但是,错误处理程序()也会被调用,并且它会使“调度程序”无法传递消息'致命队列中的消息。
我希望在这种情况下甚至不应该调用错误通道,因为jmsMessageDrivenFlow()没有创建任何错误。显然,如果我在jmsMessageDrivenFlow()中省略了.errorChannel(errorChannel()),则不会调用错误流,只会按预期执行jmsMessageDrivenFlow()。
@EnableIntegration
@IntegrationComponentScan
@Component
@Configuration
public class MessageReceiver {
private static final Logger logger = LoggerFactory.getLogger(MessageReceiver.class);
String fatalErrorQueue = "fatal";
String incomingQueue = "incoming";
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Bean
public Queue incomingQueue() {
return new ActiveMQQueue(incomingQueue);
}
@Bean
public MessageChannel errorChannel() {
return new DirectChannel();
}
@Bean
public IntegrationFlow handleErrors() {
return IntegrationFlows
.from("errorChannel")
.handle((payload,headers) -> {
System.out.println("processing error: "+payload.toString());
return payload;
})
.handle(Jms.outboundAdapter(jmsMessagingTemplate.getConnectionFactory()).destination(fatalErrorQueue))
.get();
}
@Bean
public IntegrationFlow jmsMessageDrivenFlow() {
return IntegrationFlows
.from(
Jms.messageDriverChannelAdapter(jmsMessagingTemplate.getConnectionFactory())
.destination(incomingQueue)
.errorChannel(errorChannel())
)
.handle((payload,headers) ->{
System.out.println("processing payload: "+payload.toString());
return payload;
})
.get();
}
}
执行记录:
2016-01-22 10:18:20,531 DEBUG DefaultMessageListenerContainer-1 ServiceActivatingHandler.handleMessage - ServiceActivator for [org.springframework.integration.dsl.LambdaMessageProcessor@522d5d91] (org.springframework.integration.handler.ServiceActivatingHandler#1) received message: GenericMessage [payload=SAMPLE QUEUE MESSAGE, headers={jms_redelivered=false, jms_correlationId=, jms_type=, id=78d5456e-4442-0c2b-c545-870d2c177802, priority=0, jms_timestamp=1453479493323, jms_messageId=ID:crsvcdevlnx01.chec.local-47440-1453310266960-6:2:1:1:1, timestamp=1453479500531}]
processing payload: SAMPLE QUEUE MESSAGE
2016-01-22 10:18:20,535 DEBUG DefaultMessageListenerContainer-1 DirectChannel.send - preSend on channel 'errorChannel', message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=dc87f71d-a38c-4718-a2e9-2fba2a7c847c, timestamp=1453479500535}]
2016-01-22 10:18:20,535 DEBUG DefaultMessageListenerContainer-1 ServiceActivatingHandler.handleMessage - ServiceActivator for [org.springframework.integration.dsl.LambdaMessageProcessor@5545b00b] (org.springframework.integration.handler.ServiceActivatingHandler#0) received message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=dc87f71d-a38c-4718-a2e9-2fba2a7c847c, timestamp=1453479500535}]
processing error: org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available
2016-01-22 10:18:20,535 DEBUG DefaultMessageListenerContainer-1 DirectChannel.send - preSend on channel 'handleErrors.channel#0', message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=f434348c-f659-1e88-2eba-3d467761ab47, timestamp=1453479500535}]
2016-01-22 10:18:20,535 DEBUG DefaultMessageListenerContainer-1 JmsSendingMessageHandler.handleMessage - org.springframework.integration.jms.JmsSendingMessageHandler#0 received message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=f434348c-f659-1e88-2eba-3d467761ab47, timestamp=1453479500535}]
2016-01-22 10:18:20,537 DEBUG DefaultMessageListenerContainer-1 DynamicJmsTemplate.execute - Executing callback on JMS Session: ActiveMQSession {id=ID:MACD13-60edd8d-49463-1453479492653-1:1:1,started=true} java.lang.Object@858db12
2016-01-22 10:18:20,568 DEBUG DefaultMessageListenerContainer-1 DynamicJmsTemplate.doSend - Sending created message: ActiveMQObjectMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@559da78d, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = {timestamp=1453479500535}, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false}
2016-01-22 10:18:20,570 DEBUG DefaultMessageListenerContainer-1 DirectChannel.send - postSend (sent=true) on channel 'handleErrors.channel#0', message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=f434348c-f659-1e88-2eba-3d467761ab47, timestamp=1453479500535}]
2016-01-22 10:18:20,571 DEBUG DefaultMessageListenerContainer-1 DirectChannel.send - postSend (sent=true) on channel 'errorChannel', message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=dc87f71d-a38c-4718-a2e9-2fba2a7c847c, timestamp=1453479500535}]
答案 0 :(得分:1)
行。谢谢。调查......但是从高处看,一切都按预期运作:
jmsMessageDrivenFlow()
是单向流您在该流程结尾处有非结束.handle()
:
.handle((payload,headers) ->{
System.out.println("processing payload: "+payload.toString());
return payload;
})
由于您返回任何内容,因此流程会在标头中output-channel
或replyChannel
。 ErrorMessage
说明了这一点。
我告诉我关于完全修复错误的方法。对于您的情况,您只需将.handle((payload,headers) ->
更改为.handle(message ->
即可
这是单向停止流动的单向方式。
由于您在回复.handle()
之后确实存在下一个端点的问题,messagingGateway
会对此做出正确反应:
this.messagingTemplate.convertAndSend(requestChannel, object, this.historyWritingPostProcessor);
}
catch (Exception e) {
MessageChannel errorChannel = getErrorChannel();
if (errorChannel != null) {
this.messagingTemplate.send(errorChannel, new ErrorMessage(e));
}
这就是为什么你的handleErrors()
能够处理这个错误。
errorChannel()
上没有Jms.messageDriverChannelAdapter()
我们最终在AbstractMessageListenerContainer
:
protected void executeListener(Session session, Message message) {
try {
doExecuteListener(session, message);
}
catch (Throwable ex) {
handleListenerException(ex);
}
}
其默认ErrorHandler
为... null
,我们只看到:
logger.warn("Execution of JMS message listener failed, and no ErrorHandler has been set.", ex);
不是吗?
<强>更新强>
请问你解释为什么messagingGateway将有效负载发送到errorChannel()只是因为我已经为非happy-path scnenarios定义了一个错误通道。
???即使使用XML定义,您最终也会遇到相同的错误。 Java DSL在后台使用相同的组件。我不会解释常规Java代码:您在try...catch
周围看到convertAndSend
,并且您在运行时的条件定义了错误。这就是你得到DestinationResolutionException
的原因。我们无法在初始阶段识别非幸福路径,因为return
中的.handle()
只能在运行时才能幸运null
。所以,从配置的角度来看一切都还可以。即使没有outputChannel
,从另一边开始,当我们在此问题上有request/reply
标题时,您仍可以使用replyChannel
情节感到满意。