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

developerWorks Japan  >  SOA and Web services  >

RESTful な Web サービスとそのための Ajax ベースのクライアント

developerWorks
ページオプション

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

原文はこちら

原文はこちら


レベル: 中級

Shailesh K. Mishra (shailekm@in.ibm.com), Software Engineer, IBM 

2007年 7月 05日

RESTful な Web サービスとは、REST (REpresentational State Transfer) アーキテクチャー・スタイルを用いてビルドされたWeb サービスのことです。この記事では、単純なプロキシー・サーブレットと Ajax (Asynchronous XML + JavaScript) ベースのクライアントを使って RESTful な Web サービスを作成する 1 つの方法を紹介します。

はじめに

Roy Fielding は彼の論文のなかで、REST を今日の Web アーキテクチャーの基礎となるコンセプトだと述べています (Fielding の論文へのリンクは、記事の終わりに記載した「参考文献」を参照してください)。彼は REST の基準を以下のように設定しました。

  • 最新の Web アーキテクチャーをモデル化するための一連の制約である
  • HTTP および URI 仕様には、REST の原則が適用されている
  • HTTP の進化のなかで目に見えて明らかである

REST はプロトコルではなく、むしろアーキテクチャー・スタイルであり、この点が重要な違いとなっています。

Web サービスに関しては、W3C では正式見解として以下のように Web サービスを定義しています。

「Web サービスは URI によって識別されるソフトウェア・システムで、その公開インターフェースとバインディングは XML を使用して定義および記述されます。XML による定義は、他のソフトウェア・システムを使って見つけ出すことが可能です。他のシステムが定義を見つけると、インターネット・プロトコルで送信されたXML ベースのメッセージを使用して、その定義で規定された方法で Web サービスと対話動作できるようになります」(この文を引用した原文へのリンクは、「参考文献」に記載しています)。

Ajax Resource Centerにアクセスしてください。ここには記事、チュートリアル、ディスカッション・フォーラム、ブログ、ウィキ、イベント、そしてニュースなど、Ajax プログラミング・モデルに関する情報が豊富に用意されており、ワンストップ・ショップになっています。新しい情報もここに記載されます。

常識からすると、Web サービスは、マシンとユーザー間の通信ではなくマシン間の通信を行うための手段だということがわかります。RESTful な Web サービスは、REST アーキテクチャー・スタイルに従ってビルドされた Web サービスです。次のセクションでは、一例を用いて RESTful な Web サービスをビルドする方法を説明します。この説明を理解するには、Ajax を理解していることが肝心です (Ajax が初めてという読者は、「参考文献」に記載した参考情報へのリンクを参照してください)。




上に戻る


RESTful な Web サービスを作成する

RESTful な Web サービスを作成するには、まず、Web サービスとして公開したいすべてのリソースを識別する必要があります。リソースの例としては、従業員リスト、従業員詳細、注文書などがあります。REST では、1 つひとつのリソースが一意の URI (Uniform Resource Identifier) で識別されます。つまり、すべてのリソースにそれぞれ一意の URI を決定しなければなりません。例えば従業員リストを識別するには http://www.employee-details.com/employees-list のような URI を使用し、従業員詳細は http://www.employee-details.com/employees/01234 といった URI で表すことができます。

リソースを取得および変更するために使用する HTTP 操作は、GET、PUT、POST、および DELETE です。追加 (および関連) 情報を許可するには、リソース表現にハイパーリンクを提供します。リソースのデータに対するリクエストおよびレスポンスを行うためのフォーマットを指定してください。そのために必要な操作は、PUT および POST です。

図 1 に、RESTful な Web サービスとの対話を図解します。


図 1. RESTful な Web サービスとの対話




上に戻る


RESTful な Web サービスを実装する

RESTful な Web サービスは、HTTP サーブレットを使って実装することができます。この記事では、ある会社の従業員詳細を表示するダミー・サービスを使用して、実装方法を説明します。従業員リストのリソースは、論理 URI、http://localhost:9080/AJAX_REST_Demo/RESTDemoServlet/employee-list で表します。このサービスを HTTP GET で呼び出すと、リスト 1 に示す従業員のリストが返されます。


リスト 1. HTTP GET で呼び出された従業員リスト
                
                <?xml version='1.0' encoding='UTF-8'?>
<p:Employees xmlns:p='http://www.employee-details.com'>
                <Employee id='00345'  href='/employees/00345'/>
            <Employee id='00346'  href='/employees/00346'/>
                <Employee id='00347'  href='/employees/00347'/>
                <Employee id='00348'  href='/employees/00348'/>
</p:Employees>


同様に、従業員詳細を表すには http://localhost:9080/AJAX_REST_Demo/RESTDemoServlet/employee/0124 などの論理 URI を使用します。このサービスを HTTP GET で呼び出した場合には、リスト 2 の従業員詳細が返されます。


リスト 2. HTTP GET で呼び出された従業員詳細
                
                <?xml version='1.0' encoding='UTF-8'?>
< EmpDetail xmlns:p='http://www.employee-details.com'>
                <<Emp-ID>00345</Emp-ID>
            <Name>David Henry</Name>
               <Department>Finance</ Department >
</p:EmpDetail>

リスト 3 は、サーブレット・コードです。このリストではすべてをハードコーディングしていますが、データベースを操作するために拡張し、リアルタイムの RESTful なサービスにすることもわけありません。


リスト 3. サーブレット・コード
                                
public class RESTDemoServlet extends HttpServlet implements Servlet {
 /* (non-Java-doc)
  * @see javax.servlet.http.HttpServlet#HttpServlet()
  */
 Map map =new HashMap();
        
 /* (non-Javadoc)
  * @see javax.servlet.GenericServlet#init()
  */
 public void init() throws ServletException {
  // TODO Auto-generated method stub
  super.init();
                
  Employee emp0 =new Employee("David","Finance");
  Employee emp1 =new Employee("Smith","HealthCare");
  Employee emp2 =new Employee("Adam","Information technology");
  Employee emp3 =new Employee("Stephan","Life Sciences");
                
  map.put("00345",emp0);
  map.put("00346",emp1);
  map.put("00347",emp2);
  map.put("00348",emp3);
 }
        
 /* (non-Java-doc)
  * @see javax.servlet.http.HttpServlet#doGet
      (HttpServletRequest arg0, HttpServletResponse arg1)
  */
 protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1) 
      throws ServletException, IOException {
  // TODO Auto-generated method stub
  arg1.setContentType("text/xml");
  PrintWriter out=arg1.getWriter();
  System.out.println(map);
  if(arg0.getPathInfo()!= null){
  String EmpId=arg0.getPathInfo().substring(1,arg0.getPathInfo().length());
  System.out.println(EmpId);
                
  out.write("<?xml version='1.0' encoding='UTF-8'? >"+"\n");
   out.write("<p:EmpDetail xmlns:p='http://www.employee-details.com' >"+"\n");
   out.write("<Emp-ID>"+EmpId+" </Emp-ID >"+"\n");
   out.write("<Name>"+((Employee)map.get(EmpId)).name+" </Name >"+"\n");
   out.write("<Department >"+((Employee)map.get(EmpId)).dept+" </Department >"+"\n");
   out.write("</p:EmpDetail >"+"\n");
   out.flush();
  }else{
   out.write("<?xml version='1.0' encoding='UTF-8'? >"+"\n");
   out.write("<p:Employees xmlns:p='http://www.employee-details.com' >"+"\n");
   out.write("<Employee id='00345' href='http://localhost:9080/
      AJAX_REST_Demo/RESTDemoServlet/employees/00345'/ >"+"\n");
   out.write("<Employee id='00346' href='http://localhost:9080/
      AJAX_REST_Demo/RESTDemoServlet/employees/00346'/ >"+"\n");
   out.write("<Employee id='00347' href='http://localhost:9080/
      AJAX_REST_Demo/RESTDemoServlet/employees/00347'/ >"+"\n");
   out.write("<Employee id='00348' href='http://localhost:9080/
      AJAX_REST_Demo/RESTDemoServlet/employees/00348'/ >"+"\n");
   out.write("</p:Employees >");
   out.flush();
  }
 }

 /* (non-Java-doc)
  * @see javax.servlet.http.HttpServlet#doPost
      (HttpServletRequest arg0, HttpServletResponse arg1)
  */
 protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1) 
      throws ServletException, IOException {
  // TODO Auto-generated method stub
 }

        
}

次のセクションでは、この RESTful な Web サービスのための Ajax クライアントを作成する方法を説明します。




上に戻る


RESTful な Web サービスの Ajax クライアントを作成する

前述のとおり、Ajax とは Asynchronous JavaScript + XML の略で、XML HTTP 手法と呼ばれることもあります。Ajax の中核となる手法が重点を置いているのは、ページの更新を行わないサーバーとの非同期通信です。XMLHTTPRequest オブジェクトにより、サーバーに対する GET、 POST、PUT、DELETE 操作を非同期で行うことが可能になります。この場合、ユーザーに対しては何も表示されません。つまり、ステータス・メッセージは表示されないということです。ただし状態変更に対するハンドラー・メソッドを指定すると、指定されたハンドラーにはリクエストの以下の状態が通知されます。

  • 初期化
  • 開始
  • リターンの処理中
  • 完了

リスト 4 に、Ajax をベースとした HTML ページのコードを示します。このページは、上記の RESTful な Web サービスに対してクライアントとして機能します。


リスト 4. Ajax ベースの HTML ページのコード
                               
<SCRIPT language="javascript" type="text/javascript" >
var req=null;
//This function initializes XHR
function initXHR() {
 if (navigator.appName.indexOf("Microsoft") > -1 ) {
   try{
      req=new ActiveXObject("Microsoft.XMLHTTP");
     }catch(e1){
      alert("failed to create XHR in IE");
     }
   }else{
       try{
            req=new XMLHttpRequest();
           }catch(error){
            alert("failed to create XHR in FireFox");
           }
        }
}
//get an employee detail
function getEmpDetails(Empurl){
 initXHR();
 req.open("GET",Empurl, true);
 req.onreadystatechange=handleEmpDetailResponse;
 req.send(null);

}

//get employee list
function getEmployeeList(listurl){
 initXHR();
  req.open("GET", listurl, true);
  req.onreadystatechange=handleEmpListResponse;
  req.send(null);
}
function handleEmpDetailResponse(){
 //if Response is complete

  if(req.readyState==4){
   //response is OK
    if(req.status==200){
     var str="";
        var response=req.responseXML;
        var root=response.documentElement;
        for(i=0;i <root.childNodes.length;i++){
         if(root.childNodes[i].nodeType != 1) continue;
        var name=root.childNodes[i].nodeName;
        var value=root.childNodes[i].firstChild.nodeValue;
        str=str+name+"--- >"+value+" <br >";
                }
         document.getElementById("emp-div").style.display="";
         document.getElementById("emp-detail-div").innerHTML=str;
        }else{
      document.getElementById("messageDiv").innerHTML=" <SPAN style='color:#FF0000; 
          font-size:12pt; text-decoration:none;' <Invalid URL or PartId </SPAN >";
        }
        req.abort();
   }
}

function handleEmpListResponse(){
 //if Response is complete

  if(req.readyState==4){
   //response is OK
    if(req.status==200){
     var pstr="";
     var response=req.responseXML;
     var root=response.documentElement;
     for(i=0;i <root.childNodes.length;i++){
      if(root.childNodes[i].nodeType != 1) continue;
       var id=root.childNodes[i].getAttribute("id");
       var href=root.childNodes[i].getAttribute("href");
         pstr=pstr+"EmpId"+"--- >"+id+"&nbsp; <input type='button' value='
            GetEmpDetails' onclick="+'"'+"getEmpDetails('"+href+"')"+'"'+">"+" <br >";
           }
         document.getElementById("emp-list-div").style.display="";
         document.getElementById("emp-list").innerHTML=pstr;
        }else{
         document.getElementById("messageDiv").innerHTML=" <SPAN style='color:#FF0000; 
          font-size:12pt; text-decoration:none;' >Invalid Employee ID. </SPAN >";
        }
    }
}
</SCRIPT >
<center >
<input type="button" value="getEmployee-List" onclick="getEmployeeList
    'http://localhost:9080/AJAX_REST_Demo/RESTDemoServlet/employee-list')" > <br > <br >
<div id="messageDiv" > </div >
<div id="emp-list-div" style='color:#FF0000; font-size:12pt; text-decoration:none; 
      display:none;' >Employee List : </div > <br >
<div id="emp-list" > </div > <br > <br >
<div id="emp-div" style='color:#FF0000; font-size:12pt; text-decoration:none; 
      display:none;' >Selected Employee Detail : </div > <br >
<div id="emp-detail-div" > </div >
</center >

リスト4 では、ユーザーが getEmployee-List ボタンをクリックすると、XML HTTP リクエストがサーバーに送信されます。readyState の変更に対しては、ハンドラー関数 handleEmpListResponse を XML HTTP リクエストに指定し、サーバーがレスポンスを完了して (readyState = 4) レスポンスが OK であれば、XML を解析してページの文書オブジェクト・モデル (DOM) に付加し、従業員リストを表示することになっています。同様に、ユーザーがGetEmpDetails ボタンをクリックすると、ハンドラー関数 handleEmpDetailResponse がサーバーからの XML レスポンスを処理し、ページの DOM を変更して特定の従業員の詳細を表示します。




上に戻る


まとめ

この記事では、サーブレットと Ajax ベースのクライアントを使用して RESTful な Web サービスを作成する方法を説明しました。この記事を読んで、RESTful な Web サービスは理解しやすく、実装するのも簡単だとわかっていただければ本望です。以下の「参考文献」セクションに記載した有益なリンクにも是非アクセスしてください。



参考文献

学ぶために

製品や技術を入手するために
  • XIBM ソフトウェアの試用版を使用して、次の開発プロジェクトを革新してください。ダウンロード、あるいは DVD で入手できます。


議論するために


著者について

Shailesh Mishra photo

Shailesh K. Mishra は、インド、グルガオン所在の IBM ソフトウェア研究所のソフトウェア・エンジニアです。現在、「BizPortlets」プロジェクトに従事しており、ビジネス・インテグレーションを専門分野としています。




記事の評価


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



 


 


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


この記事を共有する

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