需要从Spring Integration中的Transformer发送Messaging Exception

时间:2014-01-27 06:57:10

标签: spring-integration

我必须自定义项目的错误处理。如果出现错误,根据错误类型,我想将其发送到不同的队列。

但是,在根据类型将它发送到队列之前,我们在异常消息中进行了一些转换以及将对象转换为String(我为其使用transformer)以便队列可以具有将对象值作为消息文本,以便我们可以轻松跟踪。

现在的问题是,在将对象转换为String或发生任何其他错误(特定于代码)期间,服务开始抛出异常而没有注册错误通道。

此错误处理代码针对多个组件进行了推广,因此即使在转换中也会出现任何故障。我想将异常传递给Error Transformer,将其传递给Error Queue

错误的XML配置是:

<int:transformer  id = "errorTransformer" input-channel="errorsDest"
    ref="exceptionTransformer" output-channel="errors" />
<bean id="exceptionTransformer"
    class="com.commons.spring.integration.error.ErrorTransformer">
</bean>
 <int-jms:outbound-channel-adapter id ="errorQueueAdapter"  
           explicit-qos-enabled="${jms.qos.enabled}"
       auto-startup="${jms.connect}" channel="errors" pub-sub-domain="false"
connection-factory="connectionFactory" destination-name="${error}" />

 @Transformer
public Message<String> handleError(MessagingException message) {
    headers.put("stacktrace", ExceptionUtils.getStackTrace(message));
    headers.put("serviceCausedTheException", EnvironmentResolver.getService());
    Message<?> failedMessage = message.getFailedMessage();
    Object msgPayload = failedMessage.getPayload();
    String payload = "";
    try {
        if (msgPayload instanceof String)
            payload = (String) failedMessage.getPayload();
        else if (msgPayload instanceof MyObject)
            payload = XMLMarshallingUtil.objectToXml((MyObject) msgPayload);
       } catch (Exception e) {
          payload = msgPayload.toString();
          headers.put("Object Conversion Exception Occurred in Error Transformer",  
                    e.getMessage());
       }
     Message<String> parsed = MessageBuilder.withPayload(payload).copyHeaders(headers).
                 copyHeaders(message.getFailedMessage().getHeaders()).build();
     return parsed;
}

现在,由于此Transformer期望Messaging Exception Object,因此为了将消息从其他变换器转发到Error Transformer,我需要传递Messaging Exception Object。使用MessageChannel.send方法,我只能传递消息对象。请建议

下面是我的另一个变换器代码,我希望将消息转发到错误队列

public Message<MyObject> handleError(MessagingException message) {
Message<MyObject> messageMyObject = null;
    try {
        Object obj = message.getFailedMessage().getPayload();
        MyObject styleML = null;
        if (obj instanceof String) {
            String temp = (String) obj;
            if (temp != null && temp.contains("MyObject"))
                styleML = XMLMarshallingUtil.xmlToObject(temp, MyObject.class);
        } else if (obj instanceof MyObject) {
            styleML = (MyObject) obj;
        }

        String serviceName = EnvironmentResolver.getService();
        Throwable t = ExceptionUtils.getRootCause(message.getCause());
        if (t == null)
            t = message.getCause();
        String userComment = "Exception Occurred";
        String sysComment = t.getMessage();
        MyObject= MyObjectUtils.addMessageEventToMyObject(sysComment, userComment, styleML, serviceName, ProcessState.IN_ERROR);
        messageMyObject = MessageBuilder.withPayload(styleML).copyHeaders(message.getFailedMessage().getHeaders()).build();
       } catch (Exception e) {
        errorsDest.send(MessageBuilder.withPayload(message).build());
    }
    return messageStyleML;
}

1 个答案:

答案 0 :(得分:1)

右。频道与发送和接收方法签订Message合同。但是每封邮件都有payload。在您的情况下handleError接受MessagingException payload的邮件。如果对errorChannel进行错误处理,当任何端点抛出异常时,它将被MessagingException包围failedMessage并进一步包含ErrorMessage

因此,如果您想直接向频道发送内容,即使它是Exception,您需要将其与Message一起包装。它可能是MessageBuilder的结果。

从另一方面,Spring Integration的方法调用原则允许您对方法参数具有任何所需的灵活性。在您的情况下,handleError方法接受MessagingException,这是将消息的有效负载映射到方法参数的默认策略。

希望我理解正确...

<强>更新

关于如何避免向两个频道发送消息的第二个问题。

我建议最简单的方法:

  1. <transformer>更改为<service-activator>。 (Fom方法调用的观点与它们相似。)
  2. errorsDest.send添加return null;之后。 Transformer不允许返回nullServiceActivator默认允许它。在这种情况下,您的主流将停止。