LoginSignup
16

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-12-16

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16