ExactTargetUser
ExactTargetUser

Reputation: 21

Spring integration chain error handling

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

Answers (1)

Artem Bilan
Artem Bilan

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

Related Questions