16
9

More than 5 years have passed since last update.

Java11でSOAP使いたいと言われた人に送る記事

Last updated at Posted at 2019-07-12

Java11のSOAPについて

JEP 320に従い、SOAP関連の資材がJavaSEから削除されました。(JakartaEEにお引越しするのかな?)
そのため、以下のコマンドが廃止されています。

  1. wsimport ・・・ WSDL情報を元に、クライアント資材を生成(インターフェイス、DTO)
  2. wsgen ・・・ 実装からWSDLを生成

SOAPサーバを新規に構築することはないと思いますが、業務システムだと、まだまだSOAPの受信は必要です。

削除されたのは、理由があるので仕方がないのですが、Java11でどうすれば良いのか、私はすごく困りました。
私と同じように困る人もいるので、問題解決の助力となるようにメモを残します。

Maven Pluginを利用したwsimprtの実行

wsimportがJavaSEから削除されましたが、jarはMaven Centralから取得することができます。
そのため、以下のdependencyを追加します。

<dependency>
    <groupId>com.sun.tools.ws</groupId>
    <artifactId>webservices-tools</artifactId>
    <version>1.6</version>
</dependency>

あとは、com.sun.tools.ws.WsImportをMaven Pluginの助けを借りて実行するだけです。
オプションについては、Java8などのwsimportのドキュメントを確認し、適時書き換えてください。

mvn installを実行すると、必要なインターフェイス、DTOが生成されます。

pom.xml
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>ws-generate-from-wsdl</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <configuration>
                            <executable>java</executable>
                            <addOutputToClasspath>true</addOutputToClasspath>
                            <longModulepath>false</longModulepath>
                            <arguments>
                     <!-- WindowsだとコメントがSJISになってしまうため、文字コードを指定 -->
                                <argument>-Dfile.encoding=UTF-8</argument>
                                <argument>-Dsun.jnu.encoding=UTF-8</argument>
                                <argument>-verbose</argument>
                                <argument>-classpath</argument>
                                <classpath/>
                                <argument>com.sun.tools.ws.WsImport</argument>
                                <argument>-extension</argument>
                                <argument>-Xnocompile</argument>
                                <argument>-d</argument>
                                <argument>${project.basedir}/src/main/java</argument>
                                <argument>-p</argument>
                                <argument>jp.co.hoge.soap.hello</argument>
                                <argument>${project.basedir}/src/main/resources/wsdl/HelloSoapService.wsdl</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>${project.basedir}/src/main/java</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

build-helper-maven-pluginは、コードの生成されたことをIDEに知らせるPluginになります。
IDEはファイルシステムと非同期となっているためです。

いちいちコマンドで実行するより、むしろあるべき姿になったきもしますね:grinning:

Spring JaxWebProxy を使用したSOAP通信

必要な資材が生成され、めでたしめでたし、、、としたいのですが、
Java EE のコードを書くのはつらいです。(主観ですが)

調べてみると、Spring JaxWebProxyというのがあるのですが、
XMLで記載するサンプルばかりで、環境別にURLを切替できなくて不便だなと感じました。

戻り値がObjectなのが、かなりイケてないですが、
以下の感じでJaxWsPortProxyFactoryBeanの力を借りて、SOAPのClientをインスタンス化します。

@Configuration
public class HelloWebServiceConfig {

    /**
     * HelloWebServiceProxyのインスタンスを生成する
     *
     * @param wsdlUrl http://localhost:8080/axis2/services?wsdl
     * @return Object JaxWsPortProxyFactoryBean
     * @throws MalformedURLException
     */
    @Bean
    public Object createHelloWebServiceProxyInstance(String wsdlUrl)  {

        JaxWsPortProxyFactoryBean bean = new JaxWsPortProxyFactoryBean();

        bean.setServiceInterface(HelloWebService.class);
        bean.setServiceName("helloWebService"); // WSDLに記載されているサービス名と同じものを記載する。省略不可。
        try {
            bean.setWsdlDocumentUrl(new URL(wsdlUrl));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        return bean;
    }
}

実際にSOAPを実行する場合のサンプルは下記のとおりです。

// SOAP Clientのインスタンス化
ApplicationContext ctx = new AnnotationConfigApplicationContext(HelloWebServiceConfig.class);
HelloWebService soapClient = (HelloWebService)ctx.getBean("createHelloWebServiceProxyInstance", "http://localhost:8080/axis2/services?wsdl");

// 実行サンプル
HelloWebServiceResponseDTO response = soapClient.execute(helloWebServiceRequestDTO);

SpringFrameworkの力を借りると、すっきりしたコードになりますね:grin:

SOAP通信実現のために追加したパッケージは、下記のとおりです。
( 不要なパッケージが含まれているかもしれません。ご指摘頂けると助かります。)

        <!-- JaxWsPortProxyFactoryBean / SOAP通信実現のため  -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.1.8.RELEASE</version>
        </dependency>

        <!-- xml.bind module / SOAP通信実現のため  -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>

        <!-- xml.ws module / SOAP通信実現のため -->
        <dependency>
            <groupId>javax.xml.ws</groupId>
            <artifactId>jaxws-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-rt</artifactId>
            <version>2.3.0</version>
        </dependency>
        <!-- javax.activation / SOAP通信実現のため -->
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency

まとめ

Java11でws系のパッケージが消えたということで、最初は不安ばかりでしたが、簡単なコードで実現することが出来ました。
もしかしたら、gRPCよりは、実は扱いやすいプロトコルなのもしれません。

16
9
0

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
9