Andy Baer
Andy Baer

Reputation: 45

DataAccessException not wrapped in MessagingException

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

Answers (1)

Gary Russell
Gary Russell

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

Related Questions