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

developerWorks Japan  >  SOA and Web services | Open source  >

Spring、Apache CXF を使用した POJO Web サービスの設計と実装: 第 2 回 RESTful な Web サービスを作成する

developerWorks
ページオプション

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

議論する

ダウンロード

原文はこちら

原文はこちら


レベル: 中級

Rajeev Hathi, Senior Software Consultant
Naveen Balani, Software Architect, IBM

2008年 09月 25日

オープンソースの Web サービス・フレームワーク、Apache CXF を使って、Spring Bean として定義した RESTful な Web サービスを作成してください。この記事では、REST (Representational State Transfer) アーキテクチャーの機能とこのアーキテクチャーを使用した場合の利点を探り、CXF の REST API を使うと簡単に RESTful なサービスを開発できることを説明します。

はじめに

この記事で構築するのは注文用アプリケーションで、アプリケーションの機能は CXF と Spring を使用した RESTful な Web サービスとして公開します。この Web サービスは注文リソースに対して read 操作と add 操作を行います。この記事を最後まで読めば、REST アーキテクチャー・スタイルの概念と機能を適用して、CXF ベースの REST API を使って RESTful な Web サービスを構築および開発できるようになっているはずです。

システム要件

この記事のサンプル・コードを実行するには、お使いのマシンに必ず以下のソフトウェアをインストールして、セットアップしてください。

  • Java™ 5 以降
  • Tomcat 5 以降
  • Ant ビルド・ツール
  • CXF バイナリー・ディストリビューション 2.1

上記のディストリビューションをインストールしたら、以下の環境変数を設定します。

  • JAVA_HOME (Java 用)
  • CATALINA_HOME (Tomcat 用)
  • ANT_HOME (Ant 用)
  • CXF_HOME (CXF 用)

一例として、CXF_HOME=C:\apache-cxf-2.1 と設定し、PATH 環境変数に以下の内容を追加します。

  • JAVA_HOME\bin
  • CATALINA_HOME\bin
  • ANT_HOME\bin



上に戻る


REST -- Web アーキテクチャー

Web サービスは極めて複雑になり得ます。それは、Web サービスの開発に伴って実装しなければならない WSDL (Web Services Description Language) や SOAP などといった各種のインフラストラクチャー・コンポーネントは、さらに他のさまざまな標準に結び付けられているためです。Web サービス・ソリューションを提供するすべての Web サーバーには、堅牢な Web サービス・インフラストラクチャー・モデルを作成するという点から多大な投資が必要になってきます。また、開発者の立場からすると、技術を習得するのがますます難しくなってきています。しかし恐れることはありません。REST が救いの手を差し伸べてくれます。

RESTful な Web サービスは単純な XML-over-HTTP サービスです。通常の Web サービスではプロバイダーとコンシューマーの間で定義し、交渉しなければならない契約がさまざまにあります。しかし RESTful なサービスはそれとは異なり、データを単純な XML フォームにカプセル化して、まさに Web サーバーに対して Web ページをリクエストするのと同じように HTTP で転送します。

REST は実装や標準というよりはむしろアーキテクチャーです。REST アーキテクチャー・スタイルは Web リソースに関連付けられます。Web リソースとはつまり、URI (Uniform Resource Indicator) で識別される表現 (例えば、http://myweb.com/myresource) で、注文、顧客、従業員などの永続エンティティーにすることもできます。クライアントは URI を使用してリソースに問い合わせを行ったり、リソースを更新したりするため、クライアントによってそのリソース表現の状態は変化します。簡単に言うと、クライアント・プログラムはさまざまな HTTP メソッドと URI により Web リソースにアクセスしたり、Web リソースを更新、追加、または削除したりすることができるため、それによってリソース表現の状態も変わるということです。使用する HTTP メソッドには、GETPOSTPUT、および DELETEがあります。

要するに REST は、ユーザーが Web リソースでの操作を Web サービス・スタイルで HTTP リクエスト・メソッドを使って起動するための標準的な方法を規定する 1 つの仕様に過ぎません。REST は HTTP と密接に関連し、メソッド、ヘッダー、タイプをはじめとする HTTP 機能のすべてを利用します。

REST と CXF

CXF は、Web サービスを手軽に構築および開発できるようにする単純な API を提供するオープンソースの Web サービス・フレームワークです。この連載第 1 回では、Spring ベースの CXF 構成を使用すると簡単に Web サービスを開発できることを説明しました。この連載第 2 回では、RESTful なサービスを開発するのも同じく簡単だということを説明します。

CXF が提供する RESTful なスタイルの Web サービス実装では、以下の 3 つを利用することができます。

  • JAX-RS (JSR-311)
  • HTTP バインディング
  • JAX-WS (Java API for XML Web Services) の Provider および Dispatch API



上に戻る


注文用アプリケーション

ここからは、ユーザーが注文を作成し、その詳細を読み取ったり、表示したりできる注文用アプリケーションを作成します。これらの関数を呼び出し、注文用アプリケーションを管理するために使用するのは、CXF による RESTful なアーキテクチャー・スタイルです。アプリケーションを開発する前に、以下のユースケースを定義しておきます。

  1. ユーザーが注文を作成する (固有の注文 ID を生成)。
  2. ユーザーが注文の詳細内容を (注文 ID をベースに) 照会する。
  3. ユーザーがすべての注文を照会する。

それぞれの操作は、Web サービスを呼び出す一般的な方法として、URI を使用して呼び出されます。各操作は GETPOSTPUTDELETE のうち、いずれかの HTTP リクエスト・メソッドに関連付けられます。この API は JRA (Java Rest Annotation) を使用して、操作と HTTP/URI 動詞の組み合わせをマッピングします。JRA/動詞の組み合わせは、表 1 のとおりです。


表 1. JRA/動詞のマッピング・テーブル
JRAHTTP リクエスト・メソッド動詞
@GetGET取得
@PostPOST追加/作成
@PutPUT更新
@DeleteDELETE削除

RESTful なサービスを開発する

RESTful な Web サービスを開発するには、まず SEI (Service Endpoint Interface) と実装クラスを作成し、続いてこの 2 つを Spring ベースの CXF 構成ファイルを使用して接続します。実行するステップは以下のとおりです。

  1. SEI を作成して REST アノテーションを付けます。
  2. 実装クラスを作成します。
  3. beans.xml を作成し、HTTP バインディングを使用してサービス・クラスを Spring Bean として定義した後、JAX-WS エンドポイントとして公開します。
  4. web.xml を作成します。

ここで作成するのは OrderProcess という名前の SEI で、この SEI がリソース表現インターフェースとして機能します。Order クラスは、リソース・クラスの 1 つです。リスト 1 に、OrderProcess SEI を記載します。


リスト 1. OrderProcess SEI
@WebService(targetNamespace = "http://demo.order")
public interface OrderProcess {

  // Get all the orders
  @Get
 @HttpResource(location = "/orders")
 @WebResult(name = "Orders")
 public Orders getOrders();

  // Get order data based on the specified order ID
  @Get
 @HttpResource(location = "/orders/{id}")
 public Order getOrder(@WebParam(name = "GetOrder") GetOrder getOrder);

  // Add an order
  @Post
 @HttpResource(location = "/orders")
 public void addOrder(@WebParam(name = "Order") Order order);
}

OrderProcess SEI には以下の 3 つのメソッドがあります。

  • getOrder は、指定された注文 ID をベースに単一の注文データを返します。
  • getOrders は、すべての注文を返します。
  • addOrder は、注文を追加するために使用します。このメソッドは Order Bean を引数に取ります。

上記の 3 つのメソッドは REST アノテーションを使用して定義し、URI で識別してください。getOrder メソッドと getOrders メソッドには @GET アノテーションを使用し、addOrder メソッドには @POST を使用します。メソッドのそれぞれを識別する手段は、@HttpResource アノテーションによって定義した URI です。URI のマッピングは表 2 のようになります。


表 2. メソッド/URI マッピング・テーブル
メソッドURI
getOrder/orders/{id}
getOrders/orders
addOrder/orders

これで、OrderProcessImpl 実装クラスを作成する準備が整いました (リスト 2 を参照)。


リスト 2. OrderProcessImpl サービスの実装
@WebService(endpointInterface = "demo.order.OrderProcess")
public class OrderProcessImpl implements OrderProcess {

 Map<String, Order> orders = new HashMap<String, Order>();
  private int i;

  public Orders getOrders() {
   Orders o = new Orders();
   o.setOrder(orders.values());
   return o;
  }

  public Order getOrder(GetOrder order) {
   String orderID = order.getId();
   return orders.get(orderID);

  }

  public void addOrder(Order order) {
   String orderID = "ORD0" + (++i);
   // Added as a POST request
   String customerName = order.getName(); 

   Order newOrder = new Order();
   newOrder.setOrderID(orderID);
   newOrder.setName(customerName);

   orders.put(orderID, newOrder);
   System.out.println("Order added successfully");
 }
}

REST インターフェースが用意できたので、その実装内容を見ていきましょう。OrderProcessImpl クラスは SEI を実装するため、それによって SEI のメソッドも実装されることになります。addOrder メソッドは注文の詳細を、注文 ID と Order インスタンスがそれぞれキーとその値として設定されたハッシュマップに取り込みます。Order Bean が持つプロパティーは、注文 ID と顧客名の 2 つです。顧客名が POST リクエスト・メソッドによって追加されると、注文 ID が生成されます。getOrder メソッドは注文 ID を引数として取り、対応する注文をハッシュマップから取得してそのまま返します。一方、getOrders メソッドはハッシュマップにあるすべての注文を返します。

次のステップは、beans.xml 構成ファイルを作成することです (リスト 3 を参照)。


リスト 3. beans.xml 構成ファイル
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

 <import resource="classpath:META-INF/cxf/cxf.xml" />
 <import resource="classpath:META-INF/cxf/cxf-extension-http-binding.xml" />
 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> 

 <jaxws:endpoint 
  id="orderProcess" 
  implementor="demo.order.OrderProcessImpl" 
  address="/"
  bindingUri="http://apache.org/cxf/binding/http" >
    <jaxws:serviceFactory > 
   <bean class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean">
 <property name="wrapped" value="false" />
   </bean>
    </jaxws:serviceFactory > 
 </jaxws:endpoint >
	  
</beans>

OrderProcessImpl の Bean 定義は、JAX-WS エンドポイントとしてラップされ、バインディング URI は http://apache.org/cxf/binding/http に設定されます。このバインディング URI は、サービスが HTTP バインディング・メソッドによってリソースにバインドされていることを示します。アドレスは / で、これは Web コンテキストとの相対アドレスです。JaxWsServiceFactoryBean は wrapped 属性を false に設定するように指定します。これはつまり、この Bean のリクエスト/レスポンスの XML ベースのデータの操作名は、ルート要素でラップされないことを意味します。


リスト 4. web.xml Web 構成ファイル
<web-app>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>WEB-INF/beans.xml</param-value>
 </context-param>

 <listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>

 <servlet>
  <servlet-name>CXFServlet</servlet-name>
  <display-name>CXF Servlet</display-name>
  <servlet-class>
   org.apache.cxf.transport.servlet.CXFServlet
  </servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>CXFServlet</servlet-name>
  <url-pattern>/*</url-pattern>
 </servlet-mapping>
</web-app>

最後に作成するのは、CXF 構成ファイルをロードする web.xml ファイルです。このファイルを作成したら、Spring コンテキスト・ローダーを使用して構成ファイルをロードしてください。また、クライアント・プログラムからのすべてのリクエストを処理する CXFServlet を登録する必要もあります。

クライアントを開発する

POST リクエストには、クライアント・クラス Client を作成します。リスト 5 の Client クラスが、新しい注文を追加します。


リスト 5. POST リクエストを処理する Client クラス
public final class Client {

 public static void main(String[] args) throws Exception {
  String xml = null;
  try {
   // Make an HTTP connection to the server
   URL u = new URL("http://localhost:8080/orderapp_rest/orders");
   HttpURLConnection httpCon = (HttpURLConnection) 
   u.openConnection();
   // Set the request method as POST
   httpCon.setRequestMethod("POST"); 
   httpCon.setDoOutput(true);

   OutputStream os = httpCon.getOutputStream();
   // XML encoded in UTF-8 format
   OutputStreamWriter wout = new OutputStreamWriter(os, "UTF-8"); 
   wout.write("<?xml version=\"1.0\"?>\r\n");  
   // Add customer name as XML fragment
   wout.write("<order xmlns=\"http://demo.order\">
   <name>Rajeev</name></order>r\n"); 
   wout.flush();

   // Make implicit connection to the server
   httpCon.getContentLength(); 
   httpCon.disconnect();
   
   os.close();
  } catch (IOException e) { 
   e.printStackTrace();
  }
 }
}

上記のクラスは http://localhost:8080/orderapp_rest/orders に HTTP で接続し、XML データを POST リクエストとして送信します。この XML は、追加される注文の詳細で構成されます。追加されるのは顧客名で、注文 ID は自動的に生成されます。URL が呼び出されると、注文 ID と顧客名が Map コレクションに追加されます。

GET リクエストの場合は、ブラウザーで http://localhost:8080/orderapp_rest/orders/ORD01 にナビゲートするだけで注文詳細を取得することができます。すると、注文 ID ORD01 の注文データが含まれる XML 要素が表示されます。顧客が行ったすべての注文を表示する場合も、同様にブラウザーで http://localhost:8080/orderapp_rest/orders にナビゲートするだけです。

図 1 は、ブラウザーに URL として http://localhost:8080/orderapp_rest/orders/ORD01 と指定した場合の出力です。


図 1. GET リクエストの場合のブラウザー出力




上に戻る


まとめ

この記事では GET メソッドと POST メソッドの使用例を紹介し、REST アーキテクチャー・スタイルの機能と概念、そして CXF でこのアーキテクチャーを使用して RESTful なサービスを開発する方法を説明しました。

RESTful な HTTP は、リソースにアクセスして操作する方法に独特の概念をもたらし、Web サービス開発にまったく新しい側面を与えます。Web ベースの開発がますます一般的に使われるようになるにつれ、REST 技術は改善の一途を辿っています。





上に戻る


ダウンロード

内容ファイル名サイズダウンロード形式
Order applicationorderapp_rest.zip12KBHTTP
ダウンロード形式について


参考文献

学ぶために

製品や技術を入手するために
  • IBM 製品の評価版をダウンロードして、DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® のアプリケーション開発ツールとミドルウェア製品を使ってみてください。


議論するために


著者について

Rajeev Hathi's photo

Rajeev Hathi は、J2EE プラットフォームのソフトウェア・コンサルタントです。J2EE をベースとしたアプリケーションの設計を専門とする彼は、Java および J2EE 技術分野 (Web、EJB、Architect) での SUN 認証を獲得しています。IBM developerWorks には Ajax、Web サービス、DB2、XML 関連の記事で貢献しています。さらに、Java 6 の適用方法に関する本『Hands on Web Services』の共著者でもあります。彼が拠点とするのはインドのムンバイで、スポーツ観戦とロックを聴くことを趣味としています。


Naveen Balani's photo

Naveen Balani は、IBM India Software Labs (ISL) のアーキテクトで、ISLでは WebSphere Business Services Fabric の設計および開発作業のリーダーを務めています。新しい技術の調査に積極的な彼は、IBM developerWorks ではお馴染みの寄稿者でもあり、今まで Web サービス、ESB、JMS、SOA、アーキテクチャー、オープンソース・フレームワーク、セマンティック Web、J2ME、パーベイシブ・コンピューティング、Spring、Ajax、そしてさまざまな IBM 製品についての記事を書いています。また、『Beginning Spring Framework 2』、『Getting Started with IBM WebSphere Business Services Fabric V6.1』の共著者でもあります。




記事の評価


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



 


 


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


この記事を共有する

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、IBM ロゴ、ibm.com、DB2、developerWorks、Lotus、Rational、Tivoli、および WebSphere は、International Business Machines Corporation の米国およびその他の国における商標です。これらおよび他の IBM 商標に、この情報の最初に現れる個所で商標表示 (® または TM) が付されている場合、これらの表示は、この情報が公開された時点で、米国において、IBM が所有する登録商標またはコモン・ロー上の商標であることを示しています。このような商標は、その他の国においても登録商標またはコモン・ロー上の商標である可能性があります。現時点での IBM の商標リストについては、www.ibm.com/legal/copytrade.shtml の「Copyright and trademark information」をご覧ください。 Adobe、Adobe ロゴ、PostScript、および PostScript ロゴは、Adobe Systems Incorporated の米国およびその他の国における登録商標または商標です。 Java およびすべての Java 関連の商標およびロゴは、Sun Microsystems, Inc. の米国およびその他の国における商標です。 他の会社名、製品名およびサービス名等はそれぞれ各社の商標です。

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