IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  SOA and Web services | Grid computing  >

WebSphere Studio を使用したステートフル Web サービスの実装とアクセス、パート 3

WS-Resource のプロパティーへのアクセス

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません

サンプルコード

原文はこちら

原文はこちら


レベル: 中級

Hidayatullah Shaikh (hshaikh@us.ibm.com), Senior Software Engineer, IBM 

2004年 6月 08日

Web Services Resource Framework では、Web サービスを使用して状態にアクセスするためのモデルが提案されています。WS-Resource Properties 仕様では、Web サービス・テクノロジーを使用して、ステートフルな資源に関連付けられたデータを照会および変更する方法が定義されています。これにより、WS-Resource に関連付けられたデータにクライアントがアクセスする際に利用できる標準手段が提供されます。この記事では、IBM® WebSphere® Studio Application Developer V5.1 によって WebSphere Application Server 環境で WS-Resource プロパティーを実装する方法について説明します。

WS-Resource Properties 仕様には、サービス・リクエスターが Web サービス・インターフェースを通じて、WS-Resource の状態の型と値を表示および修正するための手段が記述されています。WS-Resource の状態は、XML スキーマを使用した XML 資源プロパティー・ドキュメントとして表現されます。WS-Resource Properties 仕様では、資源のプロパティーの定義を Web サービス・インターフェースの一部として宣言するための手段が標準化されています。また、リクエスターが暗黙的資源インスタンスのプロパティー値を照会または更新できるようにするための、メッセージ交換の標準セットも定義されています。

この記事では、シンプルな計算機サービスの例を使用して、IBM WebSphere Application Server 環境で WS-Resource プロパティーを指定したり、アクセスしたりする方法を説明します。

対象読者

この記事は、J2EE テクノロジー、Web サービス、および WebSphere Application Server V5.1 に関する基本的な知識のある方を対象にしています。これらのテクノロジーに関する理解を深めたい場合は、この記事の『参考文献』に入門用資料が用意されているのでご利用ください。IBM developerWorks で入手できる資料を参照することもおすすめします。

このシリーズのパート 1 およびパート 2、「サービスを介して資源にアクセス」および「WS-Resources のライフサイクルの管理」を読み、記事で使用する計算機の例についても理解しておいてください。




上に戻る


サンプル・コードの内容と要件

この記事で引用されるサンプルは、WebSphere Studio Application Developer V5.1.1 GM 版で作成されたものです。これらのサンプルは、WebSphere Application Server V5.1 に組み込まれたテスト環境において単体でテストされました。サンプルの WSDL は tcpmon ユーティリティーを使用するように構成されています。このユーティリティーは、交換される SOAP メッセージの監視用として Apache Axis に付属しています。リスン・ポートをポート 81 (listenPort) に設定し、要求を 9080 のターゲット・ポート (targetPort) に転送するように、tcpmon ユーティリティーを構成してください。tcpmon の詳細については、この記事の『参考文献』を参照してください。

ファイル ws-statefulws3code.zip には、この記事に収録されたコード・サンプルが含まれています。このファイルは、この記事の最上部または最下部にある「Code」アイコンをクリックするとダウンロードすることができます。このファイルには、次のファイルが含まれます。

WASv5WSAExtensions.jar SOAP メッセージの WS-Addressing メッセージ情報ヘッダーの作成時やアクセス時に WebSphere Application Server V5.1 によって必要とされる、ユーティリティー・クラスが含まれた JAR ファイル。WS-Addressing のエンドポイント・リファレンスを操作するためのヘルパー・クラスも含まれています。これらのクラスは、WebSphere Studio アプリケーションでの用途に応じて構成することができます。
WASvsWSAExtensions-javadoc.zip ユーティリティー・クラスの javadoc。
CalculatorService.ear ステートフルな計算機サービス (サンプル)。計算機サービスを簡単に呼び出すことのできる Web アプリケーションが用意されています。



上に戻る


計算機サンプル

このシリーズのパート 1 で紹介した計算機サンプルでは、標準の WSDL v1.1インターフェースを通じて、シンプルな計算機サービスがクライアント・プログラムに提供されました。このサービス・インターフェースでは、クライアントは計算機のインスタンスを作成した後、計算機の合計値に対して加算と減算を行うことができました。サンプル内では、計算機インスタンスは WS-Resource として扱われます。また、計算機 Web サービスの実装には、サービス・インターフェースをステートレス Session Bean として実装し、CMP Entity Bean に状態を保持する、既存の J2EE ベスト・プラクティスを使用することができました。

この記事では、WS-Resource Properties 仕様に記述されている技法を使用して、計算機の状態の構成要素をプロパティーとして選択的に公開する手順を、順を追って説明します。実際の作業は次のとおりです。

  • 新たな属性 request を CalculatorState Bean に追加する。
  • WS-Resource から公開されるプロパティーを表す XML スキーマを作成する。
  • 作成したスキーマを計算機サービス WSDL に付加することにより、資源のプロパティーを計算機サービスと関連付ける。
  • WS-Resource プロパティーに対する (実装予定の) アクセス・オペレーションが含まれるように、計算機サービス WSDL を更新する。
  • 計算機サービス実装を拡張して、新しいオペレーションをサポートする。

この記事に記載された説明は、このシリーズのパート 1 で出てきたサンプル・コードを修正する際の参考になります。これらの修正を終えると、ws-statefulws3code.zip にあるようなコードが完成します。




上に戻る


CalculatorStateBean の修正

この例では、add、sub、および getTotal オペレーションを通じて資源へのアクセスが行われた回数を追跡するために、CalculatorState Bean を修正します。そのため、request という属性を CalculatorState Bean に追加します。さらに、add、sub、および getTotal メソッドに手を加えて、これらが呼び出されるたびに request カウンターが加算されるようにします。リスト 1 には、計算機サービスで修正された、add メソッドのコード・サンプルが含まれています。詳細については、CalculatorService.ear に含まれている CalculatorServiceSoapBindingImpl.java ファイルを参照してください。


リスト 1. add メソッドの実装
                
public float add(float value) {

	float _newTotal = 0f;

	try {
		CalculatorStateLocalHome home = getCalculatorStateHome();
		if (home != null) {
			String calcID = getPrimaryKeyFromContext();
			CalculatorStateLocal calculatorState =
				home.findByPrimaryKey(calcID);
			if (calculatorState != null) {
				_newTotal = calculatorState.getTotal() + value;
				calculatorState.setTotal(_newTotal);
 		      }
		      //Increment the request counter
		      int request = calculatorState.getRequest();
		      calculatorState.setRequest(++request);
	     }

	} catch (FinderException e) {
		e.printStackTrace();
	}

	return _newTotal;
}




上に戻る


計算機 WS-Resource 用の資源プロパティー・ドキュメントの定義

WS-Resource Properties 仕様では、資源プロパティー・ドキュメントは、資源プロパティー要素の論理的構成を示す XML ドキュメントとして定義されています。資源プロパティー・ドキュメントでは、WS-Resource によって実装された状態データの特定のビューまたは射影が定義されます。計算機 WS-Resource には、calcid、request、および value の 3 つの資源プロパティーがあります。サンプルでは、これらのプロパティーを、計算機サービス経由で公開される WS-Resource のプロパティーとして公開します。公開するプロパティーは、実装の仕組みを説明するために、計算機サービスから任意に選択したものです。WS-Resource Properties 仕様では、どのプロパティーをサービスから公開すべきかについては規定されていません。時間が経てば、より高レベルなドメイン別仕様が発表され、資源プロパティーを公開する際のスタイルとベスト・プラクティス・パターンが定義されることでしょう。初期の例は、OASIS WSDM Technical Committee が作成した WS-Manageability 仕様に見られます (WS-Manageability および WSDM の詳細については、『参考文献』を参照)。

WS-Resource Properties 仕様に従い、WS-Resource を公開する Web サービスの WSDL 定義に、資源プロパティーのスキーマを追加する必要があります。リスト 2 に、計算機サービス WSDL に追加したスキーマを示します。詳細については、CalculatorService.ear に含まれている CalculatorService.wsdl ファイルを参照してください。


リスト 2. 計算機の資源プロパティーのスキーマ
                
...
   <!-- Resource property element declarations -->
   <element name="calcId" type="string"/>
   <element name="total" type="float"/>
   <element name="request" type="int"/>

   <!-- Resource properties document declaration -->   
   <element name="GenericCalculatorProperties">
       <complexType>
       <sequence>
           <element ref="intf:calcId"/>
           <element ref="intf:total"/>
           <element ref="intf:request"/>
       </sequence>
       </complexType>
   </element>
...

リスト3 に示すように、WS-Resource Properties ドキュメントの宣言は、ResourceProperties 属性によって WSDL の portType 定義と関連付けられています。詳細については、CalculatorService.ear に含まれている CalculatorService.wsdl ファイルを参照してください。


リスト 3. 資源プロパティー・ドキュメントと portType の関連付け
                
...
<wsdl:portType name="CalculatorService" wsrp:ResourceProperties=
"intf:GenericCalculatorProperties">

...




上に戻る


計算機サービスへの WS-Resource Properties オペレーションの追加

  • WS-Resource Properties:仕様には、メッセージ交換のコレクションが定義されています。このコレクションにより、リクエスターが資源プロパティーに対して値の取得、値の更新、クエリーの発行を行う際の手段が標準化されます。WS-Resource Properties 仕様に定義されている 4 つのオペレーションを次に示します。
  • GetResourceProperty:このオペレーションでは、リクエスターは WS-Resource の単一の資源プロパティーの値を取得することができます。資源プロパティー・ドキュメントの型宣言を持つ portType を実装する Web サービスは、必ずこのオペレーションをサポートしている必要があります。
  • GetMultipleResourceProperties:このオペレーションでは、リクエスターは WS-Resource の複数の資源プロパティーの値を取得することができます。このオペレーションのサポートはオプションです。
  • SetResourceProperties:このオペレーションでは、リクエスターは WS-Resource の複数の資源プロパティーの値を修正することができます。このオペレーションで許可される変更には、挿入、更新、削除の 3 種類があります。このオペレーションのサポートはオプションです。
  • QueryResourceProperties:このオペレーションでは、リクエスターは XPath などのクエリー式を使用して WS-Resource の資源プロパティー・ドキュメントを照会することができます。このオペレーションのサポートはオプションです。

この例では、GetResourceProperty と GetMultipleResourceProperties をサポートするように計算機サンプルを拡張します。今後の記事では、SetResourceProperties オペレーションと QueryResourceProperties オペレーションの実装について説明する予定です。リスト 4 は、GetResourceProperty オペレーションをサポートするために計算機サービスの WSDL に加えた修正です。WSDL で GetResourceProperty オペレーションをサポートするには、次の手順を実行します (他の WS-ResourceProperties オペレーションについても、これらの手順を繰り返してください)。

  1. WS-ResourceProperties スキーマを WSDL ドキュメントに貼り付けます。このスキーマには、BaseFaultType および GetRequestProperty の要求と応答の定義が含まれています。
  2. WS-Resource Properties 仕様の定義に従って、各種の障害に対する WSDL メッセージ、および GetRequestProperty の要求と応答に対する WSDL メッセージを追加します。
  3. CalculatorService portType に GetResourceProperty オペレーションを追加します。
  4. GetResourceProperty オペレーションのバインディング情報を、CalculatorService の SOAP バインディングに追加します。

WSDL には、実装予定のオペレーションのみを組み込んでください。そうすれば、すべてのサービス・リクエスターが、WSDL を手動またはプログラマチックにイントロスペクトする方法で、サポートされているオペレーションやアクセス可能なプロパティーを判別できます。他のオペレーションをサポートするために必要な変更については、CalculatorService.ear に含まれている CalculatorService.wsdl ファイルを参照してください。


リスト 4. 計算機サービスの WSDL に追加された GetResourceProperty オペレーション
                
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://calculator.samples.ibm.com" ...>
  <wsdl:types>
    <xsd:schema targetNamespace=
    "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties" xmlns:wsrp=
"http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties" ...>
              
    <!-- ======= Global Attribute Declaration for WSDL 1.1 portType==== -->
    <xsd:attribute name="ResourceProperties" type="xsd:QName"/>
    
      
<!-- ==== Common fault information to carry in all fault messages ==== -->       
       <xsd:complexType name="BaseFaultType">
          <xsd:sequence>
             <xsd:element maxOccurs="1" minOccurs="1" name="Timestamp" type=
             "xsd:dateTime"/>
             <xsd:element maxOccurs="1" minOccurs="0" name="Originator" type=
             "wsa:EndpointReferenceType"/>
                      
             <!-- 
             <xsd:element name="ErrorCode" 
                      minOccurs="0" maxOccurs="1">
                <xsd:complexType>
                   <xsd:complexContent mixed="true">
                      <xsd:extension base="xsd:anyType">
                         <xsd:attribute name="dialect" type="xsd:anyURI"
                                    use="required"/>
                      </xsd:extension>
                   </xsd:complexContent>
                </xsd:complexType>      
             </xsd:element>
             -->
             
             <xsd:element maxOccurs="unbounded" minOccurs="0" name=
             "Description" type="xsd:string"/>
             <xsd:element maxOccurs="unbounded" minOccurs="0" name=
             "FaultCause" type="wsrp:BaseFaultType"/> 
          </xsd:sequence>
       </xsd:complexType>

<!-- ========== Message Types for GetResourceProperty  ============ -->
       
       <xsd:element name="GetResourcePropertyRequest" type="xsd:QName"/>

       <xsd:element name="GetResourcePropertyResponse">
         <xsd:complexType>
           <xsd:sequence>
             <xsd:any maxOccurs="unbounded" minOccurs="0"/>
           </xsd:sequence>
         </xsd:complexType>
       </xsd:element>

      <xsd:complexType name="ResourceUnknownFaultType">
         <xsd:complexContent>
            <xsd:extension base="wsrp:BaseFaultType"/>
         </xsd:complexContent>
      </xsd:complexType>
      <xsd:element name="ResourceUnknownFault" type="wsrp:ResourceUnknownFaultType"/>

      <xsd:complexType name="InvalidResourcePropertyQNameFaultType">
         <xsd:complexContent>
            <xsd:extension base="wsrp:BaseFaultType"/>
         </xsd:complexContent>
      </xsd:complexType>
      <xsd:element name="InvalidResourcePropertyQNameFault" type=
      "wsrp:InvalidResourcePropertyQNameFaultType"/>

...

  <wsdl:message name="InvalidResourcePropertyQNameFault">
    <wsdl:part name="InvalidResourcePropertyQNameFault" element=
    "wsrp:InvalidResourcePropertyQNameFault"/>
  </wsdl:message>
  <wsdl:message name="GetResourcePropertyResponse">
    <wsdl:part name="GetResourcePropertyResponse" element=
    "wsrp:GetResourcePropertyResponse"/>
  </wsdl:message>
  <wsdl:message name="GetResourcePropertyRequest">
    <wsdl:part name="GetResourcePropertyRequest" element=
    "wsrp:GetResourcePropertyRequest"/>
  </wsdl:message>
  <wsdl:message name="ResourceUnknownFault">
    <wsdl:part name="ResourceUnknownFault" element=
    "wsrp:ResourceUnknownFault"/>
  </wsdl:message>

...

  <wsdl:portType name="CalculatorService" wsrp:ResourceProperties=
  "intf:GenericCalculatorProperties">
    <wsdl:operation name="GetResourceProperty">
      <wsdl:input name="GetResourcePropertyRequest" message=
      "impl:GetResourcePropertyRequest"/>
      <wsdl:output name="GetResourcePropertyResponse" message=
      "impl:GetResourcePropertyResponse"/>
      <wsdl:fault name="InvalidResourcePropertyQNameFault" message=
      "impl:InvalidResourcePropertyQNameFault"/>
      <wsdl:fault name="ResourceUnknownFault" message=
      "impl:ResourceUnknownFault"/>
    </wsdl:operation>
...
  </wsdl:portType>
  <wsdl:binding name="CalculatorServiceSoapBinding" type="impl:CalculatorService">
    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="GetResourceProperty">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="GetResourcePropertyRequest">
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="GetResourcePropertyResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
      <wsdl:fault name="InvalidResourcePropertyQNameFault">
        <wsdlsoap:fault name="InvalidResourcePropertyQNameFault" use="literal"/>
      </wsdl:fault>
      <wsdl:fault name="ResourceUnknownFault">
        <wsdlsoap:fault name="ResourceUnknownFault" use="literal"/>
      </wsdl:fault>
    </wsdl:operation>
    ...
  </wsdl:binding>

...
</wsdl:definitions>


リスト5 に、更新済みの WSDL を WSDL2Java ユーティリティーを通じて実行した後に得られるサービス・エンドポイント・インターフェース (SEI) を示します。


リスト 5. WS-ResourceProperties メソッドが含まれたサービス・エンドポイント・インターフェース
                
public interface CalculatorService extends Remote 
{

public GetResourcePropertyResponse
getResourceProperty(QName getResourcePropertyRequest) 
throws RemoteException,                      
       InvalidResourcePropertyQNameFaultType,          
       ResourceUnknownFaultType;

public GetMultipleResourcePropertiesResponse getMultipleResourceProperties(
GetMultipleResourcePropertiesRequest getMultipleResourcePropertiesRequest) 
throws RemoteException,                      
       InvalidResourcePropertyQNameFaultType, 
       ResourceUnknownFaultType;

public SOAPElement 
getCalculator(String accountName) 
throws RemoteException;

public float 
add(float value) 
throws RemoteException;

public float 
sub(float value) 
throws RemoteException;

public float 
getTotal() 
throws RemoteException;

}





上に戻る


WS-Resource Properties オペレーションの実装と呼び出し

リスト6 に、計算機 Web サービスの GetResourceProperty メソッドの実装を示します。


リスト 6. 計算機 Web サービスの GetResourceProperty メソッドの実装
                
001  public com.ibm.samples.wsrp.GetResourcePropertyResponse
002  getResourceProperty(javax.xml.namespace.QName 
003  getResourcePropertyRequest) 
004    throws com.ibm.samples.wsrp.
       InvalidResourcePropertyQNameFaultType, 
005           com.ibm.samples.wsrp.ResourceUnknownFaultType 
006   {
007	GetResourcePropertyResponse   resourcePropertyResponse = null;
008		
009	if((getResourcePropertyRequest != null)&&
010		   011(getResourcePropertyRequest.getNamespaceURI().equals
011                      (CALCULATOR_NS)))
012	{
013		try {
014			CalculatorStateLocalHome home = 
015                       getCalculatorStateHome();
016			if (home != null) {
017				String calcID = getPrimaryKeyFromContext();
018				CalculatorStateLocal calculatorState =
019				    home.findByPrimaryKey(calcID);
020						
021				String name = 
022                     getResourcePropertyRequest.getLocalPart();
023				SOAPFactory sf = new SOAPFactory();
024				SOAPElement[] se = new SOAPElement[1];
025				se[0] = (SOAPElement) 
026                             sf.createElement(name, 
027                                              "calc", 
028                                              CALCULATOR_NS);
029
030				if(name.equals("calcId"))
031				{
032				    se[0].addTextNode(calcID);
033				    resourcePropertyResponse = new 
034                               GetResourcePropertyResponse();
035				    resourcePropertyResponse.set_any(se);
036					
037				}
038				else if(name.equals("total"))
039				{
040				    float total = calculatorState.getTotal();
041				    se[0].addTextNode(
042                                     (new Float(total)).toString());
043				    resourcePropertyResponse = new
044                               GetResourcePropertyResponse();
045				    resourcePropertyResponse.set_any(se);	
046
047				}
048				else if(name.equals("request"))
049				{
050				    int request = calculatorState.getRequest();
051				    se[0].addTextNode(
052                                 (new Integer(request)).toString());
053				    resourcePropertyResponse = new 
054                               GetResourcePropertyResponse();
055				    resourcePropertyResponse.set_any(se);
056				}
057				else
058				{
059				    String[] description 
060                             = {"Cannot find resource property"};
061				    throw new                                   
062                         InvalidResourcePropertyQNameFaultType
063                                 (Calendar.getInstance(), 
064                                  null, 
065                                  description, 
066                                  null);
067				
068				}
069				
070			}
071			} catch (FinderException e) {
072			e.printStackTrace();
073			String[] description = {"Cannot find resource"};
074			throw new ResourceUnknownFaultType
075                         (Calendar.getInstance(), 
076                          null, 
077                          description, 
078                          null);
079			} catch (SOAPException e) {
080				e.printStackTrace();
081			}		
082		
083		}		 	
084		else
085		{				
086			String[] description 
087                   = {"Cannot find resource property"};
088			throw new InvalidResourcePropertyQNameFaultType
089                         (Calendar.getInstance(), 
090                         null, 
091                         description, 
092                         null);
093		}
094     return resourcePropertyResponse;
095 }
096

上のコード・サンプルを詳しく見てみましょう。

  1. 行 9 から 11 では、getResourcePropertyRequest オブジェクトがヌルでなく、それに含まれるネーム・スペース URI が計算機サービスのネーム・スペース URI と一致することを確認します。
  2. 行 14 から 19 では、最初にリファレンス・プロパティーから calcID を取得し、それを使用して CalculatorState EJB ホームの findByPrimaryKey メソッドを呼び出して、CalculatorState Entity EJB コンポーネントの正しいインスタンスを検索します。
  3. 行 23 から 29 では、計算機サービスのネーム・スペースを使用して SOAP 要素を作成します。この SOAP 要素は、応答オブジェクト (resourcePropertyResponse) 内で送信されます。
  4. 行 30 から 37 では、getResourcePropertyRequest に含まれる名前が calcId かどうかを調べます。calcId である場合は、SOAP Element ノード (手順 3 でインスタンス化) の値を calcID (手順 2 で取得) に設定します。さらに、その SOAP 要素を resourcePropertyResponse 応答オブジェクトに設定します。
  5. 行 38 から 47 では、getResourcePropertyRequest に含まれる名前が total かどうかを調べます。total である場合は、CalculatorState EJB インスタンス (手順 2 で取得) から total の値を取得し、それを SOAP 要素に設定します。さらに、その SOAP 要素を resourcePropertyResponse 応答オブジェクトに設定します。
  6. 行 48 から 56 では、getResourcePropertyRequest に含まれる名前が request かどうかを調べます。request である場合は、CalculatorState EJB インスタンス (手順 2 で取得) から request の値を取得し、それを SOAP 要素に設定します。さらに、その SOAP 要素を resourcePropertyResponse 応答オブジェクトに設定します。
  7. 行 57 から 93 では、異なる例外 (WS-Resource Properties 仕様で定義) をスローします。
  8. 行 94 では、resourcePropertyResponse オブジェクトを返します。

リスト7 に、計算機 Web サービスが提供する GetResourceProperty オペレーションをクライアントが呼び出す方法を示します。詳細については、CalculatorService.ear に含まれている CalculatorTestExecute.jsp ファイルを参照してください。この例では、クライアントは、計算機 WS-Resource の total という名前の資源プロパティーを求めています。


リスト 7. 計算機の資源プロパティーへのアクセスを要求するサンプル・クライアント
                
com.ibm.samples.calculator.CalculatorService calculatorService = null;




// Initial Context
javax.naming.InitialContext ic = new javax.naming.InitialContext();

// Lookup calculator SI
// Returns object support javax.xml.rpc.Service
com.ibm.samples.calculator.CalculatorServiceService calculatorServiceSI 
 = (com.ibm.samples.calculator.CalculatorServiceService) ic.lookup(
 "java:comp/env/service/CalculatorServiceService");

// Get the calculator SEI
// Object that supports CalculatorService remote interface
//
calculatorService = 
(com.ibm.samples.calculator.CalculatorService) 
	  calculatorServiceSI.getPort(com.ibm.samples.calculator.CalculatorService.class);

if(calculatorService != null)
{
    try
    {
        String acctName = request.getParameter("acctName");

        float add 
            = (new Float(request.getParameter("add"))).floatValue();
        float sub 
            = (new Float(request.getParameter("sub"))).floatValue();
        
             
        javax.xml.soap.SOAPElement SE 
             = calculatorService.getCalculator(acctName);
        
        com.ibm.samples.wsa.wsaddr.EndpointReference epr 
        = com.ibm.samples.wsa.wsaddr.EndpointReference.fromSOAPElement(SE);   
                                            
	// Call JAXRPCHelper to associate EPR with account and 
      // make it stateful
	com.ibm.samples.wsa.utils.JAXRPCHelper.setEPR( 
                               (javax.xml.rpc.Stub) calculatorService , 
		                    epr);
      // Call a couple of other methods on calculator SEI		
      calculatorService.add(add);		
	calculatorService.sub(sub);
	javax.xml.namespace.QName rpQName 
		= new javax.xml.namespace.QName("http://calculator.samples.ibm.com", 
                          "total");
	com.ibm.samples.wsrp.GetResourcePropertyResponse getResourcePropertyResponse 
			= calculatorService.getResourceProperty(rpQName);
	    javax.xml.soap.SOAPElement[] se1 
                  =  getResourcePropertyResponse.get_any();

...


GetResourceProperty 要求は Implied Resource パターンに従っています。つまり、ターゲットとなる暗黙的資源を識別するためにサービスが必要とする識別子の値は、WS-Addressing リファレンス・プロパティーに含まれています。これらは、SOAP ヘッダーの GetResourceProperty 要求メッセージに含まれていなければなりません。リスト 8 およびリスト 9 に、GetResourceProperty メッセージ交換の SOAP エンコーディングを示します。


リスト 8. GetResourceProperty 要求の SOAP
                
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc=
"http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd=
"http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing">
<wsa:To ...>
http://localhost:9080/CalculatorServiceWeb/services/CalculatorService
</wsa:To>
<calcID ...>
  1083949184296
</calcID>
<dummyProp...>
  EXAMPLE PROPERTY
</dummyProp>
</soapenv:Header>
<soapenv:Body>
     <GetResourceProperty xmlns="">
        <GetResourcePropertyRequest xmlns:ns-1495319864=
        "http://calculator.samples.ibm.com" xmlns=
        "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
         ns-1495319864:total
       </GetResourcePropertyRequest>
     </GetResourceProperty>
</soapenv:Body>
</soapenv:Envelope>



リスト 9. GetResourceProperty 応答の SOAP メッセージ
                
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc=
"http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd=
"http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
     <GetResourcePropertyResponse xmlns="">
        <GetResourcePropertyResponse xmlns=
        "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
           <calc:total xmlns:calc="http://calculator.samples.ibm.com">5.0</calc:total>
        </GetResourcePropertyResponse>
     </GetResourcePropertyResponse>
</soapenv:Body>
</soapenv:Envelope>


リスト10 に、計算機 Web サービスの GetMultipleResourceProperties メソッドの実装を示します。詳細については、CalculatorService.ear に含まれている CalculatorServiceSoapBindingImpl.java ファイルを参照してください。実装では、getResourceProperty オペレーションを N 回呼び出しています。ここで、N は getMultipleResourcePropertiesRequest に含まれる QName 配列と同じサイズです。各呼び出しの結果は、SOAP 要素の配列に収集された後、resourcePropertiesResponse に設定されます。これがクライアントに返されます。


リスト 10. GetMultipleResourceProperties オペレーションの実装
                
public com.ibm.samples.wsrp.GetMultipleResourcePropertiesResponse
 getMultipleResourceProperties
(com.ibm.samples.wsrp.GetMultipleResourcePropertiesRequest
 getMultipleResourcePropertiesRequest) 
throws com.ibm.samples.wsrp.InvalidResourcePropertyQNameFaultType, 
       com.ibm.samples.wsrp.ResourceUnknownFaultType 
{

    QName[] resourceProperty 
        = getMultipleResourcePropertiesRequest.getResourceProperty();
    int size =  resourceProperty.length;
    SOAPElement[] se = new SOAPElement[size];
		
    GetMultipleResourcePropertiesResponse resourcePropertiesResponse 
        = null;
		
    if((resourceProperty != null)&&( size!= 0))
    {
        for(int i=0; i<size; i++)
	  {
		SOAPElement[] _se 
                = getResourceProperty(resourceProperty[i]).get_any();
		se[i] = _se[0];
	  }
			
	 resourcePropertiesResponse 
           = new GetMultipleResourcePropertiesResponse();
			
	 resourcePropertiesResponse.set_any(se);			        	
    }
    return resourcePropertiesResponse;
}


リスト11 に、計算機 Web サービスが提供する GetMultipleResourceProperties オペレーションをクライアントが呼び出す方法を示します。詳細については、CalculatorService.ear に含まれている CalculatorTestExecute.jsp ファイルを参照してください。この例では、クライアントは計算機 WS-Resource の 2 つの資源プロパティー (total および request) を求めています。


リスト 11. 計算機の資源の複数プロパティーへのアクセスを要求するサンプル用クライアント
                
com.ibm.samples.calculator.CalculatorService calculatorService = null;

// Initial Context
javax.naming.InitialContext ic = new javax.naming.InitialContext();

// Lookup calculator SI
// Returns object support javax.xml.rpc.Service
com.ibm.samples.calculator.CalculatorServiceService calculatorServiceSI 
  = (com.ibm.samples.calculator.CalculatorServiceService) ic.lookup(
  "java:comp/env/service/CalculatorServiceService");

// Get the calculator SEI
// Object that supports CalculatorService remote interface
//
calculatorService = 
(com.ibm.samples.calculator.CalculatorService) 
	calculatorServiceSI.getPort(com.ibm.samples.calculator.CalculatorService.class);

if(calculatorService != null)
{
    try
    {
        String acctName = request.getParameter("acctName");

        float add 
            = (new Float(request.getParameter("add"))).floatValue();
        float sub 
            = (new Float(request.getParameter("sub"))).floatValue();
        
             
        javax.xml.soap.SOAPElement SE 
             = calculatorService.getCalculator(acctName);
        
        com.ibm.samples.wsa.wsaddr.EndpointReference epr 
        = com.ibm.samples.wsa.wsaddr.EndpointReference.fromSOAPElement(SE);   
                                            
	// Call JAXRPCHelper to associate EPR with account and 
      // make it stateful
	com.ibm.samples.wsa.utils.JAXRPCHelper.setEPR( 

                               (javax.xml.rpc.Stub) calculatorService , 
		                    epr);
      // Call a couple of other methods on calculator SEI		
      calculatorService.add(add);		
	calculatorService.sub(sub);
 ...
      com.ibm.samples.wsrp.GetMultipleResourcePropertiesRequest 
          getMultipleResourcePropertiesRequest =
      new com.ibm.samples.wsrp.GetMultipleResourcePropertiesRequest();

      javax.xml.namespace.QName[] resourceProperty 
          = new javax.xml.namespace.QName[2];
      resourceProperty[0] = new javax.xml.namespace.QName(
                            "http://calculator.samples.ibm.com", 
                            "total");
      resourceProperty[1] = new javax.xml.namespace.QName(
                            "http://calculator.samples.ibm.com",
                            "request");         
      getMultipleResourcePropertiesRequest.setResourceProperty(
                       resourceProperty);
        
      com.ibm.samples.wsrp.GetMultipleResourcePropertiesResponse 
          getMultipleResourcePropertiesResponse = 
          calculatorService.getMultipleResourceProperties(
              getMultipleResourcePropertiesRequest);

      javax.xml.soap.SOAPElement[] se 
          = getMultipleResourcePropertiesResponse.get_any();        

...


GetMultipleResourceProperties要求も、Implied Resource パターンに従っています。リスト 12 およびリスト 13 に、GetResourceProperty メッセージ交換の SOAP エンコーディングを示します。


リスト 12. GetMultipleResourceProperties 要求の SOAP
                
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc=
"http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd=
"http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing">
<wsa:To ...>
http://localhost:9080/CalculatorServiceWeb/services/CalculatorService
</wsa:To>
<calcID ...>
  1083949184296
</calcID>
<dummyProp...>
  EXAMPLE PROPERTY
</dummyProp>
</soapenv:Header>
<soapenv:Body>
      <GetMultipleResourceProperties xmlns="">
           <GetMultipleResourcePropertiesRequest xmlns=
           "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
               <ResourceProperty xmlns:ns-1495319864=
               "http://calculator.samples.ibm.com" xmlns=
               "">ns-1495319864:total</ResourceProperty>
               <ResourceProperty xmlns:ns-1495319864=
               "http://calculator.samples.ibm.com" xmlns=
               "">ns-1495319864:request</ResourceProperty>
           </GetMultipleResourcePropertiesRequest>
     </GetMultipleResourceProperties>
</soapenv:Body>
</soapenv:Envelope>




リスト 13. GetMultipleResourceProperties 応答の SOAP メッセージ
                
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc=
"http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd=
"http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
   <GetMultipleResourcePropertiesResponse xmlns="">
      <GetMultipleResourcePropertiesResponse xmlns=
      "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
         <calc:total xmlns:calc="http://calculator.samples.ibm.com">5.0</calc:total>
         <calc:request xmlns:calc="http://calculator.samples.ibm.com">4</calc:request>
      </GetMultipleResourcePropertiesResponse>
   </GetMultipleResourcePropertiesResponse>
</soapenv:Body>
</soapenv:Envelope>






上に戻る


結論

この記事では、サービス・リクエスターが WS-Resource プロパティーの定義およびアクセスをどのように行うかについて基本的な説明を加えました。説明では、J2EE ベスト・プラクティスを利用した基本サービス実装を簡単に拡張することで、新しいアクセサー・オペレーションをサポートできることを示しました。特に、プロパティー・ドキュメントで定義された QName を、その状態が含まれる EJB Entity Bean フィールドにシンプルにマッピングする方法を示しました。同様に、既存のツールを利用してこの実装を簡単に実現できることも示しました。

この分野に投入されるテクノロジーが増えていくにつれて、WS-Resource プロパティーによって導入されるオプションのオペレーションは、ますます簡単に実装できるようになるでしょう。特に、WS-transactions と Set オペレーションを組み合わせれば、セマンティクスを新しくするために、より多くの構造と定義を得られると考えられます。また、XMLBeans や Service Data Objects などの新しいテクノロジーの登場は、XPATH の表現力をより活かすことにつながります。これらの構造を利用した構成体を使って照会オペレーションを実装することは、今後のプロトタイプ化に向けた興味深いテーマです。




上に戻る


Acknowledgements

The author wishes to thank Sonny Fulkerson for reviewing this article and for providing technical guidance.





上に戻る


ダウンロード

内容ファイル名サイズダウンロード形式
ws-statefulws3code.zipws-statefulws3code.zip  FTP
ダウンロード形式について


参考文献



著者について

Hidayatullah H. Shaikh is a senior software engineer on the IBM Software Group On-Demand Architecture and Development Team. His areas of interest and expertise include business process modeling and integration, service-oriented architectures, grid computing, e-commerce, J2EE technology, and database management (DBMSs) technologies. You can contact Hidayatullah at hshaikh@us.ibm.com.




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



 


 


不充分・不完全である大変素晴らしい
 


この記事を共有する

del.icio.us del.icio.us newsing newsing FC2ブックマーク FC2ブックマーク
Choix! Choix! ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
MM/memo MM/memo CZブックマーク CZブックマーク livedoorクリップ livedoorクリップ
はてなブックマーク はてなブックマーク Buzzurl(バザール) Buzzurl(バザール)




上に戻る


    日本IBMについて プライバシー お問い合わせ