【问题标题】:How to handle exception strategy in SOAP Web Service in Mule如何在 Mule 中处理 SOAP Web 服务中的异常策略
【发布时间】:2013-05-31 10:56:16
【问题描述】:

我有一个关于 Mule 3.3.1 CE 中的 Web 服务的问题。我有一个 Web 服务,它公开了三个操作和一个实现这些操作的类。这些操作可以返回结果(肯定)或异常(AuthExeception、ValidateExeception 等)。 感谢 SOAP Mule 组件,当我引发 Java 异常时,框架能够在 SOAP 错误中编组 Java 异常,但是如果我想既向客户端返回 SOAP 错误并使用 Mule 中的异常策略处理异常(即发送电子邮件),骡子的行为不是我怎么能期望的。 换句话说,例如,当我引发 AuthException 时,流控制传递给定义的异常策略,我不再能够将 SOAP 错误 (AuthException) 发送回客户端。

问题是:我怎样才能既发回 SOAP 响应又处理异常策略?

这里有一个mule xml文件的sn-p,其中异常策略是通过一个Logger组件简单实现的:

<flow name="esb_consignmentFlow1" doc:name="esb_consignmentFlow1">
        <http:inbound-endpoint exchange-pattern="request-response" host="${conn.host}" port="8081" doc:name="HTTP" path="sgb/consignment" />
        <cxf:jaxws-service doc:name="Process SOAP Request" serviceClass="com.suzuki.sales.webservice.ProcessTriggerPortType"/>
        <component class="it.aizoon.suzuki.service.implementation.TriggerConsignmentOperationsImplementation" doc:name="triggerConsignmentOperationsImpl"/>
        <catch-exception-strategy doc:name="Catch Exception Strategy">
            <flow-ref name="ErrorHandling" doc:name="Flow Reference"/>
        </catch-exception-strategy>
</flow>

<flow name="ErrorHandling" doc:name="ErrorHandling" >
        <logger level="INFO" doc:name="Logger"/>
</flow> 

我读过一些关于处理策略的东西,但我不知道这是否是正确的方法。 非常感谢您的帮助。

【问题讨论】:

    标签: web-services exception soap mule


    【解决方案1】:

    下面是我的 flow.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <mule xmlns:smtp="http://www.mulesoft.org/schema/mule/smtp" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"   xmlns:context="http://www.springframework.org/schema/context" 
            xmlns:http="http://www.mulesoft.org/schema/mule/http" 
            xmlns="http://www.mulesoft.org/schema/mule/core" 
            xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
    http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd 
    http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd 
    http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd 
    http://www.mulesoft.org/schema/mule/smtp http://www.mulesoft.org/schema/mule/smtp/current/mule-smtp.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd 
    http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd ">
        <spring:beans>
            <spring:bean id="consignmentProperty" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                <!-- In questo modo riesco a definire un file di property esterno che non è in una locazione hard-coded -->
                <spring:property name="ignoreUnresolvablePlaceholders" value="true"/>
                <spring:property name="locations">
                    <spring:list>
                        <spring:value>classpath:esb_consignment.properties</spring:value>
                        <spring:value>classpath:connections.properties</spring:value>
                        <spring:value>classpath:email.properties</spring:value>
                        <!-- L'ultimo nella lista è il più generico perché sovrascrive le properties -->
                    </spring:list>
                </spring:property>
            </spring:bean>
            <spring:bean id="outfaultInterceptor" class="it.aizoon.suzuki.service.interceptors.CustomSoapFaultOutInterceptor">
                <spring:property name="outputQueue" value="ErrorHandler"/>
            </spring:bean>
        </spring:beans>
    
        <flow name="TriggerConsignmentInterceptorService" doc:name="TriggerConsignmentInterceptorService">
            <http:inbound-endpoint exchange-pattern="request-response" host="${conn.host}" port="${conn.port}" doc:name="HTTP" path="sgb/consignment" />
            <cxf:jaxws-service doc:name="Process SOAP Request" serviceClass="com.suzuki.sales.webservice.ProcessTriggerPortType">
                <cxf:outFaultInterceptors>
                    <spring:ref bean="outfaultInterceptor"/>
                </cxf:outFaultInterceptors>        
            </cxf:jaxws-service>
            <component class="it.aizoon.suzuki.service.implementation.TriggerConsignmentOperationsImplementation" doc:name="triggerConsignmentOperationsImpl"/>
        </flow>
        <flow name="ErrorHandler" doc:name="ErrorHandler">
            <vm:inbound-endpoint exchange-pattern="one-way" path="ErrorHandler" doc:name="Error Handler"/>
            <logger message="PAYLOAD: #[message.payload]" level="INFO" doc:name="Payload"/>
            <set-payload value="Tipo di Eccezione: #[message.payload]" doc:name="Set Payload"/>
            <smtp:outbound-endpoint host="${smtp.host}"
                                    from="${email.fromAddress}"
                                    to="${email.toAddress}" 
                                    subject="${email.subject}" 
                                    responseTimeout="10000" 
                                    doc:name="Email Notification"/>
            <logger message="EMAIL SENT" level="INFO" doc:name="Result"/>
            <catch-exception-strategy doc:name="Catch Exception Strategy">
                <logger message="ERRORE INVIO EMAIL" level="INFO" doc:name="Logger"/>
            </catch-exception-strategy>
        </flow>
    
    </mule>
    

    下面是处理 SOAP 响应和异常策略的拦截器

    package it.aizoon.suzuki.service.interceptors;
    
    import javax.xml.bind.UnmarshalException;
    import org.apache.cxf.interceptor.Fault;
    import org.apache.cxf.message.Message;
    import org.apache.cxf.phase.AbstractPhaseInterceptor;
    import org.apache.cxf.phase.Phase;
    import org.mule.DefaultMuleMessage;
    import org.mule.api.MuleContext;
    import org.mule.api.MuleEvent;
    import org.mule.api.MuleException;
    import org.mule.api.client.MuleClient;
    import org.mule.api.context.MuleContextAware;
    import org.mule.module.cxf.CxfConstants;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.suzuki.sales.webservice.AuthenticationFailedException;
    import com.suzuki.sales.webservice.ValidationFailedException;
    
    public class CustomSoapFaultOutInterceptor extends AbstractPhaseInterceptor implements MuleContextAware{
    
        private static final Logger logger = LoggerFactory.getLogger(CustomSoapFaultOutInterceptor.class);
    
        private String outputQueue;
        private MuleContext context;
    
    
        public CustomSoapFaultOutInterceptor() {
            // TODO Auto-generated constructor stub
            super(Phase.MARSHAL);
        }
    
        @Override
        public void setMuleContext(MuleContext context) {
            // TODO Auto-generated method stub
            this.context = context;
        }
    
        @Override
        public void handleMessage(Message message) throws Fault {
            // TODO Auto-generated method stub
            MuleClient client = context.getClient();
            MuleEvent event = (MuleEvent) message.getExchange().get(CxfConstants.MULE_EVENT);
            DefaultMuleMessage muleMessage = (DefaultMuleMessage) event.getMessage();
    
            Throwable genericExec = message.getContent(Exception.class).getCause();
            Throwable exception = null;
    
            if(genericExec instanceof ValidationFailedException){
                exception = (ValidationFailedException) genericExec;
    
            }else if(genericExec instanceof AuthenticationFailedException){
                exception = (AuthenticationFailedException) genericExec;
    
            }else if(genericExec instanceof UnmarshalException){
                exception = (UnmarshalException) genericExec;
            }
    
    
            try {
    
                muleMessage.setPayload(exception);
                client.send("vm://" + getOutputQueue(), muleMessage);
    
            } catch (MuleException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        public String getOutputQueue() {
            return outputQueue;
        }
    
        public void setOutputQueue(String outputQueue) {
            this.outputQueue = outputQueue;
        }
    
        public MuleContext getContext() {
            return context;
        }
    
        public void setContext(MuleContext context) {
            this.context = context;
        }
    }
    

    【讨论】:

      【解决方案2】:

      Mule 抑制了超出异常策略的异常。

      对于这种您想要处理异常并将其作为回复发送的场景,将提供一个自定义转换器来准备带有异常的soap故障,然后将其设置为异常策略流中的有效负载。

      <flow name="ErrorHandling" doc:name="ErrorHandling" >
          <logger level="INFO" doc:name="Logger"/>
          <custom-transformer class="com.example.service.ErrorTransformer"></custom-transformer>
      </flow>
      

      还有一个转换器来准备错误信息。

      @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;
      }
      

      注意:这是一个示例转换器。为您的场景定制它。

      【讨论】:

      • 首先感谢您的回复。我想知道您的解决方案是否发送了 SOAP 响应,如果是,在哪里?换句话说,如果我使用转换器来构建 SOAP 响应……响应发送到哪里?我需要一个 SOAP 和一个 HTTP 组件,对吧?
      • 这是一个以字符串形式准备的SOAP故障体。这是从您的 http:inbound 端点作为回复发回的。
      • 我使用了一个 outFaultInterceptor。通过这种方式,我能够捕获异常,使用 client.send() API 并将消息写入 VM 队列。所以主流程发回soap响应,SMTP组件发送电子邮件
      • 使用更新后的流程更新帖子。这也可能对其他人有所帮助。
      • 下面是我的 xml 流程
      猜你喜欢
      • 2023-03-04
      • 2011-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      • 2012-04-20
      • 2018-08-17
      • 2013-05-30
      相关资源
      最近更新 更多