Java11のSOAPについて
JEP 320に従い、SOAP関連の資材がJavaSEから削除されました。(JakartaEEにお引越しするのかな?)
そのため、以下のコマンドが廃止されています。
- wsimport ・・・ WSDL情報を元に、クライアント資材を生成(インターフェイス、DTO)
- 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が生成されます。
<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はファイルシステムと非同期となっているためです。
いちいちコマンドで実行するより、むしろあるべき姿になったきもしますね
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の力を借りると、すっきりしたコードになりますね
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よりは、実は扱いやすいプロトコルなのもしれません。