WAS LibertyでJAX-WSによるSOAPクライアントを実装するために参照したオンライン・マニュアル

# はじめに
2020年にJAX-WSでSOAP通信の実装をするとは思いもしなかったのですが、当初はアプリケーション・サーバー（WebSphere Application Server Liberty）のオンライン・マニュアル（IBM Knowledge Center）を参照すればすぐに実装できると思っていました。しかし、始めてみると、オンライン・マニュアルの適切なページになかなか辿り着けず苦労したので、参照したオンライン・マニュアル情報を整理して記録として残しておくことにしました。

# 目的

本投稿の目的は、「以下のようなWebサービス・クライアントを実装する時に参照すべきオンライン・マニュアル（IBM Knowledge Center）情報を整理すること」とします。カッコ内の難易度は個人的な感覚によるものです。

- JAX-WSによるSOAPクライアント（難易度：低）
- HTTPプロキシー経由でSOAPリクエストを送信（難易度：中）
- WS-Security対応（タイムスタンプの付加と署名）（難易度：高）

# 環境
動作確認に使用した環境は以下のとおりです。

- IBM WebSphere Application Server Liberty 19.0.0.12(およびOpen Liberty 20.0.0.1)
- Java 8

**準備作業**
今回実装したかったのはSOAPクライアントの方でしたが、テスト用のSOAP Webサービスが必要なので、まずはPOJOクラス（Hello1.java）からEclipseプラグインでWebサービス（Hello1Service）を生成しています。

# オンライン・マニュアル参照箇所
上記「目的」に記載したサンプル・アプリを実装するにあたって参照すべきオンライン・マニュアルのページを以下に示します。

## JAX-WSによるSOAPクライアントの実装
上記準備作業の過程で生成されたWSDLからEclipseプラグインでSOAPクライアントを生成しました。これは難なくできました。一応、オンライン・マニュアルの参照先は下記になります。

\:blue_book: **WAS Libertyオンライン・マニュアルの参照先**
[Liberty: JAX-WS クライアント・アプリケーションの実装](https://www.ibm.com/support/knowledgecenter/ja/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/rwlp_jaxws_client.html)

上記オンライン・マニュアルにクライアントのプログラミング・モデルと開発手順が説明されています。開発手順の説明としては、「WSDLを入手し、WSDLからwsimportコマンドでJAX-WSクライアントを生成して、これを呼び出すアプリを実装してください。」といった内容が記載されているだけです。

## HTTPプロキシー経由でSOAPリクエストを送信する実装
これも難なくできると思っていたのですが、オンライン・マニュアルの下記ページに辿り着くまで時間がかっかってしまいました。WebSphere Application Server traditionalのオンライン・マニュアルに記載されている方法ではうまくいかないので要注意（WAS LibertyのオンラインマニュアルにはWAS traditionalのオンラインマニュアルへの参照リンクが時々あるのですが、参照すべき範囲を超えてWAS traditionalのオンラインマニュアルのリンクを辿ってしまうとWAS Libertyでは有効でない機能や仕様を利用可能なものと誤認してしまうので要注意です）。

\:blue_book: **WAS Libertyオンライン・マニュアルの参照先**
[HTTP コンジット・クライアント・プロパティーおよびユーザー・カスタム・プロパティーの使用可能化](https://www.ibm.com/support/knowledgecenter/ja/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_dep_jaxws_http_conduit.html)

**ポイント1**
WebContent/WEBINF/ibm-ws-bnd.xmlにプロキシー・サーバー名(ProxyServer)とプロキシー・サーバーのポート番号(ProxyPort)を指定します。ちなみに8888はFiddlerのポート番号です。FiddlerをプロキシーにすることでSOAP通信の送受信データをFiddlerで確認できます。

```ibm-ws-bnd.xml
<?xml version="1.0" encoding="UTF-8"?>
<webservices-bnd xmlns="http://websphere.ibm.com/xml/ns/javaee"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ws-bnd_1_0.xsd"
		version="1.0">
	<!-- POJO service reference binding-->
	<service-ref name="service/Hello1Service">
		<properties http.conduit.client.ProxyServer="localhost"
					http.conduit.client.ProxyServerPort="8888" />
	</service-ref>
</webservices-bnd>

```
**ポイント2**
クライアント側のサービス・オブジェクトは、newでポート・プロキシーを生成するのではなく、`@WebServiceRef`アノテーションでインジェクトする必要があります。

```java:クライアントのJavaコード
	@WebServiceRef(name="service/Hello1Service", wsdlLocation ="/wsdl/Hello1Service.wsdl")
    private Hello1Service service;
```

## WS-Security対応（タイムスタンプの付加と署名）

難易度が高かったのはWS-Security対応です。今回WS-Security対応としてやりたかったことは、「タイムスタンプの付加」と「付加したタイムスタンプおよびSOAP Bodyに対するX.509証明書による署名」です。まず、何から調べたらよいのか解らずオンライン・マニュアルを検索・乱読したのですが、整理すると以下の順に読み進めていくのがお勧めです。

### WS-Security適用の全体像を掴む
WS-Security適用の全体像を掴むために、まず以下のトピックを読みます。

\:blue_book: **WAS Libertyオンライン・マニュアルの参照先**
[WS-Security ポリシーを使用した Web サービスの保護](https://www.ibm.com/support/knowledgecenter/ja/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_wssec_securing.html)

上記を読んで以下を理解してください。

* タイムスタンプの付加や署名といったセキュリティ・ポリシーをWS-SecurityPolicyの作法でWSDLに定義する（セキュリティー・ポリシーは添付ファイルとしてWSDLから分離することも可能。具体的な方法は後述。）
* 署名に使用する証明書を保管する鍵ストアが必要
* 鍵ストアにアクセスするためのパスワードを提供するために**パスワード・コールバック・ハンドラー**というモジュールの開発が必要
* パスワード・コールバック・ハンドラーはWAS Libertyにユーザー・フィーチャーとして追加
* WAS Libertyのフィーチャーとして``<feature>wsSecurity-1.1</feature>``を追加
* WAS Libertyに``<wsSecurityProvider>``(Webサービス側)または``<wsSecurityClient``(クライアント側)で鍵ストア情報とパスワード・コールバック・ハンドラー情報を登録

上記を理解したら次は実装作業になりますが、以下の2点を作ることになります。

* WS-SecurityPolicyに従ったセキュリティー・ポリシーの定義
* パスワード・コールバック・ハンドラー

必要に応じて（セキュリティー・ポリシーの定義をWSDL内に記述できない場合）以下を作成します。

* ポリシー添付ファイル


### WS-SecurityPolicyのテンプレート
よく使われるシナリオについてはWS-SecurityPolicyのテンプレートが提供されています。
下記の中から要件に合ったものを選択しカスタマイズして使用できます。

\:blue_book: **WAS Libertyオンライン・マニュアルの参照先**
[WS-SecurityPolicyおよびテンプレート](https://www.ibm.com/support/knowledgecenter/ja/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/cwlp_wssec_templates.html)

私の場合は、上記テンプレートの存在を知らなかったため[X.509 トークンを使用した Web サービスの保護](https://www.ibm.com/support/knowledgecenter/ja/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/cwlp_wssec_x509.html)の記載されていたサンプルをコピーしてカスタマイズしました。


### パスワード・コールバック・ハンドラーの実装
パスワード・コールバック・ハンドラーは、WAS Libertyのランタイム環境が鍵ストア内の証明書にアクセスするためのパスワードを提供するモジュールであり、WAS Libertyのユーザー・フィーチャーとして登録して使います。
下記を参照し、サンプルをカスタマイズして実装します。

\:blue_book: **WAS Libertyオンライン・マニュアルの参照先**
[WS-Security 用のパスワード・コールバック・ハンドラーの開発](https://www.ibm.com/support/knowledgecenter/ja/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_wssec_callbackhandler.html)

**注意点**
上記オンラインマニュアルに記載されているパスワード・コールバック・ハンドラーをコンパイルしようとすると下記import文がエラーになります。

```java:
import org.apache.ws.security.WSPasswordCallback;
```
私の場合はWindows 10環境でOpen Libertyを使っていたので、下記ランタイム用jarをビルドパスに追加して解決しました。

```
C:\openliberty-20.0.0.1\wlp\lib\com.ibm.ws.org.apache.ws.security.wss4j.1.6.7_1.0.36.jar
```


## ポリシー添付ファイルの利用

ここまでに登場したオンライン・マニュアルのサンプルでは、セキュリティー・ポリシーの定義をWSDLに記述していましたが、WSDLを編集できない場合や管理上の観点から編集することが望ましくない場合があります。そのような場合は、セキュリティー・ポリシーをポリシー添付ファイルに記述する方法を選択できます。
下記オンライン・マニュアルで、ポリシーのバインド方法（ポリシーとWebサービスURLとの関連付け）、ポリシー添付ファイルのファイル名および配置場所を含めたポリシー添付ファイルの利用方法が確認できます。

\:blue_book: **WAS Libertyオンライン・マニュアルの参照先**
[ポリシー添付を介した Web サービス・ポリシーの定義](https://www.ibm.com/support/knowledgecenter/ja/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_dep_policyattach.html)

## その他
### 鍵ストア
鍵ストアを準備する必要がありますが、私はJDK付属のkeytoolで作成しました。

### Webサービス関連仕様の解説記事
Webサービス関連仕様を概要レベルで（あまり時間をかけずに）理解したい方は以下の記事に目を通すと良いでしょう。

■[WSDL 1.1 を理解してモデル化する](https://www.ibm.com/developerworks/jp/java/library/j-jws20/index.html?ca=drs-)
■[WS-Policy について理解する](https://www.ibm.com/developerworks/jp/java/library/j-jws18/index.html?ca=drs-)




以上です。