spring integration:响应消息未从错误通道发送到客户端

时间:2013-06-03 10:05:25

标签: response spring-integration channel

我理解Spring Integration(SI)会将任何异常(在SI域下)包装到MessageException实例并将其放在“错误通道”上。

以下是我的spring配置文件中的几个片段:

<int:channel-interceptor pattern="ersServiceReqRcvPostValidationChannel,ersServiceResRcvPostValidationChannel" order="1">
    <bean class="com.bnym.ecs.report.service.orchestration.interceptors.MsgJSONSyntaxValidationInterceptor"/>
</int:channel-interceptor>

<int:channel-interceptor pattern="ersServiceReqRcvPostValidationChannel,ersServiceResRcvPostValidationChannel" order="2">
    <bean class="com.bnym.ecs.report.service.orchestration.interceptors.MsgMetaDataValidationInterceptor"/>
</int:channel-interceptor>

<!--  Gateways -->
<int:gateway id="ersServiceReqRcvGateway"
    service-interface="com.bnym.ecs.report.service.orchestration.gateway.ERSOrchestrationSvcReqGateway"
    error-channel="reqRcvExceptionHandlerChannel">
    <int:method name="processRequest" request-channel="ersServiceReqRcvPostValidationChannel" />
</int:gateway>

<!--  Chain to handle all incoming request *after* doing all validations -->
<int:chain input-channel="ersServiceReqRcvPostValidationChannel">
    <int:service-activator ref="msgReqAuditDetailDAOIntegrator" method="persist" />
    <!--  Router -->
    <int:router ref="ersServiceReqRcvRouter" />
</int:chain>

<!--  6) Pass the message through ERS svc to Exec svc ADH chain - Chain2 -->
<int:chain input-channel="ersSvc2execSvcQMRChannel" output-channel="ersServiceResRcvPostValidationChannel">
    <int:transformer ref="json2ObjTransformer" method="transformToERSOrchestrationSvcReq" />
    <int:service-activator ref="executionSvcReqMsgBuilder" method="getRptExecutionSvcReqForDataEngine" />
    <int:transformer ref="obj2JsonTransformer" method="transformFromRptExecutionSvcReqForDataEngine" />
    <int:service-activator ref="msgReqAuditDAOIntegrator" method="persist" />
    <int:service-activator ref="msgReqAuditDetailDAOIntegrator" method="persist" />
    <int:service-activator ref="executionSvcRESTStub" method="executeReportJSON" />
</int:chain>

<int:chain input-channel="reqRcvExceptionHandlerChannel">
    <int:transformer ref="exceptionTransformer" method="handleError"/>
</int:chain>

客户端对我的实现类进行REST调用,该调用将接收到的请求放在上面的spring配置文件中定义的Gateway上

@Path("/reportExecutor")
public class ERSOrchestrationServiceImpl {

    @Autowired
    private ReportInstanceDAO reportInstanceDAO;

    private static final ERSOrchestrationSvcDiagnosticLogger _logger = 
    ERSOrchestrationSvcDiagnosticLogger.getInstance(ERSOrchestrationServiceImpl.class);

    @Context
    HttpServletRequest request;
    @Context
    HttpServletResponse response;

    @POST
    @Path("/executeOnlineReport")
    @Produces({MediaType.APPLICATION_JSON})
    public String executeOnlineReport(String jsonRequest) {

        ApplicationContext appCtx = SpringApplicationContextUtil.getApplicationContext();

        ERSOrchestrationSvcReqGateway ersOrchestrationSvcReqGateway = 
            (ERSOrchestrationSvcReqGateway) appCtx.getBean("ersServiceReqRcvGateway");

        Message<String> inputMsg = MessageBuilder.withPayload(jsonRequest)
                                                 .setHeader(ERSServiceConstants.KEY_MSG_CORRELATION_ID, correlationId)
                                                 .setHeader(ERSServiceConstants.KEY_MSG_REPORT_INSTANCE_ID, reportInstanceId)
                                                 .build();

        Message<String> returnMsg = ersOrchestrationSvcReqGateway.processRequest(inputMsg);
        return returnMsg.getPayload();

    }

如上面的spring配置文件中所述,错误通道由Transformer读取,它为客户端创建有效的失败响应消息并返回消息。

public class ErrorMessageUnwrapTransformer {

    @Autowired
    private Gson gsonUtil;
    @Autowired
    private ReportInstanceDAO reportInstanceDAO;
    @Autowired
    private ERSOrchestrationSvcFailedResMsgBuilder executionSvcFailedMsgBuilder;

    private static final ERSOrchestrationSvcDiagnosticLogger _log = 
    ERSOrchestrationSvcDiagnosticLogger.getInstance(ErrorMessageUnwrapTransformer.class); 

    @Transformer
    public Message<?> handleError(Message<?> message) {
        try{
            failedMsg = ((MessagingException) message.getPayload()).getFailedMessage();

            //some code logic to build a valid failed response message goes here
            Message<?> failedResponseMsg = executionSvcFailedMsgBuilder.getERSOrcSvcFailedResMsg(failedMsg );

            return failedResponseMsg;
        }

当我得到异常时,所有似乎工作正常,即异常被包装为MessagingException,放在错误通道上,Transformer能够读取通道,从中获取failedMessage,能够创建有效失败的响应消息并将其返回。

然而,我得到的唯一问题是呼叫不会回到呼叫者。换句话说,句柄不会返回到已启动处理流程的以下代码:

Message<String> returnMsg = ersOrchestrationSvcReqGateway.processRequest(inputMsg);   

有人请不要让我知道为什么error-channel-read-Transformer返回的消息没有返回到调用Gateway方法的类?

1 个答案:

答案 0 :(得分:0)

此处的问题是,您从Message<?>返回整个transformer。当返回的对象已经Message<?>时,这个组件不关心标题。您应该自己担心它们,例如将所有标题从failedMsg复制到您自己的failedResponseMsg

为什么这么重要?

由于您使用request/reply网关,您希望在该方法调用上返回,后台的某些内容确保为您服务。它是一种经典的replyChannel算法。

如果您没有配置AbstractReplyProducingMessageHandler,那么任何replyChannel都会将结果发送到outputChannel,例如此处reqRcvExceptionHandlerChannel <chain>

对于其他组件,我们可以依赖copy-header-from-request函数,但不能使用<transformer>

可以在我们没有标题的某些上下文中创建另一侧ErrorMessage,但我们failedMessage中的MessagingException可能ErrorMessage headers已经造成了。因此,我们必须从failedMessage确保<Mold>

希望我很清楚。