弹簧集成:响应消息未从错误通道发送到客户端
Posted
技术标签:
【中文标题】弹簧集成:响应消息未从错误通道发送到客户端【英文标题】:spring integration : response message not sent to client from error-channel 【发布时间】:2013-05-29 11:01:37 【问题描述】:我了解到 Spring Integration (SI) 会将任何异常(在 SI 域下)包装到 MessageException 实例并将其放置在“错误通道”上。
以下是我的 spring 配置文件中的几个 sn-ps:
<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 配置文件中定义的网关上
@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返回的消息没有返回到调用网关方法的类?
【问题讨论】:
我也遇到了同样的问题你解决了吗? 【参考方案1】:您的问题是从transformer
返回整个Message<?>
。这是一个不关心标题的组件,当返回的对象已经是Message<?>
。您应该自己担心它们,例如将所有标题从failedMsg
复制到您自己的failedResponseMsg
。
为什么这么重要?
由于您使用request/reply
网关,因此您期望该方法调用的返回,因此后台的某些内容可以确保为您服务。而且是经典的replyChannel
算法。
任何AbstractReplyProducingMessageHandler
将其结果发送到replyChannel
,如果您没有配置outputChannel
,例如您的reqRcvExceptionHandlerChannel
<chain>
这里。
对于其他组件,我们可以依赖 copy-header-from-request
函数,但这里不能使用 <transformer>
。
另一方面,ErrorMessage
可能是在我们没有标头的某些上下文中创建的,但我们恰好可能在 MessagingException
中拥有 failedMessage
,而导致 ErrorMessage
的原因。所以,我们必须确保headers
来自failedMessage
。
希望我清楚。
【讨论】:
一句话,你要设置header让处理器识别和处理消息。以上是关于弹簧集成:响应消息未从错误通道发送到客户端的主要内容,如果未能解决你的问题,请参考以下文章
Android 客户端未从 node.js 服务器接收到 socket.io 消息
将消息发送到套接字端口并使用Spring Integration接收响应