common spring 集成异常处理程序

common spring integration exception handler

目前我们需要在 spring 集成流程中处理异常。

当前的解决方案是通过方面来处理从任何 POJO(转换器、聚合器、服务等)抛出的异常。在方面,将发送一条推文,说明发生了异常。但是,这方面不包括 Spring 集成流抛出的异常。也就是说,如果 <object-to-json-transformer> 中发生异常或 <int-http:outbound-gateway>.

返回 500 状态

我们需要一种方法来处理这个问题。目前我们看到我们可以让流程的开始(网关)附加一个错误通道,并在这个错误通道中发送一条推文。然而,问题是我们在错误通道调用的服务中也有业务逻辑。因此,我们需要混合推文(通知)和业务问题。这也意味着每个错误通道服务都需要手动编程以发送一条推文。因此,如果新开发人员创建了新的错误通道服务 he/she 可能会忘记输入推文代码。

有没有什么方法可以放置一个通用的全局错误句柄,除了流特定的错误服务之外,它也会被调用。然后在通用的全局错误处理程序代码中运行所有通知推文逻辑和任何其他横切关注点。那么最好的策略是什么。

更新 1

我想出了以下代码,但它似乎给出了 WhosebugException,但是当我将有效负载路由通道更改为 nullChannel 时,错误消失了

<int:publish-subscribe-channel id="global-wire-tap-channel" />

<int:service-activator input-channel="log-channel" ref="loggerEndpointService" method="logMessageHistory" />

<int:payload-type-router input-channel="global-wire-tap-channel" default-output-channel="nullChannel">
    <int:mapping type="java.lang.Exception" channel="global-notifier-error-channel" />
</int:payload-type-router>

堆栈跟踪是给定的

java.lang.WhosebugError
at java.lang.Class.privateGetDeclaredMethods(Class.java:2414)
at java.lang.Class.getMethod0(Class.java:2670)
at java.lang.Class.getMethod(Class.java:1603)
at org.apache.commons.logging.LogFactory.directGetContextClassLoader(LogFactory.java:825)
at org.apache.commons.logging.LogFactory.run(LogFactory.java:791)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.commons.logging.LogFactory.getContextClassLoader(LogFactory.java:788)
at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:383)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:645)
at org.springframework.messaging.support.MessageHeaderAccessor.<init>(MessageHeaderAccessor.java:51)
at org.springframework.integration.IntegrationMessageHeaderAccessor.<init>(IntegrationMessageHeaderAccessor.java:49)
at org.springframework.integration.support.MessageBuilder.<init>(MessageBuilder.java:59)
at org.springframework.integration.support.MessageBuilder.fromMessage(MessageBuilder.java:75)
at org.springframework.integration.support.DefaultMessageBuilderFactory.fromMessage(DefaultMessageBuilderFactory.java:29)
at org.springframework.integration.support.DefaultMessageBuilderFactory.fromMessage(DefaultMessageBuilderFactory.java:25)
at org.springframework.integration.history.MessageHistory.write(MessageHistory.java:76)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:76)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:160)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:142)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.interceptor.WireTap.preSend(WireTap.java:128)
at org.springframework.integration.channel.AbstractMessageChannel$ChannelInterceptorList.preSend(AbstractMessageChannel.java:338)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:251)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:93)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:175)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:160)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:142)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.interceptor.WireTap.preSend(WireTap.java:128)
at org.springframework.integration.channel.AbstractMessageChannel$ChannelInterceptorList.preSend(AbstractMessageChannel.java:338)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:251)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:93)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:175)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:160)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:142)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.interceptor.WireTap.preSend(WireTap.java:128)
at org.springframework.integration.channel.AbstractMessageChannel$ChannelInterceptorList.preSend(AbstractMessageChannel.java:338)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:251)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:93)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:175)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:160)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:142)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.interceptor.WireTap.preSend(WireTap.java:128)
at org.springframework.integration.channel.AbstractMessageChannel$ChannelInterceptorList.preSend(AbstractMessageChannel.java:338)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:251)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:93)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:175)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:160)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:142)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.interceptor.WireTap.preSend(WireTap.java:128)
at org.springframework.integration.channel.AbstractMessageChannel$ChannelInterceptorList.preSend(AbstractMessageChannel.java:338)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:251)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:93)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:175)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:160)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:142)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.interceptor.WireTap.preSend(WireTap.java:128)
at org.springframework.integration.channel.AbstractMessageChannel$ChannelInterceptorList.preSend(AbstractMessageChannel.java:338)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:251)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:93)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:175)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:160)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:142)

显然当我执行以下操作时它也不起作用

<int:wire-tap pattern="*" channel="global-wire-tap-channel" />

<int:channel id="global-wire-tap-channel" />

<int:payload-type-router input-channel="global-wire-tap-channel" default-output-channel="nullChannel">
    <int:mapping type="java.lang.Exception" channel="global-notifier-error-channel" />
</int:payload-type-router>

但是,如果我直接调用 global-notifier-error-channel 给定的

<int:wire-tap pattern="*" channel="global-notifier-error-channel" />

然后通知将起作用

此致, 米琳达

我会说你按照正确的方式划分逻辑来实现 loosely-coupled 原理。这是正确的,不同的模块(或集成流)可以有自己的错误处理逻辑,你使用 error-channel 来捕获那些下游异常是很好的。

我看到一个很好的全球推文错误处理解决方案。我们不能在这里使用内置的error-channel,因为任何自定义的都有优先权。但是我们可以为它们添加一个方面,它是全局 <wire-tap>pattern 用于所有这些目标错误通道。在这种情况下,您所有的开发人员都应该遵循所有错误通道的命名约定,以允许该全局通道拦截器为他们处理消息。

不过请注意,WireTap 处理 preSend 中的消息。因此全局错误处理将在任何自定义逻辑之前进行。在这种情况下,您可能需要编写简单的 WireTap 扩展来在 postSend

中执行此操作