Reputation: 45
This is a follow up question to this post
The flow looks like this:
<int:channel id="myapp.input">
<int:queue/>
</int:channel>
<int:channel id="myapp.output">
<int:queue/>
</int:channel>
<int:chain input-channel="myapp.input" output-channel="myapp.output">
<int:poller error-channel="baseFlow.error">
<int:transactional/>
</int:poller>
<int:service-activator ref="jmsService1"/>
<int:service-activator ref="dbService2"/>
<int:service-activator ref="jmsService2"/>
<int:service-activator ref="dbService2"/>
</int:chain>
Now at the end of the chain and before sending of message to the output-channel
'myapp.output' the transaction is comitted and a DataAccessException
is thrown.
The desired behavior is that in my errorChannel
I get a MessagingException
containing the failedMessage
and the DataAccessException
.
The actual behavior is that I get the bare DataAccessException
in my errorChannel
but I do not know which message for and I cannot react on it.
Is there a way to achieve the desired behavior?
Upvotes: 0
Views: 186
Reputation: 174554
Interesting - that's the normal behavior for a gateway.
Normally, gateways are used to invoke an integration flow from java code and the messaging exception is unwrapped so the caller gets the actual exception.
When a gateway is used in this context (called from some other messaging component), however, I can see that the gateway should re-throw the MessagingException
. We will look into doing that automatically.
In the meantime...
The default service-interface
is RequestReplyExchanger
.
If you create your own version of RequestReplyExchanger
and add throws MessagingException
to the exchange()
method, and use it in your gateway, the gateway should re-throw that exception rather than unwrapping it.
I opened a JIRA Issue.
EDIT
You can use nested gateways to solve the issue; remove the transaction and error channel from the poller and, instead, start the transaction at the second gateway; when the commit fails, the messaging exception will be sent to the first channel's error channel...
public interface TxGateway {
@Transactional
Message<?> exchange(Message<?> message);
}
<tx:annotation-driven/>
<int:service-activator ref="errorHandlingGW" input-channel="one">
<int:poller ... />
</int:service-activator>
<int:gateway id="errorHandlingGW" default-request-channel="two" error-channel="two" />
<int:service-activator ref="transactionalGW" input-channel="two" />
<int:gateway id="transactionalGW" service-interface="my.TxGateway" default-request-channel="chain1" />
Upvotes: 1