Web services 如何在Mule中处理soapweb服务中的异常策略

Web services 如何在Mule中处理soapweb服务中的异常策略,web-services,exception,soap,mule,Web Services,Exception,Soap,Mule,我对Mule 3.3.1 CE中的Web服务有一个问题。我有一个公开三个操作的Web服务和一个实现这些操作的类。这些操作可以返回结果(肯定)或异常(AuthExeception、ValidateExeception等)。 多亏了SOAP Mule组件,当我提出Java异常时,框架能够在SOAP错误中处理Java异常,但是如果我想将SOAP错误返回给客户端,并在Mule中使用异常策略处理异常(即发送电子邮件),Mule行为就不是我所能期望的了。 换句话说,例如,当我提出一个AuthExceptio

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

问题是:我如何发送回SOAP响应和处理异常策略

下面是mule xml文件的一个片段,其中异常策略仅通过记录器组件实现:

<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> 

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

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;
}
@覆盖
公共对象转换消息(多消息消息、字符串输出编码)
抛出TransformerException{
字符串exceptionMessage=message.getExceptionPayload().getException().getCause().getMessage();
String outputMessage=“”+
“soap:服务器”+
“”+例外消息+“”+
"";
返回输出消息;
}

注:这是一个样品变压器。为您的场景定制它。

下面是my 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响应,如果是,在哪里?换句话说,如果我使用转换器来构建SOAP响应……响应发送到哪里?我需要一个SOAP和HTTP组件,对吗?这是一个以字符串形式准备的SOAP错误体。这是从您的http:inbound端点作为回复发送回来的。我使用了一个outaultinkeptor。通过这种方式,我能够捕获异常,使用client.send()API并将消息写入VM队列。因此,主流会发回soap响应,SMTP组件会发送电子邮件,并使用更新的流更新帖子。这也可能对其他人有所帮助
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;
    }
}