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
@RequestPayloadで xs: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自体への理解度が低いということに気付いた今日この頃。