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

developerWorks Japan  >  SOA and Web services | Sample IT projects  >

Web サービス・プログラミングのヒントと秘訣: シンプルで実用的な Web サービスのデザイン・パターンを学習 その 1

JMS を使用した非同期 Web サービス・オペレーション

developerWorks
ページオプション

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

サンプルコード

原文はこちら

原文はこちら


レベル: 中級

James Snell (jasnell@us.ibm.com), Software Engineer, IBM 

2004年 10月 19日

どのようにして明確かつ証明済みの Web アプリケーションの設計戦略を Web サービスの世界に応用するかを学習しましょう。このシリーズでの最初の記事にて、Java Messaging Service(JMS)のキューを使用することによりどのようにして非同期の照会オペレーションを実装するかを披露します。

SOAPでWebサービスを実装することを考慮する場合、同期的な要求/応答の形式を取り入れた操作を前提としていることでしょう。しかしながら、正真正銘のSOA(Service-Oriented Architecture)は、遥かに広範囲にわたるメッセージ・パターンと設計戦略を取り扱う能力を持ちます。この記事では、Webサービス・アプリケーションへのWebアプリケーションの基本的な設計パターンの応用に焦点を合わせる短いシリーズを開始します。紹介されるパターンは目新しくなく、実を言えばより伝統的なWebアプリケーションにて長年にわたり使われてきました。しかし、Webサービスの領域ではそのような戦略を実装する方法を多くの開発者が知らないか、それらの戦略の応用をまだ完全に考慮に入れていないかのどちらかなのです。シンプルでわかりやすい設計の別の方法をいくつか要求/応答のモデルに取り入れるのが、ここでの目的です。J2EEの環境にてWebサービスを実装する方法を(少なくとも基本的に)理解をしているのであれば、この記事で紹介される例を把握するのが少しは楽になります。

非同期照会パターン

まず手始めに、コード実行におけるタイムアウトや長時間にわたるハングアップを回避するために長期的な操作に割り込むことを目的とした非同期要求/応答の操作の実装を探究します。伝統的なHTTPそしてHTMLの Webアプリケーションでの非同期照会の実装を既に経験されているのでしたら、ここで実装されるパターンは見慣れたものでしょう。


図1. 非同期照会パターン
The asynchronous query pattern

このパターンのフローはシンプルです。

  1. (Requester が後の段階で要求(Request)の状況をチェックするために使用できる相関ID(correlation ID)を戻しメッセージをキューする)Service Providerへの要求(Request)を要求者(Requester)は送信します。
  2. 要求処理プログラムは要求(Request)をデキューしてそれを処理します。一般的には要求の処理には時間がかかります。処理が一度終了すればProcessor は応答(Response)メッセージをキューします。
  3. 未来の不確定な時点にて、要求(Request)に対する応答(Response)の準備ができたかどうかをRequester がService Provider に問いかけます。応答(Response)がキューされたら、Provider は要求者(Requester)にその応答(Response)を戻します。応答(Response)が有効でなければ、Provider はその旨を(応答が使用可能になるまで選択された任意のインターバルにてProvider をポーリングしながら、要求(Request)をキャンセルするか待機を続行するかを選べる)要求者(Requester)に報告します。

Java開発リソースのWebサイトであるJava RanchのJ2EE Servlet アプリケーションにて、このパターンのアプリケーションに関する優れた記事(参考文献を参照)をKyle Brown氏は著作しました。この記事にて、このパターンの基本的な実装に関与する根本的な設計の論点と動機について、著者は適切に考察しています。このパターンのWebサービス実装にて実装はあまり変化していませんが、それは別段驚くべきことでもありません。




上に戻る


サービス・インターフェースを設計

非同期照会パターンを図解するには、パターンの概念を図解する以外の実用的な価値を全く持たないWebサービスの簡単な例を実装します。そのサービスがすることは、長時間実行される処理をシミュレートするために実行中に10秒間の一時停止を強制した後に3つの小文字のString 入力値を大文字に変換することだけです。

このサービスを実装するには、2つのWebサービス・オペレーション(submitRequest そしてcheckResponse)が公開されます。それぞれのオペレーションが何をするかは、自明の理です。文字どおり、submitRequest はRequest(要求)を送信し、checkResponseはResponse(応答)をチェックします。サービス・インターフェースを説明するWSDLを、リスト 1に示します。


リスト1. AsyncService.wsdl
                
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions 
  targetNamespace="http://one.wspattern.developerworks.ibm.com" 
  xmlns:impl="http://one.wspattern.developerworks.ibm.com" 
  xmlns:intf="http://one.wspattern.developerworks.ibm.com" 
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
  xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <wsdl:types>
  <schema 
    targetNamespace="http://one.wspattern.developerworks.ibm.com" 
    xmlns="http://www.w3.org/2001/XMLSchema" 
    xmlns:impl="http://one.wspattern.developerworks.ibm.com" 
    xmlns:intf="http://one.wspattern.developerworks.ibm.com" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <complexType name="ResponseCheck">
    <sequence>
     <element name="correlationID" nillable="true" type="xsd:string"/>
    </sequence>
   </complexType>
   <element name="ResponseCheck" nillable="true" type="impl:ResponseCheck"/>
   <complexType name="Response">
    <sequence>
     <element name="type" type="xsd:int"/>
     <element name="correlationID" nillable="true" type="xsd:string"/>
     <element name="refresh" type="xsd:int"/>
     <element name="a" nillable="true" type="xsd:string"/>
     <element name="b" nillable="true" type="xsd:string"/>
     <element name="c" nillable="true" type="xsd:string"/>
    </sequence>
   </complexType>
   <element name="Response" nillable="true" type="impl:Response"/>
   <complexType name="Request">
    <sequence>
     <element name="a" nillable="true" type="xsd:string"/>
     <element name="b" nillable="true" type="xsd:string"/>
     <element name="c" nillable="true" type="xsd:string"/>
    </sequence>
   </complexType>
   <element name="Request" nillable="true" type="impl:Request"/>
  </schema>
 </wsdl:types>

   <wsdl:message name="submitRequestRequest">
      <wsdl:part name="request" type="intf:Request"/>
   </wsdl:message>

   <wsdl:message name="checkResponseResponse">
      <wsdl:part name="checkResponseReturn" type="intf:Response"/>
   </wsdl:message>

   <wsdl:message name="checkResponseRequest">
      <wsdl:part name="check" type="intf:ResponseCheck"/>
   </wsdl:message>

   <wsdl:message name="submitRequestResponse">
      <wsdl:part name="submitRequestReturn" type="intf:Response"/>
   </wsdl:message>

   <wsdl:portType name="AsyncService">
      <wsdl:operation name="checkResponse" parameterOrder="check">
         <wsdl:input 
           message="intf:checkResponseRequest" 
           name="checkResponseRequest"/>
         <wsdl:output 
           message="intf:checkResponseResponse" 
           name="checkResponseResponse"/>
      </wsdl:operation>
      <wsdl:operation name="submitRequest" parameterOrder="request">
         <wsdl:input 
           message="intf:submitRequestRequest" 
           name="submitRequestRequest"/>
         <wsdl:output 
           message="intf:submitRequestResponse" 
           name="submitRequestResponse"/>
      </wsdl:operation>
   </wsdl:portType>

   <wsdl:binding name="AsyncServiceSoapBinding" type="intf:AsyncService">
      <wsdlsoap:binding 
        style="rpc" 
        transport="http://schemas.xmlsoap.org/soap/http"/>
      <wsdl:operation name="checkResponse">
         <wsdlsoap:operation soapAction=""/>
         <wsdl:input name="checkResponseRequest">
            <wsdlsoap:body 
              namespace="http://one.wspattern.developerworks.ibm.com" 
              use="literal"/>
         </wsdl:input>
         <wsdl:output name="checkResponseResponse">
            <wsdlsoap:body 
              namespace="http://one.wspattern.developerworks.ibm.com" 
              use="literal"/>
         </wsdl:output>
      </wsdl:operation>
      <wsdl:operation name="submitRequest">
         <wsdlsoap:operation soapAction=""/>
         <wsdl:input name="submitRequestRequest">
            <wsdlsoap:body 
              namespace="http://one.wspattern.developerworks.ibm.com" 
              use="literal"/>
         </wsdl:input>
         <wsdl:output name="submitRequestResponse">
            <wsdlsoap:body 
              namespace="http://one.wspattern.developerworks.ibm.com" 
              use="literal"/>
         </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>

   <wsdl:service name="AsyncServiceService">
      <wsdl:port binding="intf:AsyncServiceSoapBinding" name="AsyncService">
         <wsdlsoap:address 
           location="http://localhost:9080/WSPattern1/services/AsyncService"/>
      </wsdl:port>
   </wsdl:service>

</wsdl:definitions>

このインターフェースについて述べるべきことがいくつかあります。

  1. サービスはRPC/Literalのエンコード方式を使用します。
  2. submitRequestcheckResponse のオペレーションの両方ともがResponseと呼ばれるオブジェクトを戻します。typeのプロパティーにより識別されるResponseのフレーバーが2種類あります。type のプロパティー の値が0ならば、Refresh Responseを参照し、type のプロパティー の値が1ならば、Request Responseを参照します。応答がまだ有効(使用可能)ではなく、(上記にて参照されるKyle Brown氏の記事にて考察されるHTTP META Refreshのメカニズムと同等の)リフレッシュ・プロパティーに指定される値をサブミットするや否や新規のcheckResponseのオペレーションを要求者がサブミットすることを、Refresh Response は表わします。Request Response は3つの大文字の入力ストリングを含み、要求処理の完了を表わします。
  3. Refresh Response は(そのcheckResponse オペレーションの入力としてその値が使用される)Correlation ID のプロパティーを含みます。この識別子(ID)はクライアントが応答と初期の要求を関連付けさせる唯一の手段です。後の段階で少し触れますが、これを実装する手段は他にもいくつかあります。

このサービスの典型的なメッセージ交換を、リスト2に示します。


リスト2. AsyncService のメッセージ交換
                
                Initial Request

<SOAP-ENV:Envelope 
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SOAP-ENV:Body>
    <m:submitRequest 
      xmlns:m="http://one.wspattern.developerworks.ibm.com">
      <request>
        <a>String</a>
        <b>String</b>
        <c>String</c>
      </request>
    </m:submitRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


submitRequest Response

<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/>
  <soapenv:Body>
    <p155:submitRequestResponse 
      xmlns:p155="http://one.wspattern.developerworks.ibm.com">
      <submitRequestReturn>
        <type>0</type>
        <correlationID>1097517621904</correlationID>
        <refresh>10000</refresh>
        <a xsi:nil="true"/>
        <b xsi:nil="true"/>
        <c xsi:nil="true"/>
      </submitRequestReturn>
    </p155:submitRequestResponse>
  </soapenv:Body>
</soapenv:Envelope>


Initial checkResponse attempt, no response available, submitted after 10000 miliseconds

<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/>
  <soapenv:Body>
    <p155:checkResponseResponse 
      xmlns:p155="http://one.wspattern.developerworks.ibm.com">
      <checkResponseReturn>
        <type>0</type>
        <correlationID>1097517621904</correlationID>
        <refresh>10000</refresh>
        <a xsi:nil="true"/>
        <b xsi:nil="true"/>
        <c xsi:nil="true"/>
      </checkResponseReturn>
    </p155:checkResponseResponse>
  </soapenv:Body>
</soapenv:Envelope>


Second checkResponse attempt, submitted after 10000 miliseconds

<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/>
  <soapenv:Body>
    <p155:checkResponseResponse 
      xmlns:p155="http://one.wspattern.developerworks.ibm.com">
      <checkResponseReturn>
        <type>1</type>
        <correlationID xsi:nil="true"/>
        <refresh>0</refresh>
        <a>STRING</a>
        <b>STRING</b>
        <c>STRING</c>
      </checkResponseReturn>
    </p155:checkResponseResponse>
  </soapenv:Body>
</soapenv:Envelope>




上に戻る


サービスを実装

非同期照会パターンのサービス実装は、Java Messaging Serviceの単刀直入な応用です。この例の目的のために、OpenJMS のオープン・ソースであるJMSプロバイダー実装(参考文献を参照)そしてIBM® WebSphere ® Application Server V5(Application Server)を使用します。デフォルトのOpenJMS 構成を使用し、JSR-109に準拠するJ2EE Webサービスを実装します。developerWorks からダウンロード可能(参考文献を参照)なWebSphere Studio Application Developer (Application Developer) V5.1を使用して、例にて示されているコードを書き出しました。Application Developerへのアクセスが不可能な場合に備え、ここにてEARファイル(参考文献を参照)を提供します。

実装されるべきサーバー側のコンポーネントが2つあります。それは要求処理プログラムにWebサービス実装です。キューから要求の引き出し、そして「長時間実行される」10秒間の大文字化の処理の実行と言う仕事が要求処理プログラムに課せられています。checkResponse オペレーションに続くかたちでクライアントへの応答を配信そして処理するためにキューし、そしてWebサービス・クライアントからの要求を受信するタスクを、サービス実装は課せられます。

典型的なJ2EEアプリケーションでは、JMS仕様によれば要求処理装置はMessage Driven Beanとして実装されます。この例では、JMSのMessageListenerインターフェースを実装する簡素なHTTP Servlet を使用します。サーブレットはサーバー始動を初期化するように構成されており、受信される可能性の高い全ての要求にlistener が使用可能になるようになっています。要求がキューされると同時に、それはlistenのサーブレットに配信されます。


リスト3. JNDIListenerServlet.java
                
package com.ibm.developerworks.wspattern.one.helper;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.naming.Context;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

public class JNDIListenerServlet 
  extends HttpServlet 
  implements Servlet, MessageListener {

  private Context context;
  private QueueConnection connection;
  private QueueSession session;
  private Queue queue;
  private QueueReceiver receiver;

  public void init() 
    throws ServletException {

     super.init();
    
     try {
       context = JNDIHelper.getInitialContext();
       connection = JNDIHelper.getConnection(context);
       session = JNDIHelper.getSession(connection);
       queue = JNDIHelper.getQueue(context);
       receiver = JNDIHelper.getQueueReceiver(session, queue);
       receiver.setMessageListener(this);
       System.out.println("Listener servlet is Listening");
     } catch (Exception e) {}
  }

  public void destroy() {
    try {
      connection.close();
    } catch (Exception e) {}
  }

  public void onMessage(Message message) {
    try {
      System.out.println("Processing message " + message.getJMSCorrelationID());
      Thread.sleep(10 * 1000); // sleep for ten seconds
      Queue responseQueue = JNDIHelper.getResponseQueue(context);
      QueueSender sender = JNDIHelper.getQueueSender(session,responseQueue);
      MapMessage request = (MapMessage)message;
      MapMessage response = session.createMapMessage();
      response.setJMSCorrelationID(request.getJMSCorrelationID());
      for (Enumeration e = request.getMapNames(); e.hasMoreElements();) {
        String name = (String) e.nextElement();
        try {
          response.setString(
            name, 
            request.getString(name).toUpperCase());
        } catch (Exception ex) {}
      }
      sender.send(response);
    } catch (Exception e) {
      System.out.println("==================");
      try {
        System.out.println(
          "THERE WAS AN ERROR PROCESSING THE MESSAGE! " + 
          message.getJMSCorrelationID());
      } catch (Exception ex) {}
      e.printStackTrace(System.out);
      System.out.println("==================");
    }
  }

}

JNDIListenerServlet とサービス実装は両方とも(セッションとJMS接続の初期化に関する詳細を隠すこのアプリケーションのために作成された)簡素なhelperクラスを使用します。


リスト4. JNDIHelper.java
                
package com.ibm.developerworks.wspattern.one.helper;

import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;


public class JNDIHelper {

  private static Context context;

  public static Context getInitialContext() 
    throws NamingException {
      if (context == null) {
        Hashtable properties = new Hashtable();
        properties.put(
          Context.INITIAL_CONTEXT_FACTORY, 
          "org.exolab.jms.jndi.InitialContextFactory");
        properties.put(
          Context.PROVIDER_URL,
          "rmi://localhost:1099");
        context = new InitialContext(properties);
      }
      return context;
  }

  public static QueueConnection getConnection(
    Context context) 
      throws NamingException, 
             JMSException {
        QueueConnectionFactory factory = 
          (QueueConnectionFactory) context.lookup(
            "JmsQueueConnectionFactory");
        QueueConnection connection = factory.createQueueConnection();
        connection.start();
        return connection;
  }

  public static QueueSession getSession(QueueConnection connection) 
    throws JMSException {
      QueueSession session = 
        connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
      return session;
  }

  public static Queue getQueue(Context context) 
    throws NamingException {
      Queue queue = (Queue) context.lookup("queue1");
      return queue;
  }  
  
  public static Queue getResponseQueue(Context context) 
    throws NamingException {
      Queue queue = (Queue) context.lookup("queue2");
      return queue;
  }
  
  public static QueueSender getQueueSender(
    QueueSession session, 
    Queue queue) 
      throws JMSException {
        QueueSender sender = session.createSender(queue);
        return sender;
  }
  
  public static QueueReceiver getQueueReceiver(
    QueueSession session,
    Queue queue) 
      throws JMSException {
        QueueReceiver receiver = session.createReceiver(queue);
        return receiver;
  }

  public static QueueReceiver getQueueReceiver(
    QueueSession session,
    Queue queue,
    String selector) 
      throws JMSException {
        QueueReceiver receiver = session.createReceiver(queue, selector);
        return receiver;
  }
    
}

一度サーブレットが作成されれば、(サーバー始動にて初期化されるように)サーブレットを構成するようにWebアプリケーションのweb.xml を編集します。サーブレットが初期化されれば、それはJMS接続を開きOpenJMSのデフォルトのメッセージ・キューのlistenerとしてそれ自身を登録します。

第二段階はサービス実装の作成です。機能するJSR-109 Webサービスを手に入れるために生成されるべき多種にわたる成果物のおかげで、Application Developer とともに作業することが役立ちます。ここではサービス実装クラスに焦点を合わせます。Application Server が必要とする他の多種類にわたるJavaそしてXML構成ファイルをご覧になりたいのであれば、この記事の最初と最後にあるCode アイコンをクリックしてダウンロードすることにより得られるコードを参照してください。


リスト5. AsyncService.java
                
package com.ibm.developerworks.wspattern.one;

import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.naming.Context;

import com.ibm.developerworks.wspattern.one.helper.JNDIHelper;

public class AsyncService {

  public Response submitRequest(Request request) {
    Response response = null;
    try {
      Context context = JNDIHelper.getInitialContext();
      QueueConnection connection = JNDIHelper.getConnection(context);
      QueueSession session = JNDIHelper.getSession(connection);
      Queue queue = JNDIHelper.getQueue(context);
      QueueSender sender = JNDIHelper.getQueueSender(session,queue);
      
      MapMessage message = session.createMapMessage();
      String corrID = Long.toString(System.currentTimeMillis());
      message.setJMSCorrelationID(corrID);
      
      message.setString("one", request.getA());
      message.setString("two", request.getB());
      message.setString("three", request.getC());
      sender.send(message);
      
      response = new Response();
      response.setType(Response.TYPE_REFRESH);
      response.setCorrelationID(corrID);
      response.setRefresh(10 * 1000);
      return response;
    } catch (Exception e) {
      response = new Response();
      response.setType(Response.TYPE_RESPONSE);
      response.setA(e.getMessage());
    }
    return response;
  }

  public Response checkResponse(ResponseCheck check) {
    String corrID = check.getCorrelationID();
    Response response = null;
    try {
      Context context = JNDIHelper.getInitialContext();
      QueueConnection connection = JNDIHelper.getConnection(context);
      QueueSession session = JNDIHelper.getSession(connection);
      Queue queue = JNDIHelper.getResponseQueue(context);
      String selector = "JMSCorrelationID = '" + corrID + "'";
      QueueReceiver receiver = JNDIHelper.getQueueReceiver(session, queue, selector);
      Message message = receiver.receiveNoWait();
      if (message == null) {
        response = new Response();
        response.setType(Response.TYPE_REFRESH);
        response.setRefresh(10 * 1000);
        response.setCorrelationID(corrID);
      } else {
        MapMessage resp = (MapMessage)message;
        response = new Response();
        response.setType(Response.TYPE_RESPONSE);
        response.setA(resp.getString("one"));
        response.setB(resp.getString("two"));
        response.setC(resp.getString("three"));
      }
    } catch (Exception e) {}
    return response;
  }
}

驚愕の対象に値するものは、ここに見当たらないはずです。submitRequest メソッドは入力パラメーターを基にJMS のMapMessage を準備します。このマップ・メッセージは3つのストリング値から成ります。メッセージはそれからキューに送信され、相関IDを含むRefresh Response が準備されてクライアントに戻されます。

checkResponse のオペレーションは入力パラメーターから相関IDを取得して、(適切な相関IDをいだくメッセージを送信することを要求するように)応答キューへの接続を開きます。メッセージが存在しなければ、オペレーションはメッセージを待ち続けません。それは単に別のRefresh Responseを新規のリフレッシュ・インターバルの期間付きで準備して、それを呼び出し者に戻します。メッセージが配信されれば、オペレーションは適切なRequest Responseを準備し戻します。

Webサービスを配置し、OpenJMS とWebSphere のサーバーを起動すれば、非同期照会パターンのWebサービスが始動し稼動を開始します。




上に戻る


まとめ

非同期照会パターンの成功の中心に位置するは、Webサービスのクライアントとサービス・プロバイダーが持つ(要求と応答を相関する)能力です。ここで表記される例では、簡素かつ一度きりの相関IDを作成してひとつのアプリケーションの例に特化したタイマー機能をリフレッシュできます。しかしながら、同じ結果を達成するために「WS-*」仕様の組み合わせを使うことも可能です。WS-Addressing Endpoint Reference またはWS-Transaction Coordination Context ならば相関IDを簡単に含有してタイマー値をリフレッシュできたことでしょう。とにかく、このパターンの使用は特定のアプリケーションに特化され、標準のSOAPヘッダーのエレメントと多種にわたるWS-* 仕様を使うかどうかに関係なく、それぞれの操作が実装する振る舞いは明確かつドキュメントによる裏付けがなくてはなりません。

さらに、ここで実装されている例は、伝統的なSOAPの要求/応答メッセージ・パターンで要求を実行して応答を受信します。別の方法として、要求がHTTP POSTによりサーブレットへ送信されHTTP GET要求を使用することにより応答が回収されるREST-style のモデルを使うのも手です。それぞれのアプローチは同等に有効であり、互いに対して相対的に長所と短所があります(一長一短な)ので、アプリケーションの独自の必要性(ニーズ)に応じて選択されるべきです。例えば、checkResponse のオペレーションがWS-Securityを基にした認証を必要としているのであれば、REST-styleのもたらす相互作用のパターンを使う意味が無いでしょう。

最後に、長期的に運用される操作への詳細にわたる状況照会を実行すること、そして実行中の操作をキャンセルすることを要求者に許可するように、この用例の有効範囲を拡張することを想像するのはそう難しくはないでしょう。これらの多種にわたる可能性を図解・説明するのはこの記事の有効範囲から外れておりますので、ここから先の探究は読者自身の実践的な学習としておまかせします。





上に戻る


ダウンロード

内容ファイル名サイズダウンロード形式
WebSphere deployable EAR filews-tip-altdesign1ear.ear701 KBHTTP
Example program source filesws-tip-altdesign1code.zip719 KBHTTP
ダウンロード形式について


参考文献



著者について

Author photo

James Snell 氏は IBM Emerging Technologies Toolkit チームの一員であり、過去数年間にわたり新興の Web サービスの技術そして標準に焦点を合わせてきました。developerWorks にて、新興の技術に焦点を定めるブログを管理しています。




記事の評価


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



 


 


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


この記事を共有する

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について プライバシー お問い合わせ