spring-ws:让 EchoEndpoint 工作,而不是返回 404
简短版本:每当我尝试访问 Spring-WS SOAP EchoEndpoint 时,它都会响应 404。请帮忙,我花了两天时间试图让它正常工作。 :-I
更长的版本:我有一个 Spring 项目,我需要在其中创建 SOAP 服务,这些服务的行为、外观和感觉都与将被弃用的系统中的 SOAP 服务一样。因此,我不会使用编组,而是通过 XPath 分析信封内容,并以类似于旧系统的方式做出响应。
但在此之前我遇到了问题。我通过 DispatcherServlet 而不是 MessageDispatcherServlet 连接了 spring-ws,因为它与我的其余 WEB 应用程序 REST 服务位于同一空间。这是我的相关bean:
<context:component-scan base-package="com.saers.niklas.view"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="" p:suffix=".jsp"/>
<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
<property name="encoding" value="UTF-8"/>
<property name="contentType" value="application/json"/>
<property name="hijackSafe" value="true"/>
<property name="hijackSafePrefixPostFix"><value>(while(1);)</value></property>
</bean>
<aop:aspectj-autoproxy />
<sws:annotation-driven />
<context:component-scan base-package="com.saers.niklas.ws"/>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<bean class="com.saers.niklas.view.web.interceptors.AddObjectIDsToResponseInterceptor"/>
</property>
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="defaultHandler" ref="messageDispatcher"/>
</bean>
<bean id="messageDispatcher" class="org.springframework.ws.soap.server.SoapMessageDispatcher"/>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<bean class="org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter">
<property name="messageFactory">
<bean class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
我的端点看起来像这样
package com.saers.niklas.ws;
import javax.xml.transform.Source;
import org.w3c.dom.*;
import org.springframework.ws.server.endpoint.annotation.*;
import org.springframework.xml.transform.StringSource;
@Endpoint
public class EchoEndpoint {
public EchoEndpoint() {
System.err.println("XXNJSXX: EchoEndPoint");
}
@PayloadRoot(localPart="echoRequest", namespace="http://niklas.saers.com/DemoService")
public Source echo(@RequestPayload Element requestElement) {
return new StringSource("<x/>");
}
}
,我的测试看起来像这样:
package com.saers.niklas.ws;
import javax.xml.transform.*;
import junit.framework.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.xml.transform.*;
public class WSTest {
private static WebServiceTemplate template;
@BeforeClass
public static void setUp() {
template = new WebServiceTemplate();
template.setDefaultUri("http://localhost:8080/MyApp/ws/");
}
@Test
public void testEchoEndpoint() {
String xml = "<echoRequest xmlns=\"http://niklas.saers.com/DemoService\">Hello world</echoRequest>";
Source source = new StringSource(xml);
Result result = new StringResult();
try {
template.sendSourceAndReceiveToResult(source, result);
System.out.println(result);
} catch (Exception ex) {
ex.printStackTrace(System.err);
Assert.fail();
}
}
}
即使在启动应用程序时我在输出中得到“XXNJSXX:EchoEndPoint”,测试也会失败
org.springframework.ws.client.WebServiceTransportException: Not Found [404]
at org.springframework.ws.client.core.WebServiceTemplate.handleError(WebServiceTemplate.java:622)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:546)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:496)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:451)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:395)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:386)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:376)
at com.saers.niklas.ws.WSTest.testKommuneEndpoint(WSTest.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
,所以我知道它已初始化,可能只是未正确连接。每当我运行测试时,我还会看到类似这样的行:
2011-06-16 09:57:10 SaajSoapMessageFactory [INFO] Creating SAAJ 1.3 MessageFactory with SOAP 1.1 Protocol
我还运行了 WireShark 来确认请求是否按照我期望的方式进行,并且我确实得到了 404 返回。这是请求:
POST /MyApp/ws/ HTTP/1.1
Accept-Encoding: gzip
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml; charset=utf-8
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.6.0_26
Host: localhost:8080
Connection: keep-alive
Content-Length: 229
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><echoRequest xmlns="http://niklas.saers.com/DemoService">Hello world</echoRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
我缺少什么?
EDIT1:有人问我是否对 MessageDispatcherServlet 有同样的问题,所以我设置了一个,是的,看来我有。以下是对 web.xml 的补充:
<servlet>
<servlet-name>MDS</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:ws-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MDS</servlet-name>
<url-pattern>/soap2/*</url-pattern>
</servlet-mapping>
ws-servlet.xml 中的所有内容是:
<context:annotation-config />
<context:component-scan base-package="com.saers.niklas.ws"/>
<sws:annotation-driven />
调用 EchoRequest 时,我得到相同的 404:
POST /MyApp/soap2/ HTTP/1.1
Accept-Encoding: gzip
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml; charset=utf-8
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.6.0_26
Host: localhost:8080
Connection: keep-alive
Content-Length: 229
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><echoRequest xmlns="http://niklas.saers.com/DemoService">Hello world</echoRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
但这次我不确定这是否是因为我的 web.xml 已将 DispatcherServlet 配置为 /文件的更下方:
<servlet-mapping>
<servlet-name>MyApp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
干杯
尼克
The short version: My Spring-WS SOAP EchoEndpoint responds 404 whenever I try to access it. Please help, I've spent two days trying to get it to work correctly. :-I
Longer version: I've got a Spring project where I need to make SOAP services that act, look and feel as SOAP services from the system that will be deprecated. Therefore I'm not going to be using marshalling, but rather analyse the envelope contents via XPath and make the response in a way that looks like the old system.
But leading up to that I'm having problems. I have wired spring-ws up through DispatcherServlet instead of MessageDispatcherServlet because it lives in the same space as the rest of my WEB applications REST services. Here are my related beans:
<context:component-scan base-package="com.saers.niklas.view"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="" p:suffix=".jsp"/>
<bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
<property name="encoding" value="UTF-8"/>
<property name="contentType" value="application/json"/>
<property name="hijackSafe" value="true"/>
<property name="hijackSafePrefixPostFix"><value>(while(1);)</value></property>
</bean>
<aop:aspectj-autoproxy />
<sws:annotation-driven />
<context:component-scan base-package="com.saers.niklas.ws"/>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<bean class="com.saers.niklas.view.web.interceptors.AddObjectIDsToResponseInterceptor"/>
</property>
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="defaultHandler" ref="messageDispatcher"/>
</bean>
<bean id="messageDispatcher" class="org.springframework.ws.soap.server.SoapMessageDispatcher"/>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<bean class="org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter">
<property name="messageFactory">
<bean class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
My endpoint looks like this
package com.saers.niklas.ws;
import javax.xml.transform.Source;
import org.w3c.dom.*;
import org.springframework.ws.server.endpoint.annotation.*;
import org.springframework.xml.transform.StringSource;
@Endpoint
public class EchoEndpoint {
public EchoEndpoint() {
System.err.println("XXNJSXX: EchoEndPoint");
}
@PayloadRoot(localPart="echoRequest", namespace="http://niklas.saers.com/DemoService")
public Source echo(@RequestPayload Element requestElement) {
return new StringSource("<x/>");
}
}
and my test looks like this:
package com.saers.niklas.ws;
import javax.xml.transform.*;
import junit.framework.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.xml.transform.*;
public class WSTest {
private static WebServiceTemplate template;
@BeforeClass
public static void setUp() {
template = new WebServiceTemplate();
template.setDefaultUri("http://localhost:8080/MyApp/ws/");
}
@Test
public void testEchoEndpoint() {
String xml = "<echoRequest xmlns=\"http://niklas.saers.com/DemoService\">Hello world</echoRequest>";
Source source = new StringSource(xml);
Result result = new StringResult();
try {
template.sendSourceAndReceiveToResult(source, result);
System.out.println(result);
} catch (Exception ex) {
ex.printStackTrace(System.err);
Assert.fail();
}
}
}
The test fails with
org.springframework.ws.client.WebServiceTransportException: Not Found [404]
at org.springframework.ws.client.core.WebServiceTemplate.handleError(WebServiceTemplate.java:622)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:546)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:496)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:451)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:395)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:386)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:376)
at com.saers.niklas.ws.WSTest.testKommuneEndpoint(WSTest.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
even though I get "XXNJSXX: EchoEndPoint" in the output when I start the application, so I know that it is initialized, probably just not hooked up correctly. Whenever I run my test I also see a line like:
2011-06-16 09:57:10 SaajSoapMessageFactory [INFO] Creating SAAJ 1.3 MessageFactory with SOAP 1.1 Protocol
I've also run WireShark to confirm that the request is going through exactly the way I expect it, and I really get a 404 back. Here is the request:
POST /MyApp/ws/ HTTP/1.1
Accept-Encoding: gzip
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml; charset=utf-8
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.6.0_26
Host: localhost:8080
Connection: keep-alive
Content-Length: 229
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><echoRequest xmlns="http://niklas.saers.com/DemoService">Hello world</echoRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
What am I missing?
EDIT1: I was asked if I had the same problem with MessageDispatcherServlet, so I've set one up and yes, it seems I do. Here is the addition to web.xml:
<servlet>
<servlet-name>MDS</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:ws-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MDS</servlet-name>
<url-pattern>/soap2/*</url-pattern>
</servlet-mapping>
All that's in ws-servlet.xml is:
<context:annotation-config />
<context:component-scan base-package="com.saers.niklas.ws"/>
<sws:annotation-driven />
I get the same 404 when calling the EchoRequest:
POST /MyApp/soap2/ HTTP/1.1
Accept-Encoding: gzip
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml; charset=utf-8
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.6.0_26
Host: localhost:8080
Connection: keep-alive
Content-Length: 229
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><echoRequest xmlns="http://niklas.saers.com/DemoService">Hello world</echoRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>
But this time I'm not sure if that's because my web.xml has configured with DispatcherServlet to / further down in the file:
<servlet-mapping>
<servlet-name>MyApp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Cheers
Nik
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以尝试使用普通的
MessageDispatcherServlet
(按照此处推荐的 http://forum.springsource.org/showthread.php?39673-Spring-WS-in-a-normal-spring-dispatcher-servlet虽然那是旧线程)?当我需要来自同一个 web 应用程序的 HTML 和 WS 响应时,这对我有用。如果您将公共 bean 提取到单独的 XML 配置文件中,那么在两个调度程序之间共享 bean 就很简单。另外,您似乎正在使用类路径扫描,这使得它变得更加容易。您可以按照此处的说明进行操作 http://springtips.blogspot .com/2007/06/using-shared-parent-application-context.html 共享 singleton 实例以及 bean 的配置。PS 测试代码中不需要
,只需让测试方法抛出异常即可。您仍然会知道测试需要修复,并且在 Eclipse/Junit 中您将获得更好的堆栈跟踪。
Can you try using a normal
MessageDispatcherServlet
instead (as recommended here http://forum.springsource.org/showthread.php?39673-Spring-WS-in-a-normal-spring-dispatcher-servlet though that's an old thread)? That's worked for me when I need both HTML and WS responses from the same webapp. It's simple to share beans between the two dispatchers if you pull out the common beans into a separate XML config file. Plus you appear to be using classpath scanning which makes it even easier. You can follow the instructions here http://springtips.blogspot.com/2007/06/using-shared-parent-application-context.html to share the singelton instances as well as the configuration of your beans.PS There's no need for
in test code, just make the test method throw Exception. You'll still know the test needs fixing, and in Eclipse/Junit you'll get a nicer stack trace.
就我而言,解决方案是注意 URI 中的大小写。我的名称全部是小写,但网络服务需要一个驼峰命名法的操作名称。
In my case, the solution was to pay attention to the case in the URI. I had it in all lower case, but the webservice was expecting a CamelCase action name.