My code deliberately throws a SourceAssertionError. Earlier in 5.1.6.release of spring-integraton for any error , in RequestHandlerRetryAdvice, for any error, it would wrap it in MessagingException. In Below doInvoke() of RequestHandlerRetryAdvice,
@Override
protected Object doInvoke(final ExecutionCallback callback, Object target, final Message<?> message)
throws Exception {
RetryState retryState = null;
retryState = this.retryStateGenerator.determineRetryState(message);
messageHolder.set(message);
try {
return this.retryTemplate.execute(context -> callback.cloneAndExecute(), this.recoveryCallback, retryState);
}
catch (MessagingException e) {
if (e.getFailedMessage() == null) {
throw new MessagingException(message, "Failed to invoke handler", e);
}
throw e;
}
catch (Exception e) {
throw new MessagingException(message, "Failed to invoke handler", unwrapExceptionIfNecessary(e));
}
finally {
messageHolder.remove();
}
}
but now in 5.3.2.Release, its not wrapped in MEssagingException but rather thrown as THrowableHolderException as seen below
@Override
protected Object doInvoke(final ExecutionCallback callback, Object target, final Message<?> message) {
RetryState retryState = this.retryStateGenerator.determineRetryState(message);
MESSAGE_HOLDER.set(message);
try {
return this.retryTemplate.execute(context -> callback.cloneAndExecute(), this.recoveryCallback, retryState);
}
catch (MessagingException e) {
if (e.getFailedMessage() == null) {
throw new MessagingException(message, "Failed to invoke handler", e);
}
throw e;
}
catch (ThrowableHolderException e) { // NOSONAR catch and rethrow
throw e;
}
catch (Exception e) {
throw new ThrowableHolderException(e);
}
finally {
MESSAGE_HOLDER.remove();
}
}
Now after spring-integration upgrade my code flow goes in such a way that error(Not MessagingException) is not being routed to error-channel. The exception thrown by doInvoke() in RequestRetryHandlerAdvice is rejected before its routed to error channel because the logic required them to be of particular type i.e., if only the exception is MessaginException then its routed to error-channel. The flow exits with exception thrown by rethrowExceptionCauseIfPossible(..) in GatewayProxyFactoryBean. Before upgrade my error had been wrapped to MessagingException and flow reaches till handleSendAndReceiveError(..) in MessagingGatewaySupport where it usualy is routed to custom defined error-channel. This is not happening after upgrade to 5.3.2.Release as flow ends before itself
my spring configuration is very straightforward, I just have one custom error channel defined only to gateway.
<int:gateway id="gateway" error-channel="myErrorChannel". and defined a transformer for this error-channel
Now my question is how can I handle this error? is there anyway I could handle it by routing to any newly defined error-channel or can I do it to my already defined myErrorChannel?
EDIT1: Adding config file as Artem Bilan Requested
<bean id="myPreferences" class="package.MyPreferences" />
<bean id="myExceptionTransformer"
class="package.myExceptionTransformer" />
<int:channel id="myErrorChannel" />
<int:transformer input-channel="myErrorChannel"
ref="myExceptionTransformer" />
<bean id="Logger" class="package.Logger" />
<int:gateway id="gateway" error-channel="myErrorChannel"
service-interface="package.myClient"
default-request-channel="myRoutingChannel">
<int:method name="invokeAuthenticationRequest">
<int:header
name="#{T(name1)}"
value="#{T(value1)}" />
</int:method>
<int:method name="invokeProvRequest">
<int:header
name="#{T(name2)}"
value="#{T(value2)}" />
</int:method>
</int:gateway>
<int:publish-subscribe-channel id="myRoutingChannel" />
<int:header-value-router input-channel="myRoutingChannel"
header-name="#{T(package.AppContext).REQUEST_TYPE}">
<int:mapping
value="#{T(value1)}"
channel="authGatewayChannel" />
<int:mapping
value="#{T(value2)}"
channel="provGatewayChannel" />
</int:header-value-router>
<int-ws:request-handler-advice-chain>
<ref bean="provRetryAdvice" />
</int-ws:request-handler-advice-chain>
</int-ws:outbound-gateway>
<bean id="provRetryAdvice"
class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice">
<property name="retryTemplate">
<bean class="org.springframework.retry.support.RetryTemplate">
<property name="backOffPolicy">
<bean class="org.springframework.retry.backoff.FixedBackOffPolicy">
<property name="backOffPeriod" value="4000" />
</bean>
</property>
<property name="retryPolicy">
<bean class="org.springframework.retry.policy.SimpleRetryPolicy">
<property name="maxAttempts" value="#{provisioningRetryCount.intValue()}" />
</bean>
</property>
</bean>
</property>
</bean>
And my Transformer is defined as
@Transformer
public Message<?> transformErrorToResponse(Message<?> exceptionMessage) {
Object exceptionMessagePayload = exceptionMessage.getPayload();
Throwable cause = ((MessagingException) exceptionMessagePayload).getCause();
newPayload = new myException(msg);
/*add headers*/
return errorMessage;
}