首页 > 解决方案 > 如何使用 Spring 集成流处理异常

问题描述

我正在尝试使用弹簧集成执行以下操作。

我想从输入通道中读取传入的消息,该消息会引发一系列步骤并产生最终消息。每个步骤都可以引发异常。这可能是由于 DB 调用或 ExternalCall 等造成的。每个步骤都被视为服务激活器。如果一切顺利,则生成最终消息。我需要将每个步骤抛出的每个异常作为单独的案例处理,然后生成适当的最终消息。

使用下面的 xml 我编写了一个测试代码,该代码在成功但发生错误时通过,尽管我在通道 'bean'finalChannel' 日志上的 postSend (sent=true) 中看到了最终消息,但该过程没有返回最后的队列。

为什么会这样?

<?xml version="1.0" encoding="UTF-8"?>
<context:component-scan base-package="com.demo.">
</context:component-scan>

<header-enricher input-channel="inputChannel"
    output-channel="enrichedChannel">
    <header name="initialMessage" expression="getPayload()" />
</header-enricher>
<!-- first-step -->
<service-activator input-channel="enrichedChannel"
    output-channel="firstStep" ref="validateOne" />
<gateway id="validateOne" default-request-channel="ch1"
    error-channel="errors1" />

<chain input-channel="ch1">
    <service-activator id="mockServiceOneActivator"
        ref="mockServiceOne" method="register" />
</chain>
<!-- enrich-header with payload to be available down the line -->
<header-enricher input-channel="firstStep"
    output-channel="secondStep">
    <header name="initialInfo" expression="getPayload()" />
</header-enricher>
<!-- second-step -->
<service-activator input-channel="secondStep"
    output-channel="enrichWithTwoChannel" ref="validateTwo" />
<gateway id="validateTwo" default-request-channel="ch2"
    error-channel="errors2" />
<chain input-channel="ch2">
    <service-activator id="mockServiceTwoActivator"
        ref="mockServiceTwo" method="callExternal" />
</chain>
<!-- enrich-header with payload to be available down the line -->
<header-enricher input-channel="enrichWithTwoChannel"
    output-channel="eligibilityCheck">
    <header name="serviceTwoInfo" expression="getPayload()" />
</header-enricher>
<!-- final-step -->
<service-activator input-channel="eligibilityCheck"
    output-channel="finalChannel" id="mockServiceFinalActivator"
    ref="mockServiceFinal" method="submit" />
<!-- error handling -->
<service-activator input-channel="errors1"
    output-channel="finalChannel" ref="traceErrorHandler"
    method="handleFailedTrace" />
<service-activator input-channel="errors2"
    output-channel="finalChannel" ref="traceErrorHandler2"
    method="handleFailedTrace" />

<channel id="finalChannel">
    <queue />
</channel>
<service-activator input-channel="errorChannel"
    ref="globalExceptionHandler" method="handleError" />

我的处理程序代码如下所示..

@Component("traceErrorHandler")public class TraceErrorHandler {
public Message<FinalMessage> handleFailedTrace(Message<?> errorMessage) {
    MessagingException payload = (MessagingException) errorMessage.getPayload();
    InitialMessage im = (InitialMessage) payload.getFailedMessage().getHeaders().get("initialMessage");
    ServiceOneException error = (ServiceOneException) payload.getCause();
    FinalMessage v = new FinalMessage(im.getFrom(), im.getTo(), error.getErrorTemplate());
    Message<FinalMessage> finalMessage = MessageBuilder.withPayload(v).copyHeaders(payload.getFailedMessage().getHeaders()).build();
    return finalMessage;
}}

我不确定这是否是关于错误处理的正确方法。最初的链是简单的激活器,但更进一步会有更多的逻辑。我们是否应该总是使用链来处理单独的错误通道

  1. 即使它调用了单个激活器服务。
  2. 仅当存在多个封装单点错误的服务激活器/转换时?

编辑 1 我添加了一个 request-handler-advice-chain 引用一个 bean。

<int:service-activator
    id="serviceOneActivator" input-channel="enrichedChannel"
    ref="serviceOne" method="register" output-channel="firstStep">
    <int:request-handler-advice-chain>
        <ref bean="myclass" />
    </int:request-handler-advice-chain></int:service-activator>

引用 bean 最初是 xml 中的默认定义

<bean id="myclass"
    class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
    <property name="failureChannel" ref="finalChannel" />
    <property name="onFailureExpression" value="#payload"/>
    <property name="returnFailureExpressionResult" value="true" />
</bean>

如果我添加<property name="onFailureExpression" value="#payload"/>它失败的属性:

Cannot convert value of type 'java.lang.String' to required type 'org.springframework.expression.Expression' for property 'onFailureExpression' 我想做的是将异常消息转换为最终消息对象?但我添加的所有表达式似乎在加载时都失败了。

标签: javaerror-handlingspring-integration

解决方案


具有一个组件的链没有意义。

链只是语法糖,每个组件在运行时仍然独立。

如果要处理单个端点的错误,请考虑使用ExpressionEvaluatingRequestHandlerAdvices 代替。

请参阅https://docs.spring.io/spring-integration/docs/5.3.2.RELEASE/reference/html/messaging-endpoints.html#message-handler-advice-chain


推荐阅读