java Spring Web 服务 - 异常跳过 ExceptionResolver
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3441183/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Web Services - Exception Skipping ExceptionResolver
提问by walnutmon
I have a SOAP service, the request and responses work as expected with good input, if I specify bad input for an XML element
我有一个 SOAP 服务,如果我为 XML 元素指定了错误的输入,请求和响应将按预期工作,输入良好
in request body:
在请求正文中:
...
<ns:myIntegerElement>asdf</ns:myIntegerElement>
...
my exception resolver is invoked, this resolver is just an implementation of the exception resolver, so it doesn't have exception mappings, just a few System.out's in the abstract method
我的异常解析器被调用了,这个解析器只是异常解析器的一个实现,所以它没有异常映射,只有抽象方法中的几个System.out
<bean id="exceptionResolver" class="com.mycompany.ws.MyExceptionResolver">
however, if I send a request that looks more like this:
但是,如果我发送一个看起来更像这样的请求:
...
<ns:myIntegSOMETHINGGOTTOTALLYMESSUP!!!ent>asdf</ns:myIntegerElement>
...
my resolver isn't executed at all
我的解析器根本没有执行
I setup log4j to have a root debug level and see this output:
我将 log4j 设置为具有根调试级别并查看以下输出:
2010-08-09 10:30:01,900 [Thread:http-8080-2] DEBUG [org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter] - Accepting incoming [org.springframework.ws.transport.http.HttpServletConnection@c46dcf] to [http://localhost:8080/myws/MyWebServices/]ERROR: 'The element type "ns:MESSEDUPELEMENT" must be terminated by the matching end-tag "".' 2010-08-09 10:30:01,920 [Thread:http-8080-2] DEBUG [org.springframework.ws.transport.http.MessageDispatcherServlet] - Could not complete request org.springframework.ws.soap.saaj.SaajSoapMessageException: Could not access envelope: Unable to create envelope from given source: ; nested exception is com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source: at org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion(SaajUtils.java:162) at org.springframework.ws.soap.saaj.SaajSoapMessage.getImplementation(SaajSoapMessage.java:251) at org.springframework.ws.soap.saaj.SaajSoapMessage.(SaajSoapMessage.java:84) at org.springframework.ws.soap.saaj.SaajSoapMessage.(SaajSoapMessage.java:70) at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:168) at org.springframework.ws.transport.AbstractWebServiceConnection.receive(AbstractWebServiceConnection.java:90) at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:86) at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:57) at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:230) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511) at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:859) at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579) at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1555) at java.lang.Thread.run(Thread.java:619) Caused by: com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source: at com.sun.xml.internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:114) at com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPPart1_1Impl.createEnvelopeFromSource(SOAPPart1_1Impl.java:70) at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:122) at org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion(SaajUtils.java:159) ... 24 more Caused by: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException: The element type "smm:smm-aid" must be terminated by the matching end-tag "". at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:719) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:313) at com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer.transform(EfficientStreamingTransformer.java:393) at com.sun.xml.internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:102) ... 27 more Caused by: org.xml.sax.SAXParseException: The element type "smm:smm-aid" must be terminated by the matching end-tag "". 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) at org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707) ... 30 more
2010-08-09 10:30:01,900 [线程:http-8080-2] 调试 [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] 调试 [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) 在 org .springframework.ws.soap.saaj.SaajSoapMessage.getImplementation(SaajSoapMessage.java:251) 在 org.springframework.ws.soap.saaj.SaajSoapMessage.(SaajSoapMessage.java: createEnvelopeFromSource(SOAPPart1_1Impl.java:70) at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:122) at org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion( 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.transform(TransformerImpl.java:719) java:313) 在 com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer.transform(EfficientStreamingTransformer.java:393) 在 com.sun.xml。internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:102) ... 27 more 引起:org.xml.sax.SAXParseException:元素类型“smm:smm-aid”必须由匹配终止结束标签“”。在 com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231) 在 com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java: 522) 在 org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) 在 com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636) 在 com .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707) ... 30 更多 createEnvelope(EnvelopeFactory.java:102) ... 27 more 原因:org.xml.sax.SAXParseException:元素类型“smm:smm-aid”必须以匹配的结束标签“”结尾。在 com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231) 在 com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java: 522) 在 org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) 在 com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636) 在 com .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707) ... 30 更多 createEnvelope(EnvelopeFactory.java:102) ... 27 more 原因:org.xml.sax.SAXParseException:元素类型“smm:smm-aid”必须以匹配的结束标签“”结尾。在 com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231) 在 com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java: 522) 在 org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) 在 com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636) 在 com .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707) ... 30 更多 元素类型“smm:smm-aid”必须以匹配的结束标签“”结尾。在 com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231) 在 com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java: 522) 在 org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) 在 com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636) 在 com .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707) ... 30 更多 元素类型“smm:smm-aid”必须以匹配的结束标签“”结尾。在 com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231) 在 com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java: 522) 在 org.xml.sax.helpers.XMLFilterImpl.parse(XMLFilterImpl.java:333) 在 com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:636) 在 com .sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:707) ... 30 更多
It appears that spring is missing a possible exception here, and not wrapping it, but such a basic error condition not being caught seems unlikely to me. Can anyone help me to find the root of this issue?
似乎 spring 在这里遗漏了一个可能的异常,并且没有将其包装起来,但是在我看来,这种没有被捕获的基本错误条件似乎不太可能。谁能帮我找到这个问题的根源?
I'll include web.xml and servlet.xml too:
我也会包含 web.xml 和 servlet.xml:
web.xml:
网页.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>
servlet context:
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>
采纳答案by Thierry-Dimitri Roy
I've looked more closely at your question and I think that I know what's happening. You exception handler is not called because it is in the higher level in the soap processing. You see, WebServiceMessageReceiverHandlerAdapter tries to decode the incoming string to an XML before sending it to the marshaller to be processed. Since the XML is invalid the call fails. And since WebServiceMessageReceiverHandlerAdapter does not support an exception handler, it just rethrows the exception "SaajSoapMessageException".
我更仔细地看了你的问题,我想我知道发生了什么。不会调用您的异常处理程序,因为它在soap 处理中处于较高级别。您会看到,WebServiceMessageReceiverHandlerAdapter 尝试将传入的字符串解码为 XML,然后再将其发送到编组器进行处理。由于 XML 无效,调用失败。由于 WebServiceMessageReceiverHandlerAdapter 不支持异常处理程序,它只是重新抛出异常“SaajSoapMessageException”。
Now what you can do is create a new class that extends WebServiceMessageReceiverHandlerAdapter, but that also wraps handleConnection() in a try/catch that uses your exception handler when a exception is throw.
现在您可以做的是创建一个扩展 WebServiceMessageReceiverHandlerAdapter 的新类,但它也将 handleConnection() 包装在 try/catch 中,该类在抛出异常时使用您的异常处理程序。
By the way, when debugging this kind of problem my approach is to output both method name and line number in log4j. As well as downloading the Spring sources.
顺便说一句,在调试此类问题时,我的方法是在 log4j 中同时输出方法名称和行号。以及下载 Spring 源代码。
回答by ehrhardt
The MessageDispatcherServlet creates its own two instances of EnpointExceptionResolver by default, namely SoapFaultAnnotationExceptionResolver@1 and SimpleSoapExceptionResolver@2
MessageDispatcherServlet 默认创建自己的两个 EnpointExceptionResolver 实例,即 SoapFaultAnnotationExceptionResolver@1 和 SimpleSoapExceptionResolver@2
And when it resolves an exception the SimpleSoapExceptionResolver@2 will stop any other registered EnpointExceptionResolver to handle an exception.
当它解决异常时,SimpleSoapExceptionResolver@2 将停止任何其他注册的 EnpointExceptionResolver 来处理异常。
It took me embarrassingly long to figure out, but the answer is quite simple, in your servlet context you have to do this:
我花了很长时间才弄明白,但答案很简单,在您的 servlet 上下文中,您必须这样做:
<bean id="exceptionResolver" class="com.wdp.smm.ws.MyExceptionResolver">
<property name="order" value="1"/>
</bean>
回答by eis
I think what @thierry-dimitri-roy explained is correct, however I had a lot of issues actually implementing it. For example, just wrapping the handleconnection method isn't enough due to noendpointfoundexception not being thrown. As this is more general issue of handling exceptions nicely, I'm putting my code here to ease the pain for future generations. This is tested with spring-ws 2.1.3 and JBoss AS7.
我认为@thierry-dimitri-roy 的解释是正确的,但是我在实际实施时遇到了很多问题。例如,由于没有抛出 noendpointfoundexception,仅仅包装 handleconnection 方法是不够的。由于这是更好地处理异常的更普遍的问题,我将我的代码放在这里是为了减轻后代的痛苦。这是用 spring-ws 2.1.3 和 JBoss AS7 测试的。
My message handler converts all problems to soap faults with response code 200.
我的消息处理程序将所有问题转换为响应代码为 200 的soap错误。
package fi.eis.applications.spring.soap.server.transport.http;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.ws.FaultAwareWebServiceMessage;
import org.springframework.ws.InvalidXmlException;
import org.springframework.ws.NoEndpointFoundException;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.support.DefaultStrategiesHelper;
import org.springframework.ws.transport.EndpointAwareWebServiceConnection;
import org.springframework.ws.transport.FaultAwareWebServiceConnection;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageReceiver;
import org.springframework.ws.transport.context.DefaultTransportContext;
import org.springframework.ws.transport.context.TransportContext;
import org.springframework.ws.transport.context.TransportContextHolder;
import org.springframework.ws.transport.http.HttpServletConnection;
import org.springframework.ws.transport.http.HttpTransportConstants;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter;
import org.springframework.ws.transport.support.TransportUtils;
/**
* Adapter to map XML parsing and other low-level errors to SOAP faults instead of
* server standard error pages. Also, this class will always use return code HTTP_OK
* (status 200) to requests, even if there are errors.
*
*/
public class MyWebServiceMessageReceiverHandlerAdapter
extends WebServiceMessageReceiverHandlerAdapter
implements HandlerAdapter, Ordered, InitializingBean, ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.context = applicationContext;
}
@Override
public void afterPropertiesSet() {
DefaultStrategiesHelper defaultStrategiesHelper = new DefaultStrategiesHelper(MessageDispatcherServlet.class);
WebServiceMessageFactory factory = defaultStrategiesHelper
.getDefaultStrategy(WebServiceMessageFactory.class, context);
setMessageFactory(factory);
}
public ModelAndView handle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object handler) throws Exception {
if (HttpTransportConstants.METHOD_POST.equals(httpServletRequest.getMethod())) {
WebServiceConnection connection = new MyWebServiceConnection(httpServletRequest, httpServletResponse);
try {
overriddenHandleConnection(connection, (WebServiceMessageReceiver) handler);
} catch (InvalidXmlException ex) {
handleInvalidXmlException(httpServletRequest, httpServletResponse, handler, ex);
} catch (Exception ex) {
handleGeneralException(httpServletRequest, httpServletResponse, handler, ex);
}
}
else {
handleNonPostMethod(httpServletRequest, httpServletResponse, handler);
}
return null;
}
/**
* Overridden version of handleConnection from WebServiceMessageReceiverObjectSupport to be able to handle
* missing endpoint ourselves. That method is final, so we need to use another method here.
*
* This has been reported as https://jira.springsource.org/browse/SWS-850
*
* @param connection
* @param receiver
* @throws Exception
*/
protected void overriddenHandleConnection(WebServiceConnection connection, WebServiceMessageReceiver receiver)
throws Exception {
logUri(connection);
TransportContext previousTransportContext = TransportContextHolder.getTransportContext();
TransportContextHolder.setTransportContext(new DefaultTransportContext(connection));
try {
WebServiceMessage request = connection.receive(getMessageFactory());
MessageContext messageContext = new DefaultMessageContext(request, getMessageFactory());
receiver.receive(messageContext);
if (messageContext.hasResponse()) {
WebServiceMessage response = messageContext.getResponse();
if (response instanceof FaultAwareWebServiceMessage &&
connection instanceof FaultAwareWebServiceConnection) {
FaultAwareWebServiceMessage faultResponse = (FaultAwareWebServiceMessage) response;
FaultAwareWebServiceConnection faultConnection = (FaultAwareWebServiceConnection) connection;
faultConnection.setFault(faultResponse.hasFault());
}
connection.send(messageContext.getResponse());
}
}
catch (NoEndpointFoundException ex) {
if (connection instanceof EndpointAwareWebServiceConnection) {
((EndpointAwareWebServiceConnection) connection).endpointNotFound();
}
throw ex;
}
finally {
TransportUtils.closeConnection(connection);
TransportContextHolder.setTransportContext(previousTransportContext);
}
}
private void logUri(WebServiceConnection connection) {
if (logger.isDebugEnabled()) {
try {
logger.debug("Accepting incoming [" + connection + "] at [" + connection.getUri() + "]");
}
catch (URISyntaxException e) {
// ignore
}
}
}
private void handleGeneralException(
HttpServletRequest httpServletRequest,
HttpServletResponse response, Object handler,
Exception ex) throws IOException {
writeErrorResponseWithMessage(response, ex.getClass().getName() + ": " + ex.getMessage());
}
/**
* By default, sets SC_BAD_REQUEST as response in Spring, so overwritten to
* provide HTTP_OK and reasonable SOAP fault response.
*/
protected void handleInvalidXmlException(
HttpServletRequest httpServletRequest,
HttpServletResponse response, Object handler, InvalidXmlException ex)
throws IOException {
writeErrorResponseWithMessage(response, ex.getClass().getName() + ": " + ex.getMessage());
}
/**
* By default, sets SC_METHOD_NOT_ALLOWED as response in Spring, so overwritten to
* provide HTTP_OK and reasonable SOAP fault response.
*/
protected void handleNonPostMethod(HttpServletRequest httpServletRequest,
HttpServletResponse response,
Object handler) throws Exception {
writeErrorResponseWithMessage(response, "HTTP Method not allowed");
}
private void writeErrorResponseWithMessage(HttpServletResponse response, String message)
throws IOException {
String errorXml = String.format(
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+" <SOAP-ENV:Header/>"
+" <SOAP-ENV:Body>"
+" <SOAP-ENV:Fault>"
+" <faultcode>SOAP-ENV:Client</faultcode>"
+" <faultstring xml:lang=\"en\">%s</faultstring>"
+" </SOAP-ENV:Fault>"
+" </SOAP-ENV:Body>"
+"</SOAP-ENV:Envelope>",
StringEscapeUtils.escapeXml(message)
);
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("text/xml");
response.getWriter().write(errorXml);
response.getWriter().flush();
}
@Override
public int getOrder() {
return 1;
}
/**
* This class is needed as org.springframework.ws.transport.http.HttpServletConnection will throw an
* exception if it is used outside Spring framework files. However, extending it and using the same
* implementation seems to be fine.
*
*/
static class MyWebServiceConnection extends HttpServletConnection {
protected MyWebServiceConnection(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
super(httpServletRequest, httpServletResponse);
}
}
}
This needs to be also configured correctly. This is the thing that is needed on spring context:
这也需要正确配置。这是在 spring 上下文中需要的东西:
<!-- 'messageReceiverHandlerAdapter' is a magic name spring-ws
org.springframework.ws.transport.http.MessageDispatcherServlet
will bind to -->
<bean id="messageReceiverHandlerAdapter"
class="fi.eis.applications.spring.soap.server.transport.http.MyWebServiceMessageReceiverHandlerAdapter">
</bean>
回答by K Erlandsson
I remember running into this kind of problem when working with spring-security. I also had issues with my exception resolver not being invoked under some condititions.
我记得在使用 spring-security 时遇到过这种问题。我也遇到了在某些条件下没有调用我的异常解析器的问题。
The problem then was that there is a filter chain that handles each request. The code that invokes the exception resolvers is a filter in this chain, but it is close to the end of the chain. Hence, if an exception ocurred somewhere within the filters before the exception resolver invoking filter, my resolver would never be invoked.
然后的问题是有一个过滤器链来处理每个请求。调用异常解析器的代码是这个链中的一个过滤器,但它靠近链的末端。因此,如果在异常解析器调用过滤器之前过滤器中的某处发生异常,我的解析器将永远不会被调用。
I am guessing you suffer from something similar here, where envelope parse errors happen before the exception resolver invoking filter. If that is the case, you will have to resort to some other way of handling those exceptions, for example a vanilla servlet filter.
我猜您在这里遇到了类似的问题,其中信封解析错误发生在异常解析器调用过滤器之前。如果是这种情况,您将不得不求助于其他处理这些异常的方法,例如 vanilla servlet 过滤器。
回答by Chiwai Chan
The solution I could come up with is to override the doService method in the MessageDispatcherServlet and capture the exception, then render a custom response. This might not be the best solution for you, but it works for me, hope this helps!
我能想到的解决方案是覆盖 MessageDispatcherServlet 中的 doService 方法并捕获异常,然后呈现自定义响应。这可能不是您的最佳解决方案,但它对我有用,希望对您有所帮助!
public class CustomMessageDispatcherServlet extends MessageDispatcherServlet {
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
super.doService(request, response);
} catch (Exception e) {
String error = e.getMessage();
String errorXml = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<SOAP-ENV:Header/>" +
"<SOAP-ENV:Body>" +
"<SOAP-ENV:Fault>" +
"<faultcode>SOAP-ENV:Client</faultcode>" +
"<faultstring xml:lang=\"en\"></faultstring>" + error +
"</SOAP-ENV:Fault>" +
"</SOAP-ENV:Body>" +
"</SOAP-ENV:Envelope>";
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("text/xml");
response.getWriter().write(errorXml);
response.getWriter().flush();
}
}
}
}
You might want to catch only the exceptions you want to handle.
您可能只想捕获要处理的异常。
Replace org.springframework.ws.transport.http.MessageDispatcherServlet with your CustomMessageDispatcherServlet in the web.xml file.
将 org.springframework.ws.transport.http.MessageDispatcherServlet 替换为 web.xml 文件中的 CustomMessageDispatcherServlet。
<servlet>
<servlet-name>web-services</servlet-name>
<servlet-class>CustomMessageDispatcherServlet</servlet-class>
</servlet>
回答by Stepan Pogosyan
In the latest Spring WS version you can use custom webservice message listener
在最新的 Spring WS 版本中,您可以使用自定义 webservice 消息侦听器
public class CustomWebServiceMessageListener extends WebServiceMessageListener {
private static final Logger LOG = LoggerFactory.getLogger(CustomWebServiceMessageListener.class);
@Override
public void onMessage(Message message, Session session) throws JMSException {
try {
this.handleMessage(message, session);
} catch (JmsTransportException jmsTransportException) {
LOG.error(jmsTransportException.getMessage(), jmsTransportException);
} catch (Exception e) {
JMSException jmsException = new JMSException(e.getMessage());
jmsException.setLinkedException(e);
LOG.error(e.getMessage(), e);
}
}
}
And inject it like this:
并像这样注入它:
<bean id="messageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="#{properties.concurrentListeners}"/>
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="queue"/>
<property name="messageListener" ref="messageListener"/>
<property name="sessionTransacted" value="true"/>
</bean>
<bean id="messageListener" class="com.yourproject.transport.CustomWebServiceMessageListener">
<property name="messageFactory" ref="saajMessageFactory"/>
<property name="messageReceiver" ref="messageDispatcher"/>
</bean>
回答by Thierry-Dimitri Roy
You have to "wire" (or "inject") the exception handler in your spring beans. I'm not sure which of your Spring bean actually needs the exception handler.
您必须在 spring bean 中“连接”(或“注入”)异常处理程序。我不确定您的哪个 Spring bean 实际上需要异常处理程序。
Personally, I use default-autowire="byName", which cause my exceptionHandler to be wired in my Controller class automatically. Your approach actually use manual wiring. So you need to find out which bean should actually use the exception handler. Have you tried (just on top of my head):
就我个人而言,我使用default-autowire="byName",这会导致我的 exceptionHandler 自动连接到我的 Controller 类中。您的方法实际上使用手动接线。所以你需要找出哪个 bean 应该实际使用异常处理程序。你有没有试过(就在我的头顶上):
<bean class="org.springframework.ws.server.endpoint.adapter.MarshallingMethodEndpointAdapter">
<constructor-arg ref="marshaller"/>
<property name="exceptionHandler" ref="exceptionHandler" />
</bean>
Or you could just add the autowired mechanism of Spring and let it wire the beans automatically. :)
或者,您可以添加 Spring 的自动装配机制,让它自动装配 bean。:)

