如何从 Mule ESB 3.8 中的 JAVA Transformer 内部抛出自定义异常?

How to throw a custom exception from inside JAVA Transformer in Mule ESB 3.8?

我正在使用 HTTP 和 CXF 组件在 Mule ESB 3.8 版中实现 SOAP 服务。流程设计见附图

Mule 流程是:

  1. HTTP 和 CXF 组件公开提供两个整数之和的 Web 服务。请求发送的对象是:

public class 添加值{ 私人诠释; 私人诠释 b; public setA(int a) { this.a =一个; } public getA() { return一个; } public setB(int b) { this.b =b; } public getB() { return b; } }

  1. 使用变量保存 SOAP 操作。
  2. 基于 SOAP Action 路由流控制。
  3. 使用JAVA转换器接收payload并抛出Custom Web故障异常如下:

    public class AddValuesBusinessLogic extends AbstractMessageTransformer 
    {
        @Override
        public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
        MuleMessage muleMessage = message;
        AddValues addValues = (AddValues) muleMessage.getPayload();
        if (addValues.getA() == null || addValues.getB() == null ) {
            //Make an AddValueException object
            throw new Exception("Add value exception");
        }
        return null;
    }
    

    }

但我收到错误 "Surround with try/catch"

我的问题是,如果我包围并处理异常,我将如何将 SOAP 错误发送给最终用户?

有人可以建议从 Mule ESB 中的 JAVA Transformer 发送自定义 SOAP 错误的最佳方法是什么吗?

您应该创建自己的 SOAP Fault(纯 Java 字符串)并将其 return 作为消息。如果需要,您还可以创建一个转换器并将其放入您的 catch-exception-strategy 中,如下所示:

@Override
public Object transformMessage(MuleMessage message, String outputEncoding)
    throws TransformerException {

    String exceptionMessage = message.getExceptionPayload().getException().getCause().getMessage();        

    String outputMessage = "<soap:Fault xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">        " +
        " <faultcode>soap:Server</faultcode> " +
        "<faultstring>" + exceptionMessage + "</faultstring>" +
        "</soap:Fault>";

    return outputMessage;
}

Mule 总是期望异常被封装在一个 TransformerException 中,所以你应该抛出一个新的 TransformerException 设置你自己的异常作为原因。

我找到了一个使用 TransformerException 和 CXF OutFaultInterceptor 的解决方案。 我的做法如下:

  1. 编写自定义转换器 class,在其中添加验证规则。例如,如果我想为整数 a 或 b 为 null 抛出错误,我将使用以下代码添加自定义转换器 AddValuesBusinessLogic.class:

    public class AddValuesBusinessLogic extends AbstractMessageTransformer 
    {
        @Override
        public Object transformMessage(MuleMessage message, String outputEncoding) throws 
        TransformerException 
        {
            MuleMessage muleMessage = message;
            AddValues addValues = (AddValues) muleMessage.getPayload();
            if (addValues.getA() == null || addValues.getB() == null ) {
            //Make an AddValueException object
            throw new TransformerException(this,new AddValueException("BAD REQUEST"));
        }
        return "ALL OK";}
    

此异常随后将传播到 CXF,我正在其中编写 OutFaultInterceptor,如下所示:

public class AddValuesFaultInterceptor extends AbstractSoapInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(AddValuesFaultInterceptor.class);

    public AddValuesFaultInterceptor() {
        super(Phase.MARSHAL);
    }

    public void handleMessage(SoapMessage soapMessage) throws Fault {
        Fault fault = (Fault) soapMessage.getContent(Exception.class);

        if (fault.getCause() instanceof org.mule.api.transformer.TransformerMessagingException) {           
            Element detail = fault.getOrCreateDetail();
            Element errorDetail = detail.getOwnerDocument().createElement("addValuesError");
            Element errorCode = errorDetail.getOwnerDocument().createElement("errorCode");
            Element message = errorDetail.getOwnerDocument().createElement("message");
            errorCode.setTextContent("400");
            message.setTextContent("BAD REQUEST");
            errorDetail.appendChild(errorCode);
            errorDetail.appendChild(message);
            detail.appendChild(errorDetail);
        }
    }
    private Throwable getOriginalCause(Throwable t) {
        if (t instanceof ComponentException && t.getCause() != null) {
            return t.getCause();
        } else {
            return t;
        }
    }
}

现在,当我使用 SOAPUI 或 jaxws 客户端进行调用时,我在 SOAP 响应中收到自定义错误异常。

为了在 JAXWS 客户端中提取 errorCode 和 errorMessage 的值,我在 try-catch 的 catch 块中执行以下操作:

catch (com.sun.xml.ws.fault.ServerSOAPFaultException soapFaultException) {

    javax.xml.soap.SOAPFault fault = soapFaultException.getFault(); // <Fault> node
    javax.xml.soap.Detail detail = fault.getDetail(); // <detail> node
    java.util.Iterator detailEntries = detail.getDetailEntries(); // nodes under <detail>'
    while(detailEntries.hasNext()) {
        javax.xml.soap.DetailEntry detailEntry = (DetailEntry) detailEntries.next();
        System.out.println(detailEntry.getFirstChild().getTextContent());
        System.out.println(detailEntry.getLastChild().getTextContent());
    }   
} 

目前这对我有用。 但是,如果有更好的解决方案,我会请求改进此解决方案的建议。

谢谢大家