如何使用 Spring Web 服务创建自定义肥皂故障消息

发布于 2024-10-01 10:53:23 字数 4463 浏览 1 评论 0原文

我正在尝试使用 Spring Web 服务库编写一个 Web 服务。我能够成功配置我的端点并且工作正常,但我在异常映射方面遇到了一些问题。

我可以使用 @SoapFault 和 SoapFaultAnnotationExceptionResolver 映射异常,但 wsdl 定义如下

<xsd:schema elementFormDefault="qualified" targetNamespace="http://abc.com/soap/">
    <xsd:complexType name="ServiceException">
        <xsd:sequence>
            <xsd:element name="message" nillable="true" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="ValidationException">
        <xsd:complexContent>
            <xsd:extension base="tns:ServiceException">
                <xsd:sequence/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="InternalException">
        <xsd:complexContent>
            <xsd:extension base="tns:ServiceException">
                <xsd:sequence/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="AuthenticationException">
        <xsd:complexContent>
            <xsd:extension base="tns:ServiceException">
                <xsd:sequence/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="LoginInput">
        <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1" name="UserName" nillable="false" type="xsd:string"/>
            <xsd:element minOccurs="1" maxOccurs="1" name="PassWord" nillable="false" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="LoginOutput">
        <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1" name="ValidTo" nillable="false" type="xsd:dateTime"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="login" type="tns:LoginInput"/>
    <xsd:element name="loginResponse" type="tns:LoginOutput"/>

    <xsd:element name="ValidationException" type="tns:ValidationException"/>
    <xsd:element name="InternalException" type="tns:InternalException"/>
    <xsd:element name="AuthenticationException" type="tns:AuthenticationException"/>
</xsd:schema>

<message name="LoginRequest">
    <part name="login" element="tns:login"/>
</message>

<message name="LoginResponse">
    <part name="loginResponse" element="tns:loginResponse"/>
</message>

<message name="ValidationException">
    <part name="ValidationException" element="tns:ValidationException"/>
</message>

<message name="InternalException">
    <part name="InternalException" element="tns:InternalException"/>
</message>

<message name="AuthenticationException">
    <part name="AuthenticationException" element="tns:AuthenticationException"/>
</message>

<portType name="ServicePortType">
    <operation name="Login">
        <input message="tns:LoginRequest"/>
        <output message="tns:LoginResponse"/>
        <fault name="ValidationException" message="tns:ValidationException"/>
        <fault name="InternalException" message="tns:InternalException"/>
        <fault name="AuthenticationException" message="tns:AuthenticationException"/>
    </operation>
</portType>

<binding name="ServiceBinding" type="tns:ServicePortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="Login">
        <soap:operation soapAction="urn://Service#Login"/>
        <input>
            <soap:body use="literal"/>
        </input>
        <output>
            <soap:body use="literal"/>
        </output>
        <fault name="ValidationException">
            <soap:fault name="ValidationException" use="literal"/>
        </fault>
        <fault name="InternalException">
            <soap:fault name="InternalException" use="literal"/>
        </fault>
        <fault name="AuthenticationException">
            <soap:fault name="AuthenticationException" use="literal"/>
        </fault>
    </operation>
</binding>

如何为此服务定义编写异常处理?

谢谢

I'm trying to write a web service using spring web service library. I'm able to configure my endpoints successfully and it is working fine, but I'm facing some issues with the exception mappings.

I'm able to map exceptions using @SoapFault and SoapFaultAnnotationExceptionResolver but the wsdl definition is as follows

<xsd:schema elementFormDefault="qualified" targetNamespace="http://abc.com/soap/">
    <xsd:complexType name="ServiceException">
        <xsd:sequence>
            <xsd:element name="message" nillable="true" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="ValidationException">
        <xsd:complexContent>
            <xsd:extension base="tns:ServiceException">
                <xsd:sequence/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="InternalException">
        <xsd:complexContent>
            <xsd:extension base="tns:ServiceException">
                <xsd:sequence/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="AuthenticationException">
        <xsd:complexContent>
            <xsd:extension base="tns:ServiceException">
                <xsd:sequence/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="LoginInput">
        <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1" name="UserName" nillable="false" type="xsd:string"/>
            <xsd:element minOccurs="1" maxOccurs="1" name="PassWord" nillable="false" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="LoginOutput">
        <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1" name="ValidTo" nillable="false" type="xsd:dateTime"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="login" type="tns:LoginInput"/>
    <xsd:element name="loginResponse" type="tns:LoginOutput"/>

    <xsd:element name="ValidationException" type="tns:ValidationException"/>
    <xsd:element name="InternalException" type="tns:InternalException"/>
    <xsd:element name="AuthenticationException" type="tns:AuthenticationException"/>
</xsd:schema>

<message name="LoginRequest">
    <part name="login" element="tns:login"/>
</message>

<message name="LoginResponse">
    <part name="loginResponse" element="tns:loginResponse"/>
</message>

<message name="ValidationException">
    <part name="ValidationException" element="tns:ValidationException"/>
</message>

<message name="InternalException">
    <part name="InternalException" element="tns:InternalException"/>
</message>

<message name="AuthenticationException">
    <part name="AuthenticationException" element="tns:AuthenticationException"/>
</message>

<portType name="ServicePortType">
    <operation name="Login">
        <input message="tns:LoginRequest"/>
        <output message="tns:LoginResponse"/>
        <fault name="ValidationException" message="tns:ValidationException"/>
        <fault name="InternalException" message="tns:InternalException"/>
        <fault name="AuthenticationException" message="tns:AuthenticationException"/>
    </operation>
</portType>

<binding name="ServiceBinding" type="tns:ServicePortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="Login">
        <soap:operation soapAction="urn://Service#Login"/>
        <input>
            <soap:body use="literal"/>
        </input>
        <output>
            <soap:body use="literal"/>
        </output>
        <fault name="ValidationException">
            <soap:fault name="ValidationException" use="literal"/>
        </fault>
        <fault name="InternalException">
            <soap:fault name="InternalException" use="literal"/>
        </fault>
        <fault name="AuthenticationException">
            <soap:fault name="AuthenticationException" use="literal"/>
        </fault>
    </operation>
</binding>

How can I write a exception handling for this service definition?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜清冷一曲。 2024-10-08 10:53:23

经过更多搜索后,我发现 这个来自 spring 源论坛

SoapMessage response = (SoapMessage) messageContext.getResponse();
SoapBody soapBody = response.getSoapBody();

SoapFault soapFault =
soapBody.addClientOrSenderFault(ex.getMessage(), Locale.ENGLISH);

SoapFaultDetail faultDetail = soapFault.addFaultDetail();
Result result = faultDetail.getResult();

// My detail XML object
InvalidArgumentFault fault = new InvalidArgumentFault();
fault.setErrorCode("Custom Error Code");
fault.setOpsMessage("This is the ops message");
fault.setSystemMessage("This is the system message");

// Marshal the detail. We have to use the ObjectFactory which isn't
// marshaller agnostic because the detail element doesn't have an
// XmlRootElement tag as required by JAXB.
ObjectFactory of = new ObjectFactory();
mMarshaller.marshal(of.createInvalidArgumentFault( fault), result);

更新

这是我正在使用的完整示例实现,

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.xml.transform.Result;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.oxm.Marshaller;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.endpoint.AbstractEndpointExceptionResolver;
import org.springframework.ws.soap.SoapBody;
import org.springframework.ws.soap.SoapFault;
import org.springframework.ws.soap.SoapFaultDetail;
import org.springframework.ws.soap.SoapMessage;

import org.apache.commons.lang.StringUtils;

public class CustomSoapFaultDetailAnnotationExceptionResolver extends
        AbstractEndpointExceptionResolver implements ApplicationContextAware {
    private static Log log = LogFactory
            .getLog(CustomSoapFaultDetailAnnotationExceptionResolver.class);

    private Collection<Marshaller> marshallers;

    private Map<Class<? extends Object>, Marshaller> marshallerMap = new HashMap<Class<? extends Object>, Marshaller>();

    public CustomSoapFaultDetailAnnotationExceptionResolver() {
        setWarnLogCategory(getClass().getCanonicalName());
    }

    @Override
    protected boolean resolveExceptionInternal(MessageContext messageContext,
            Object endpoint, Exception ex) {
        boolean resolved = false;

        try {
            CustomSoapFaultDetails annotation = ex.getClass().getAnnotation(
                    CustomSoapFaultDetails.class);
            if (annotation != null) {

                Method m = ex.getClass().getMethod("getFaultInfo",
                        new Class[] {});
                Object fault = m.invoke(ex, new Object[] {});

                SoapMessage response = (SoapMessage) messageContext
                        .getResponse();
                SoapBody soapBody = response.getSoapBody();

                SoapFault soapFault = soapBody
                        .addClientOrSenderFault(
                                StringUtils.isBlank(ex.getMessage()) ? "server exception"
                                        : ex.getMessage(), Locale.ENGLISH);

                SoapFaultDetail faultDetail = soapFault.addFaultDetail();
                Result result = faultDetail.getResult();

                if (marshallerMap.containsKey(fault.getClass())) {
                    marshallerMap.get(fault.getClass()).marshal(fault, result);
                    resolved = true;
                } else {
                    for (Marshaller marshaller : marshallers) {
                        try {
                            marshaller.marshal(fault, result);
                            marshallerMap.put(fault.getClass(), marshaller);
                            resolved = true;
                            break;
                        } catch (Exception e) {
                            // Ignore error
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return resolved;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.marshallers = applicationContext.getBeansOfType(Marshaller.class)
                .values();
    }
}

After some more search I found this from spring source forum.

SoapMessage response = (SoapMessage) messageContext.getResponse();
SoapBody soapBody = response.getSoapBody();

SoapFault soapFault =
soapBody.addClientOrSenderFault(ex.getMessage(), Locale.ENGLISH);

SoapFaultDetail faultDetail = soapFault.addFaultDetail();
Result result = faultDetail.getResult();

// My detail XML object
InvalidArgumentFault fault = new InvalidArgumentFault();
fault.setErrorCode("Custom Error Code");
fault.setOpsMessage("This is the ops message");
fault.setSystemMessage("This is the system message");

// Marshal the detail. We have to use the ObjectFactory which isn't
// marshaller agnostic because the detail element doesn't have an
// XmlRootElement tag as required by JAXB.
ObjectFactory of = new ObjectFactory();
mMarshaller.marshal(of.createInvalidArgumentFault( fault), result);

UPDATED

This a complete sample implementations I'm using,

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.xml.transform.Result;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.oxm.Marshaller;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.endpoint.AbstractEndpointExceptionResolver;
import org.springframework.ws.soap.SoapBody;
import org.springframework.ws.soap.SoapFault;
import org.springframework.ws.soap.SoapFaultDetail;
import org.springframework.ws.soap.SoapMessage;

import org.apache.commons.lang.StringUtils;

public class CustomSoapFaultDetailAnnotationExceptionResolver extends
        AbstractEndpointExceptionResolver implements ApplicationContextAware {
    private static Log log = LogFactory
            .getLog(CustomSoapFaultDetailAnnotationExceptionResolver.class);

    private Collection<Marshaller> marshallers;

    private Map<Class<? extends Object>, Marshaller> marshallerMap = new HashMap<Class<? extends Object>, Marshaller>();

    public CustomSoapFaultDetailAnnotationExceptionResolver() {
        setWarnLogCategory(getClass().getCanonicalName());
    }

    @Override
    protected boolean resolveExceptionInternal(MessageContext messageContext,
            Object endpoint, Exception ex) {
        boolean resolved = false;

        try {
            CustomSoapFaultDetails annotation = ex.getClass().getAnnotation(
                    CustomSoapFaultDetails.class);
            if (annotation != null) {

                Method m = ex.getClass().getMethod("getFaultInfo",
                        new Class[] {});
                Object fault = m.invoke(ex, new Object[] {});

                SoapMessage response = (SoapMessage) messageContext
                        .getResponse();
                SoapBody soapBody = response.getSoapBody();

                SoapFault soapFault = soapBody
                        .addClientOrSenderFault(
                                StringUtils.isBlank(ex.getMessage()) ? "server exception"
                                        : ex.getMessage(), Locale.ENGLISH);

                SoapFaultDetail faultDetail = soapFault.addFaultDetail();
                Result result = faultDetail.getResult();

                if (marshallerMap.containsKey(fault.getClass())) {
                    marshallerMap.get(fault.getClass()).marshal(fault, result);
                    resolved = true;
                } else {
                    for (Marshaller marshaller : marshallers) {
                        try {
                            marshaller.marshal(fault, result);
                            marshallerMap.put(fault.getClass(), marshaller);
                            resolved = true;
                            break;
                        } catch (Exception e) {
                            // Ignore error
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return resolved;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.marshallers = applicationContext.getBeansOfType(Marshaller.class)
                .values();
    }
}
汐鸠 2024-10-08 10:53:23

我已经成功地使用 SOAP Spring-WS 创建了一个 Web 服务。现在我正在这个 SOAP 服务中执行错误实现,并且我能够使用我创建的类来完成此操作,如下所示,

public class ServiceSoapFaultMappingExceptionResolver extends SoapFaultMappingExceptionResolver

并在以下重写函数中,

@Override


protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) {

//code for adding fault details

    SoapFaultDefinition soapFaultDefinition = new SoapFaultDefinition();
    String ENVELOPE_NAMESPACE_URI = "http://schemas.xmlsoap.org/soap/envelope/";

    //      soapFaultDefinition.setFaultStringOrReason("--" + ex);

    //      soapFaultDefinition.setLocale(Locale.ENGLISH);

    QName CLIENT_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI,"5003", "e");
    soapFaultDefinition.setFaultCode(CLIENT_FAULT_NAME);
    setDefaultFault(soapFaultDefinition);
    Result result = fault.addFaultDetail().getResult();

        // marshal
        try {
             JAXBContext.newInstance(ExceptionListType.class).createMarshaller().marshal(exceptionList, result);

}

此答案用于原始解决方案。

I have successfully used SOAP Spring-WS to create a web service. Now I was doing the fault implementation in this SOAP service and I was able to do it with a class that I created like the following,

public class ServiceSoapFaultMappingExceptionResolver extends SoapFaultMappingExceptionResolver

and inside the following overridden function,

@Override


protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) {

//code for adding fault details

    SoapFaultDefinition soapFaultDefinition = new SoapFaultDefinition();
    String ENVELOPE_NAMESPACE_URI = "http://schemas.xmlsoap.org/soap/envelope/";

    //      soapFaultDefinition.setFaultStringOrReason("--" + ex);

    //      soapFaultDefinition.setLocale(Locale.ENGLISH);

    QName CLIENT_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI,"5003", "e");
    soapFaultDefinition.setFaultCode(CLIENT_FAULT_NAME);
    setDefaultFault(soapFaultDefinition);
    Result result = fault.addFaultDetail().getResult();

        // marshal
        try {
             JAXBContext.newInstance(ExceptionListType.class).createMarshaller().marshal(exceptionList, result);

}

Please this answer for the original solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文