Edited at

Spring WS(WebService)でSOAPリクエストを受け取るための設定

More than 3 years have passed since last update.

Spring WS (WebService)を使ったSOAPで死ぬほどハマったのでまとめておきます。


Spring WS (2.2.2)でSOAPリクエストを受け取る環境をつくる。

以下のような構成の既存WEBアプリケーションへの組込みです。


  • Spring Framework 3.2.8

  • Spring MVC

  • Java7

  • Tomcat7


pom.xml

依存関係を追加

<dependency>

<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>


web.xml

{context-root}/ws/* のアクセスがMessageDispatcherServletに流れるようになる。

<servlet>

<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/META-INF/spring-ws-servlet.xml</param-value>
</init-param>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>*.wsdl</url-pattern>
</servlet-mapping>


spring-ws-servlet.xml

WEB-INF配下にwsdlファイルを配備しておく

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sws="http://www.springframework.org/schema/web-services"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd"
>

<context:component-scan base-package="jp.xxx.*" />
<sws:annotation-driven />
<sws:static-wsdl id="hoge" location="/WEB-INF/hoge.wsdl"/>
</beans>


wsdl/xsdからjavaクラスを生成

wsdl/xsdが用意できる場合は便利。

mavenを利用し、pom.xml に以下を記述する。


  • wsdlの場合

WEB-INF配下のwsdlファイル参照を想定

<plugin>

<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
<configuration>
<wsdl>true</wsdl>
<xmlschema>false</xmlschema>
<schemaDirectory>${basedir}/src/main/webapp/WEB-INF</schemaDirectory>
<schemaFiles>hoge.wsdl</schemaFiles>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>


  • xsdの場合

resource配下のxsdファイルの参照を想定

<plugin>

<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
<configuration>
<schemaDirectory>${basedir}/src/main/resource/xsd</schemaDirectory>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>

mavenでタスク clean jaxb2:xjc を実行すると、wsdl/xsd の記述に基づいて

${basedir}/src/main/java配下にjavaソースが出力される。

(IDEの機能でも同じことができるかも。)


Endpointの作成

spring-ws-servlet.xmlに記載した

component-scanの対象パッケージに作成する。

HogeRequest/HogeResponseが上述のmavenタスクで自動生成されたクラス。

@Endpoint

public class HogeEndPoint {
private static final String NAMESPACE_URI = "http://example.com/"; // wsdlのtargetNamespaceとあわせる

@PayloadRoot(localPart = "Hoge", namespace = NAMESPACE_URI)
@ResponsePayload
public JAXBElement<HogeResponse> hoge(@RequestPayload JAXBElement<HogeRequest> request) {
return new JAXBElement<>(
new QName(NAMESPACE_URI, "HogeResponse"),
HogeResponse.class,
new HogeResponse()
);
}
}


@RequestPayload 内のフィールドをunmarshal

@RequestPayloadxs:anyType を Object型で受け取った場合、

そこからさらにunmarshalする場合は以下手順でいけた。

Node node = (Node)request.getValue().getPiyo();

JAXBContext jaxb = JAXBContext.newInstance(Piyo.class);
JAXBElement<Piyo> piyo = jaxb.createBinder().unmarshal(node.getFirstChild(), Piyo.class);


ログ出力

logbackを利用していますが、

ログの出力レベルをtraceまで許可してやると、


  • どこまでSOAPリクエストが届いてるのか?

  • EndPointがちゃんとマッピングされてるのか?

などの情報も確認できるため、トラぶったときにはオススメ。



まとめてみると大した記述量でもないですね・・・

ほとんどRESTでしか通信することが無かったので、

SOAP自体への理解度が低いということに気付いた今日この頃。