Reputation: 21
Need help in error handling in a chain during splitter and aggregator flow for a synchronous channel. Below is the Use case and it will be synchronous channel. So in the chain there will be a set of service activator to perform the business logic. Now if there is any exception in the service activator present in the chain, I want that to be handled in the chain itself and continue with the other splitted messages.
Inorder to do that, I have tried adding header enricher for error handler in the chain.But did not work. Any suggestion.
Object1 contains List < Object2 >
Flow:
List < Object1 > --> Splitter1 (for Object1) --> Splitter2 (for Object2) --> Chain --> Aggregator --> Aggregator
Code
<int:chain input-channel="ch3" output-channel="ch10" >
<int:header-enricher>
<int:error-channel ref="exception1" ></int:error-channel>
</int:header-enricher>
<int:service-activator ref="myService" method="method1"></int:service-activator>
<int:service-activator ref="myService" method="method2"></int:service-activator>
<int:service-activator ref="myService" method="method3"></int:service-activator>
<int:service-activator ref="myService" method="method4"></int:service-activator>
</int:chain>
<!-- Exception channel for chain and the output should go to the chain output channel -->
<int:chain input-channel="exception1" output-channel="ch10" >
<int:service-activator ref="exp" method="myException"></int:service-activator>
</int:chain>
Upvotes: 2
Views: 3823
Reputation: 121552
Unfortunately it doesn't work that way. The error-channel
header is for the asynchronous cases, too. It allows to override the default behavior in the MessagePublishingErrorHandler
for PollableChannel
and channels with Executor
. In other words when we really can't do try...catch
if talk in raw Java words.
So, to fix your requirements you really should rely on the try...catch
function for that particular <service-activator>
. It is called like ExpressionEvaluatingRequestHandlerAdvice
and must be configured as on the <request-handler-advice-chain>
.
In your case you should configure that Advice
like:
<bean class="ExpressionEvaluatingRequestHandlerAdvice">
<property name="trapException" value="true"/>
<property name="onFailureExpression" value="#exception"/>
<property name="failureChannel" value="myErrorChannel"/>
</bean>
The trapException="true"
allows do not re-throw the exception to the top level. In your case to the <splitter>
.
The onFailureExpression
says what to send to the failureChannel
from the catch
block.
The failureChannel
is your desired error-channel
to handle <service-activator>
failures.
The source code looks like, by the way:
try {
Object result = callback.execute();
if (this.onSuccessExpression != null) {
this.evaluateSuccessExpression(message);
}
return result;
}
catch (Exception e) {
Exception actualException = this.unwrapExceptionIfNecessary(e);
if (this.onFailureExpression != null) {
Object evalResult = this.evaluateFailureExpression(message, actualException);
if (this.returnFailureExpressionResult) {
return evalResult;
}
}
if (!this.trapException) {
throw actualException;
}
return null;
}
Since we prevent re-throw with trapException="true"
, we end up on the return null
. And having <service-activator>
with null-payload
loyalty we allow our <splitter>
to go ahead with other messages.
HTH
Upvotes: 2