1.2.14. WS-ReliableMessaging

1.2.14.1. 事前準備

ここでは永続化のために使用するデータベースの準備をします。

データベースの種別により手順が異なります。使用するデータベースに合わせてデータベースがOracleの場合あるいはデータベースがDerbyの場合を参照してください。
データベースがOracleの場合
  1. データベース作成とデータベースのユーザ登録

    データベースの作成とデータベースのユーザ登録を行います。
    SYSユーザで以下のSQL文を実行します。

    SQL> CREATE TABLESPACE <テーブルスペース名> 
       2 LOGGING 
       3 DATAFILE <データファイル名> SIZE <データファイルサイズ>
       4 AUTOEXTEND ON
       5 EXTENT MANAGEMENT LOCAL
       6 SEGMENT SPACE MANAGEMENT AUTO;
    SQL>CREATE USER <ユーザ名>  PROFILE "DEFAULT" 
       2 IDENTIFIED BY <パスワード> DEFAULT TABLESPACE <テーブルスペース名> 
       3 ACCOUNT UNLOCK;
    SQL>GRANT CONNECT TO <ユーザ名>;
    SQL>GRANT DBA, CREATE SESSION, RESOURCE TO <ユーザ名>;
    	

    Memo
    SQL文を実行するときには、データベース管理システムに付属するコマンドを使用します(例としてsqlplusを使用する場合は"sqlplus sys/<パスワード> as SYSDBA"のようにデータベースへ接続します)

  2. JDBCドライバのコピー

    操作対象のドメインが起動されているときは、一旦終了します。
    JDBCドライバライブラリ( <ORACLE_HOME>/jdbc/lib配下にあるojdbc6.jar、orai18n.jar)を、<WebOTX_DIR>/domains/<ドメイン名>/lib/extへコピーします。
    コピー後、操作対象のドメインを起動します。

  3. データソースの登録

    WebOTX統合運用管理ツールを用いてJDBCデータソースを登録します。統合運用管理ツールの画面上で操作対象のドメインリソースをクリックします。次に「JDBCデータソース」を右クリックして「JDBCデータソースの登録」を選択します。「リソースの操作」画面が開きます。この画面を用いてJDBCデータソースを登録します。このとき、以下の点を確認してから登録します。

    「一般」タブにおいて、次のように設定します。


    図1.2.14.1-1

    「拡張」タブの「JTAのトランザクション毎に1つの物理コネクションを使用するかどうか」をチェックします。


    図1.2.14.1-2

  4. 初期設定

    WebOTX統合運用管理ツールを用いて設定します。統合運用管理ツールの画面上で操作対象のドメインアプリケーションサーバWebサービスをクリックします。次に「WS-ReliableMessaging」をクリックして、WS-ReliableMessagingの属性設定画面が表示されます。この画面でを以下の点を確認してから更新します。

    「JDBCデータソースのJNDI名」は前述のデータソースの登録で指定したJNDI名を指定します。
    複数ドメインから1つのデータベースを共有して使う場合にドメイン毎にデータベースのテーブルを分けるため、「テーブル名プレフィックス」でテーブル名プレフィックスを指定します。

    設定後、操作対象のドメインを再起動します。


    図1.2.14.1-3

  5. テーブルの作成

    WebOTX統合運用管理ツールを用いてデータベースのテーブルを作成します。統合運用管理ツールの画面上で操作対象のドメインアプリケーションサーバWebサービスをクリックします。次に「WS-ReliableMessaging」を右クリックして「テーブルの作成」を選択します。「テーブルの作成」画面が開きます。この画面で「実行」ボタンをクリックしてテーブルを作成します。


    図1.2.14.1-4

データベースがDerbyの場合
  1. データベース作成とデータベースのユーザ登録

    データベースの作成とデータベースのユーザ登録を行います。
    Derbyに付属するijツールで以下のコマンドを実行します。

    ij>CONNECT 'jdbc:derby://localhost:1527/<データベース名>;create=true;user=<ユーザ名>;password=<パスワード>';
    
  2. JDBCドライバのコピー

    操作対象のドメインが起動されているときは、一旦終了します。
    JDBCドライバライブラリ(<DERBY_HOME>/lib配下にあるderbyclient.jar)を、<WebOTX_DIR>/domains/<ドメイン名>/lib/extへコピーします。
    コピー後、操作対象のドメインを起動します。

  3. データソースの登録

    WebOTX統合運用管理ツールを用いてJDBCデータソースを登録します。統合運用管理ツールの画面上で操作対象のドメインリソースをクリックします。次に「JDBCデータソース」を右クリックして「JDBCデータソースの登録」を選択します。「リソースの操作」画面が開きます。この画面を用いてJDBCデータソースを登録します。このとき、以下の点を確認してから登録します。

    「一般」タブにおいて、次のように設定します。


    図1.2.14.1-5

    「拡張」タブの「JTAのトランザクション毎に1つの物理コネクションを使用するかどうか」をチェックします。


    図1.2.14.1-6

  4. 初期設定

    WebOTX統合運用管理ツールを用いて設定します。統合運用管理ツールの画面上で操作対象のドメインアプリケーションサーバWebサービスをクリックします。次に「WS-ReliableMessaging」をクリックして、WS-ReliableMessagingの属性設定画面が表示されます。この画面でを以下の点を確認してから更新します。

    「JDBCデータソースのJNDI名」は前述のデータソースの登録で指定したJNDI名を指定します。
    複数ドメインから1つのデータベースを共有して使う場合、ドメイン毎にデータベースのテーブルを分けるため、「テーブル名プレフィックス」でテーブル名プレフィックスを指定します。

    設定後、操作対象のドメインを再起動します。


    図1.2.14.1-7

  5. テーブルの作成

    WebOTX統合運用管理ツールを用いてデータベースのテーブルを作成します。統合運用管理ツールの画面上で操作対象のドメインアプリケーションサーバWebサービスをクリックします。次に「WS-ReliableMessaging」を右クリックして「テーブルの作成」を選択します。「テーブルの作成」画面が開きます。この画面で「実行」ボタンをクリックしてテーブルを作成します。


    図1.2.14.1-8

1.2.14.2. Webサービスの作成

Webサービスの作成方法を説明します。
WS-ReliableMessaging の設定を定義する方法は、アプリケーションにnec-jaxws.xmlを含めているかどうかにより変わります。
どちらの方法でも、以下の手順でPolicyを追加することで、同様にWS-RMの動作を定義できます。

Memo
nec-jaxws.xmlが存在しない場合、Webサービスのアノテーション定義をもとにWSDLが生成されるため、WSDLから独立した設定ファイルを作成する必要があります。設定ファイルの内容はWebサービスのWSDL定義にポリシー・アサーションを追加したものになります。
設定ファイルの名称は以下のようにします。
  wsit-<Webサービス実装クラス名>.xml
たとえばcom.nec.AddNumbersPortTypeImpl.classがWebサービス実装クラスであった場合、設定ファイル名は「wsit-com.nec.AddNumbersPortTypeImpl.xml」となります。 この設定ファイルはWEB-INF/classesなど、CLASSPATHのルートに配置してください。

JAX-WS準拠Webサービスの作成

JAX-WS準拠WebサービスのWSDLに、WS-RM Policyを追加することでWS-ReliableMessaging機能が有効になります。 JAX-WS準拠Webサービスの作成方法は、Webサービスの チュートリアルで説明しています。 新規作成、WSDLファイルから作成のどちらでも構いません。

WSDLファイルにWS-RM Policyを追加

WS-ReliableMessaging 機能を有効にするためには、WSDLファイルにWS-RM Policyの追加が必要です。
追加する内容は次のとおりです。

  1. WS-RM Policyで使用する名前空間を追加します。
  2. wsdl:definitions要素の子要素としてポリシー定義を追加します。
  3. wsdl:binding要素の子要素としてwsp:PolicyReference要素を追加して、ポリシーを参照します。

以下のように設定した場合のwsdl記載例を示します。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions targetNamespace="http://nec.webotx.com" name="webServiceService"
    ...
    <!--1.WS-RM Policyで使用する名前空間を追加します。-->
    xmlns:wsp="http://www.w3.org/ns/ws-policy"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
    xmlns:wsrm="http://docs.oasis-open.org/ws-rx/wsrmp/200702"
    ...
    <!--2.wsdl:definitions要素の子要素としてポリシー定義を追加します。-->
    <wsp:Policy wsu:Id="WebServiceServicePortBindingPolicy">
        <wsp:ExactlyOne>
            <wsp:All>
                <wsam:Addressing wsp:Optional="false"/>
                <wsrm:RMAssertion>
                    <wsp:Policy>
                        <wsrm:DeliveryAssurance>
                            <wsp:Policy>
                                <wsrm:InOrder/>
                                <wsrm:ExactlyOnce/>
                            </wsp:Policy>
                        </wsrm:DeliveryAssurance>
                    </wsp:Policy>
                </wsrm:RMAssertion>
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>
    ...
    <!--3.wsdl:binding要素の子要素としてwsp:PolicyReference要素を追加して、ポリシーを参照します。-->
    <binding name="WebServiceServicePortBinding" type="tns:WebServiceService">
        <wsp:PolicyReference URI="#WebServiceServicePortBindingPolicy"></wsp:PolicyReference>
        ...
    </binding>
    ...
</definitions>

太字の箇所は追加した内容です。WS-ReliableMessaging機能を利用する場合、<wsam:Addressing wsp:Optional="false"/>と<wsrm:RMAssertion>は必須です。

WS-RM Policyで使用する名前空間

WS-RM Policyで使用する名前空間は下記です。

表1.2.14.2-1
Prefix Namespace 説明
wsp http://www.w3.org/ns/ws-policy Web Services Policy 1.5
wsu http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd Web Services Utility Schema
wsam http://www.w3.org/2007/05/addressing/metadata WS-Addressing 1.0
wsrm http://docs.oasis-open.org/ws-rx/wsrmp/200702 Web Services Reliable Messaging Policy 1.2

ポリシー定義で利用可能なアサーション

ポリシー定義で利用可能なWS-RM Policyのアサーションは下記です。

表1.2.14.2-2
アサーション 説明 設定例
/wsrm:RMAssertion メッセージの送信時に、WS-ReliableMessagingが使用されなければならないことを指定する。 <wsrm:RMAssertion/>
/wsrm:RMAssertion
/wsp:Policy
/wsrm:SequenceSTR
WS-ReliableMessaging 機能が、CreateSequence メッセージにおいて wsse:SecurityTokenReference で参照されるトークンを使用することを定義する。wsrm:SequenceTransportSecurity とは同時に指定できない。 <wsrm:RMAssertion>
  <wsp:Policy>
    <wsrm:SequenceSTR/>
  </wsp:Policy>
</wsrm:RMAssertion>
/wsrm:RMAssertion
/wsp:Policy
/wsrm:SequenceTransportSecurity
WS-ReliableMessaging 機能が、CreateSequence メッセージをトランスポートレベルのセキュリティプロトコルにバインドして送受信することを定義する。トランスポート方法を指定するためのアサーション sp:TransportBinding と組み合わせて使用する必要がある。wsrm:SequenceSTR とは同時に指定できない。 <wsrm:RMAssertion>
  <wsp:Policy>
    <wsrm:SequenceTransportSecurity/>
  </wsp:Policy>
</wsrm:RMAssertion>
/wsrm:RMAssertion
/wsp:Policy
/wsrm:DeliveryAssurance
配信保証を有効にする。配信保証レベルはExactlyOnceとInOrderを設定できる。設定しない場合、配信保証レベルは ExactlyOnce が使用される。 <wsrm:RMAssertion>
  <wsp:Policy>
    <wsrm:DeliveryAssurance/>
  </wsp:Policy>
</wsrm:RMAssertion>
/wsrm:RMAssertion
/wsp:Policy
/wsrm:DeliveryAssurance
/wsp:Policy
/wsrm:ExactlyOnce
すべてのメッセージが必ず 1 回は重複なしで配信される。デフォルトではこの値が使用される。 <wsrm:RMAssertion>
  <wsp:Policy>
    <wsrm:DeliveryAssurance>
      <wsp:Policy>
        <wsp:ExactlyOnce/>
      <wsp:Policy/>
    <wsrm:DeliveryAssurance/>
  </wsp:Policy>
</wsrm:RMAssertion>
/wsrm:RMAssertion
/wsp:Policy
/wsrm:DeliveryAssurance
/wsp:Policy
/wsrm:InOrder
メッセージは送信された順序で配信される。この配信保証は上記の ExactlyOnceと組み合わせて指定できる。 <wsrm:RMAssertion>
  <wsp:Policy>
    <wsrm:DeliveryAssurance>
      <wsp:Policy>
        <wsp:InOrder/>
      <wsp:Policy/>
    <wsrm:DeliveryAssurance/>
  </wsp:Policy>
</wsrm:RMAssertion>

WebOTX独自のアサーション
WS-Policyにより設定できるアサーション

WSDLのポリシーに設定できるアサーションは、WS-RM Policyで定義しているアサーションの以外にWebOTX独自のアサーションもあります。

WebOTX独自のアサーションで利用する名前空間は以下の通りです。

表1.2.14.2-3
Prefix Namespace
wo92rmp http://nec.com/ws-rx/wsrmp/201312

WebOTX独自のアサーションについて説明します。

表1.2.14.2-4
アサーション 説明 設定例
/wo92rmp:RetransmissionConfig
/wo92rmp:Interval
クライアントがメッセージを送信してから再送するまでの間隔(ミリ秒単位)を指定する。デフォルト値は2000。 <wo92rmp:RetransmissionConfig>
  <wo92rmp:Interval Milliseconds="2000"/>
</wo92rmp:RetransmissionConfig>
/wo92rmp:RetransmissionConfig
/wo92rmp:Algorithm
再送間隔の調整に用いるアルゴリズムを指定する。指定できる値は以下の通り。
Constant:一定(デフォルト値)
Exponential:再送毎に待ち時間を増加
<wo92rmp:RetransmissionConfig>
  <wo92rmp:Algorithm>Exponentia
</wo92rmp:Algorithm>
</wo92rmp:RetransmissionConfig>
/wo92rmp:RetransmissionConfig
/wo92rmp:MaxRetries
クライアントからACKが返されることによって、メッセージは配送されたと判断される。一定時間でACKが受信されない時は、自動的に再送が行われる。あらかじめ設定された回数だけ、メッセージを再送する。この制限に達するまでACKの返信が得られない場合、通信エラーによりセッションが失敗しているとみなす。設定されない場合は無制限になる。 <wo92rmp:RetransmissionConfig>
  <wo92rmp:MaxRetries>10
</wo92rmp:MaxRetries>
</wo92rmp:RetransmissionConfig>
/wo92rmp:CloseSequenceTimeout ReliableMessaging セッションのクローズ時に、制御をブロックしてACKを待ち受ける時間(ミリ秒単位)を指定する。指定されたタイムアウト時間に達してもACKを受け取っていないメッセージがある場合、制御が返り、ACKを受け取っていないメッセージは失われる。デフォルト値は0。 <wo92rmp:CloseSequenceTimeout Milliseconds="0"/>
/wo92rmp:AckRequestInterval クライアントがサービスに連続してACKを送信する際の時間間隔(ミリ秒単位)を指定する。デフォルト値は2000。 <wo92rmp:AckRequestInterval Milliseconds="2000"/>
/wo92rmp:MaxConcurrentSessions Webサービスのエンドポイントが同時に受け入れる WS-ReliableMessaging セッションの数(InboundのReliableMessaging シーケンスに基づき測定)を指定する。設定されない場合は無制限になる。 <wo92rmp:MaxConcurrentSessions>10
</wo92rmp:MaxConcurrentSessions>
/wo92rmp:MaintenanceTaskPeriod WS-ReliableMessaging シーケンスのメンテナンスタスクの実行間隔(ミリ秒単位)を指定する。
メンテナンスタスクは以下の動作を行う。
  • アクティブでないシーケンスを終了し、デッドキューへ移動する。
  • 保存期間が過ぎたデッドキューを削除する。
デフォルト値は60000。
<wo92rmp:MaintenanceTaskPeriod Milliseconds="60000"/>
/wo92rmp:ExpiresTimeout クライアントとサービス間のタイムアウト時間を指定する。デフォルト値はP1D(1日)。
値はDuration文字表記で記述する。具体的な記述方法は、 http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#duration を参照。

記述例
P1D: 1日
P1M: 1ヶ月
P1Y: 1年
PT1H: 1時間
PT30M: 30分
PT60S: 60秒
これらを組み合わせた記述の指定も可能。
P1Y2M3DT4H50M20S: 1年2ヶ月3日4時間50分20秒
また、PT0Sは指定できない。
<wo92rmp:ExpiresTimeout>P2D
</wo92rmp:ExpiresTimeout>

以下のように設定した場合のWSDL記載例を示します。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions targetNamespace="http://nec.webotx.com" name="webServiceService"
    ...
    xmlns:wsp="http://www.w3.org/ns/ws-policy"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
    xmlns:wsrm="http://docs.oasis-open.org/ws-rx/wsrmp/200702"
    <!--WebOTX独自のアサーションで利用する名前空間を追加します。-->
    xmlns:wo92rmp="http://nec.com/ws-rx/wsrmp/201312" 
    ...
    <wsp:Policy wsu:Id="WebServiceServicePortBindingPolicy">
        <wsp:ExactlyOne>
            <wsp:All>
                <wsam:Addressing wsp:Optional="false"/>
                <wsrm:RMAssertion>
                    <wsp:Policy>
                        <wsrm:DeliveryAssurance>
                            <wsp:Policy>
                                <wsrm:InOrder/>
                            </wsp:Policy>
                        </wsrm:DeliveryAssurance>
                    </wsp:Policy>
                </wsrm:RMAssertion>
                <!---WebOTX独自のアサーションを追加します。-->
                <wo92rmp:RetransmissionConfig>
                    <wo92rmp:Algorithm>Exponentia</wo92rmp:Algorithm>
                </wo92rmp:RetransmissionConfig>
                <wo92rmp:ExpiresTimeout>P2D</wo92rmp:ExpiresTimeout>
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>
    ...
    <binding name="WebServiceServicePortBinding" type="tns:WebServiceService">
        <wsp:PolicyReference URI="#WebServiceServicePortBindingPolicy"></wsp:PolicyReference>
        ...
    </binding>
    ...
</definitions>

太字の箇所は追加した内容です。

1.2.14.3. Webサービスクライアントの作成

WS-ReliableMessaging機能を利用するWebサービスクライアントの作成方法はJAX-WSに準拠した Web サービスのクライアントの作成方法と同じです。クライアント側は、1.2.14.2. Webサービスの作成の手順で作成されたWSDLを参照することで動作します。 JAX-WS準拠Webサービスのクライアントの作成方法は、アプリケーション開発ガイド(Java EE)の 1.1.6. Webサービスクライアントの作成で説明しています。
ただし、以下の点を注意ください。

  1. WS-ReliableMessagingはJAX-WSの同期モードで呼び出してください。非同期モードには対応しておりません。
  2. Webサービスクライアントの実装クラスに、シーケンス終了処理の追加が必要になります。

シーケンス終了処理を追加する必要があり、例を次に示します。

package main;

import com.nec.webotx.webservice.xml.ws.Closeable;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        sample.hello.HelloService port = null;
        try {
            sample.hello.HelloService_Service service = new sample.hello.HelloService_Service();
            port = service.getHelloServicePort();
            java.lang.String arg0 = "Bob";
            java.lang.String result = port.sayHello(arg0);
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally { 
            if( port != null && port instanceof Closeable ) {
                ((Closeable)port).close();
            }
        }
    }
}