spring-ws: заставить EchoEndpoint работать, а не возвращать 404 - PullRequest
2 голосов
/ 16 июня 2011

Короткая версия: Мой Spring-WS SOAP EchoEndpoint отвечает 404 всякий раз, когда я пытаюсь получить к нему доступ. Пожалуйста, помогите, я провел два дня, пытаясь заставить его работать правильно. : -I

Более длинная версия: у меня есть проект Spring, в котором мне нужно сделать SOAP-сервисы, которые действуют, выглядят и воспринимаются как SOAP-сервисы из системы, которые будут устаревшими. Поэтому я не собираюсь использовать маршаллинг, а скорее проанализировать содержимое конверта через XPath и сделать ответ таким образом, который выглядит как старая система.

Но в связи с этим у меня проблемы. Spring-ws я подключил через DispatcherServlet вместо MessageDispatcherServlet, потому что он находится в том же пространстве, что и остальные REST-сервисы моих веб-приложений. Вот мои родственные бобы:

<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();
        }
    }
}

Тест не пройден с

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)

, даже когда я получаю «XXNJSXX: EchoEndPoint» в выводе при запуске приложения, поэтому я знаю, что оно инициализировано, возможно, просто неправильно подключено. Всякий раз, когда я запускаю тест, я также вижу строку вроде:

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

Я получаю те же 404 при вызове 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>

Но на этот раз я не уверен, так ли это, потому что мой web.xml настроил DispatcherServlet для / ниже в файле:

<servlet-mapping>
  <servlet-name>MyApp</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

Приветствия

Nik

Ответы [ 2 ]

2 голосов
/ 16 июня 2011

Можете ли вы попробовать вместо обычного MessageDispatcherServlet (как рекомендовано здесь http://forum.springsource.org/showthread.php?39673-Spring-WS-in-a-normal-spring-dispatcher-servlet, хотя это старая ветка)? Это сработало для меня, когда мне нужны ответы HTML и WS из одного и того же веб-приложения. Распределить bean-компоненты между двумя диспетчерами просто, если вы извлекаете общие bean-компоненты в отдельный XML-файл конфигурации. Кроме того, вы, похоже, используете сканирование пути к классам, что делает его еще проще. Вы можете следовать инструкциям здесь http://springtips.blogspot.com/2007/06/using-shared-parent-application-context.html, чтобы поделиться экземплярами Singelton, а также конфигурацией ваших бинов.

PS Нет необходимости в

} catch (Exception ex) {
            ex.printStackTrace(System.err);
            Assert.fail();
        }

в тестовом коде, просто заставьте тестовый метод генерировать Exception. Вы по-прежнему будете знать, что тест нуждается в исправлении, а в Eclipse / Junit вы получите более качественную трассировку стека.

0 голосов
/ 25 июня 2013

В моем случае решением было обратить внимание на случай в URI. У меня было все в нижнем регистре, но веб-сервис ожидал имя действия CamelCase.

...