Currently we have a requirement to handle exceptions in a spring integration flow.
The current solution was to handle exceptions thrown from any POJO (transformer, aggregator, service etc) by means of Aspects. And in the aspects a tweet would be sent that an exception occured. However this aspects do not cover exceptions thrown by for example the Spring Integration Flow. That is if an exception happens in an <object-to-json-transformer> or a 500 status is returned by an <int-http:outbound-gateway>.
We need a method to handle this. Currently we see that we can have the start of the flow (gateway) have an error channel attached and in this error channel send a tweet. However the issue is that we also have business logic in the service called by the error channel. So we would need to mix the tweeting (notification) and business concerns. Also this would mean that each error channel service would manually needed to be programmed to send out a tweet. So if a new error channel service is created by a new developer he/she may forget to put in the tweet code.
Is there any way that we could put a common global error handle which also gets called in addition to the flow specific error service. Then in the common global error handler code all the notification tweeting logic and any other cross cutting concerns is run. What would be the best strategy for this then.
UPDATE 1
I have come up with the following code, however it seems to give a StackOverFlowException, however when I change the payload routing channel to nullChannel the error goes away
<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>
The stack trace is as given
java.lang.StackOverflowError
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$1.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)
Apparently when I do the following it also does not work
<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>
However if I directly call the global-notifier-error-channel as given
<int:wire-tap pattern="*" channel="global-notifier-error-channel" />
then the notification will work
Regards, Milinda