Spring Web Services - 异常跳过ExceptionResolver

wal*_*mon 6 java soap web-services spring-ws

我有一个SOAP服务,如果我为XML元素指定了错误的输入,请求和响应按预期工作,输入良好

在请求正文中:

...
<ns:myIntegerElement>asdf</ns:myIntegerElement>
...
Run Code Online (Sandbox Code Playgroud)

我的异常解析器被调用,这个解析器只是异常解析器的一个实现,因此它没有异常映射,只是抽象方法中的一些System.out

<bean id="exceptionResolver" class="com.mycompany.ws.MyExceptionResolver">
Run Code Online (Sandbox Code Playgroud)

但是,如果我发送的请求看起来更像这样:

...
    <ns:myIntegSOMETHINGGOTTOTALLYMESSUP!!!ent>asdf</ns:myIntegerElement>
...
Run Code Online (Sandbox Code Playgroud)

我的解析器根本没有执行

我将log4j设置为具有根调试级别并查看此输出:

2010-08-09 10:30:01,900 [主题:http-8080-2] DEBUG [org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter] - 接受传入[org.springframework.ws.transport.http.HttpServletConnection@c46dcf ]到[ http:// localhost:8080/myws/MyWebServices /] 错误:'元素类型"ns:MESSEDUPELEMENT"必须由匹配的结束标记""终止." 2010-08-09 10:30:01,920 [主题:http-8080-2] DEBUG [org.springframework.ws.transport.http.MessageDispatcherServlet] - 无法完成请求org.springframework.ws.soap.saaj.SaajSoapMessageException:无法访问信封:无法从给定来源创建信封:; 嵌套异常是com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl:无法从给定的源创建信封:org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion(SaajUtils.java:162)at org .springframework.ws.soap.saaj.SaajSoapMessage.getImplementation(SaajSoapMessage.java:251)org.springframework.ws.soap.saaj.SaajSoapMessage.(SaajSoapMessage.java:位于org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion的com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:122)中的createEnvelopeFromSource(SOAPPart1_1Impl.java:70)( SaajUtils.java:159)... 24更多引起:javax.xml.transform.TransformerException:org.xml.sax.SAXParseException:元素类型"smm:smm-aid"必须由匹配的结束标记终止" ".在com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:719)的com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl. java:313)在com.sun.xml的com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer.transform(EfficientStreamingTransformer.java:393).internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:102)... 27更多引起:org.xml.sax.SAXParseException:元素类型"smm:smm-aid"必须由匹配终止结束标记"".at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231)at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse(SAXParserImpl.java: 522)在com的com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636)的org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707)... 30更多 createEnvelope(EnvelopeFactory.java:102)... 27更多引起:org.xml.sax.SAXParseException:元素类型"smm:smm-aid"必须由匹配的结束标记""终止.at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231)at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse(SAXParserImpl.java: 522)在com的com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636)的org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707)... 30更多 createEnvelope(EnvelopeFactory.java:102)... 27更多引起:org.xml.sax.SAXParseException:元素类型"smm:smm-aid"必须由匹配的结束标记""终止.at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231)at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse(SAXParserImpl.java: 522)在com的com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636)的org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707)... 30更多 元素类型"smm:smm-aid"必须由匹配的结束标记""终止.at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231)at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse(SAXParserImpl.java: 522)在com的com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636)的org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707)... 30更多 元素类型"smm:smm-aid"必须由匹配的结束标记""终止.at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231)at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl $ JAXPSAXParser.parse(SAXParserImpl.java: 522)在com的com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636)的org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707)... 30更多

看来spring在这里缺少一个可能的异常,并没有包装它,但是这样一个基本的错误条件没有被捕获似乎不太可能.任何人都可以帮我找到这个问题的根源吗?

我也将包含web.xml和servlet.xml:

web.xml中:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <init-param>
            <param-name>transformWsdlLocations</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>ws</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>
Run Code Online (Sandbox Code Playgroud)

servlet上下文:

<context:component-scan base-package="com.mycomp.proj.ws" />
    <bean id="smmService" class="com.mycomp.proj.ws.SMMRequestHandlingServiceStubImpl"/>

    <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping"/>
    <bean class="org.springframework.ws.server.endpoint.adapter.MarshallingMethodEndpointAdapter">
        <constructor-arg ref="marshaller"/>
    </bean>
    <bean id="marshaller" class="org.springframework.oxm.castor.CastorMarshaller">
        <property name="mappingLocations">
            <list>
                <value>classpath:mapping.xml</value>
                <value>classpath:hoursOfOperationMapping.xml</value>
            </list>
        </property>
    </bean>

    <bean id="smmws" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
        <property name="schema" ref="schema" />
        <property name="portTypeName" value="SMM" />
        <property name="locationUri" value="/SMMWebServices/"/>
        <property name="targetNamespace" value="http://mycomp.proj.com" />
    </bean>

    <bean id="exceptionResolver" class="com.wdp.smm.ws.MyExceptionResolver"/>

    <bean id="schema" class="org.springframework.xml.xsd.SimpleXsdSchema">
        <property name="xsd" value="/WEB-INF/ws.xsd" />
    </bean>
Run Code Online (Sandbox Code Playgroud)

ehr*_*rdt 6

MessageDispatcherServlet默认创建自己的两个EnpointExceptionResolver实例,即SoapFaultAnnotationExceptionResolver @ 1和SimpleSoapExceptionResolver @ 2

当它解决异常时,SimpleSoapExceptionResolver @ 2将停止任何其他已注册的EnpointExceptionResolver来处理异常.

我花了很长时间才弄清楚,但答案很简单,在你的servlet上下文中你必须这样做:

<bean id="exceptionResolver" class="com.wdp.smm.ws.MyExceptionResolver">
    <property name="order" value="1"/>
</bean>
Run Code Online (Sandbox Code Playgroud)


Thi*_*Roy 5

我更仔细地看了你的问题,我想我知道发生了什么。不会调用您的异常处理程序,因为它在soap 处理中处于较高级别。您会看到,WebServiceMessageReceiverHandlerAdapter 尝试将传入的字符串解码为 XML,然后再将其发送到编组器进行处理。由于 XML 无效,调用失败。由于 WebServiceMessageReceiverHandlerAdapter 不支持异常处理程序,它只是重新抛出异常“SaajSoapMessageException”。

现在您可以做的是创建一个扩展 WebServiceMessageReceiverHandlerAdapter 的新类,但它也将 handleConnection() 包装在 try/catch 中,该类在抛出异常时使用您的异常处理程序。


顺便说一下,在调试此类问题时,我的方法是在 log4j 中输出方法名称和行号。以及下载Spring源。