Apache Wink による RESTful な Web サービス: 第 1 回 Apache Wink REST サービスを作成する

RESTful なサービス開発のポイント

3 回連載の第 1 回目となるこの記事で、REST ベースの Web サービスを実装して使用するための新しい Java™ フレームワーク、Apache Wink 1.0 の基本を学んでください。

Vishnu Vettrivel , Principal Consultant, PunditLabs

Photo of Vishnu VettrivelVishnu Vettrivelは、企業向けコンサルティングおよび技術を専門とする PunditLabs の主任コンサルタントで、10 年以上にわたり、ミッション・クリティカルなエンタープライズ・アプリケーションの構築、設計、開発に携わっています。フォーチュン 50 社に挙げられたさまざまなクライアントに協力し、多くの新しい技術に対する戦略的技術計画を立ててきました。



2010年 2月 09日 (初版 2010年 1月 19日)

この記事では Apache Wink 1.0 フレームワークのアーキテクチャーを概説し、Apache Wink による新しい RESTful なサービスを設計、実装、デプロイする方法を説明します。この記事は、REST パラダイムの基本を理解する上で役に立つとともに、Java 開発者がアノテーションを使用して RESTful な Web サービスを実装する上でも役立つように、新しい標準 JAX-RS 1.0 についても詳しく説明します。

よく使われる頭字語

  • API: Application Programming Interface
  • CSV: Comma-Separated Values
  • HTML: HyperText Markup Language
  • HTTP: HyperText Transfer Protocol
  • JSON: JavaScript™ Object Notation
  • OOP: Object-Oriented Programming
  • REST: Representational State Transfer
  • RSS: Really Simple Syndication
  • URI: Uniform Resource Identifier
  • WAR: Web Archive
  • WSDL: Web Services Description Language
  • XML: Extensible Markup Language

REST の紹介

まずは、REST を簡単に紹介するところからはじめましょう。REST (Representational State Transfer) とは、World Wide Web のベースとなっているアーキテクチャーの原則の集まりであり、Roy Thomas Fielding の博士論文「Architectural Styles and the Design of Network-based Software Architectures」のなかで初めて紹介されました。Fielding はこの論文で REST のアーキテクチャーの原則として以下の 5 つを規定し、その延長線上で World Wide Web を規定しています。

  • アドレス指定可能であること。REST では何もかもがリソースの概念に基づきます。OOP でのオブジェクトすなわち名詞とは違い、リソースは抽象概念です。そのため、アドレス指定可能でなければなりません。つまり、URI を介して到達可能であるということです。
  • インターフェースが統一されていること。SOAP や他の標準とは異なり、REST ではリソースの操作に使用するメソッドすなわち動詞に原則を設けることを規定しています。これは、RESTful なサービスの開発者が使用できるのは、HTTP がサポートするメソッド (GETPUTPOSTDELETE など) だけであることを意味します。そのため、WSDL のようなサービス記述言語を使用する必要はありません。
  • ステートレスであること。スケーラビリティーを確保するため、サーバー・サイドはクライアントの状態情報を保管しません。したがって、サーバーが特定のクライアントに束縛されることはなくなり、ロード・バランシングが遥かに単純になります。さらにサーバーの監視が容易になる上、ネットワーク障害に対する信頼性が高くなるという付加価値もあります。
  • 表現を使用すること。クライアントは常に、何らかのリソース表現と対話し、リソース自体と直接対話することはありません。1 つのリソースに複数の表現がある場合もありますが、リソース表現を保持するクライアントは理論上、そのリソース表現の背後にあるリソースを操作するのに十分な情報を持っているはずです。
  • 連結性があること。あらゆる REST ベースのシステムは、クライアントが関連リソースへアクセスする必要があることを前提とし、リソース表現に関連リソースを含めて返します。例えば、特定の RESTful なサービスに対する一連のアクションにおける関連ステップをハイパーリンクとして組み込み、クライアントが選択に応じてこれらのステップに従えるようにすることもできます。

JAX-RS

Web 上での REST

現在 Web 上では、以下のサイトで REST が使用されています。

  • Atom 出版プロトコル。REST プロトコルのなかで最も正統な実装の 1 つとして数えられている Atom は、ブログ配信の領域で広範に使用されています。
  • Sun の Cloud API。クラウドのリソース (コンピューター、ネットワーク、ストレージなど) を管理、作成するための Sun による RESTful な API です。
  • Digg の API。人気の高い新しいソーシャル Web サイトである Digg では、RESTful な API を使用して、ユーザーとパートナーがプログラムによってサイトおよびデータと対話できるようにしています。
  • Netflix API。DVD レンタル Web サイトの Netflix は、RESTful な API によって、タイトル・カタログへのきめの細かいアクセスを可能にするとともに、プログラムによってユーザー・キューを微調整し、お勧め映画の情報を取得します。
  • Flickr API。写真をアップロードして共有するための Web サイトである Flickr は、ユーザーが写真および写真コレクションのアップロード、置換、検索に使用できる RESTful な API を公開しています。

さらに別の Java 標準が必要になった理由は何かと言うと、JAX-RS は REST ベースの Java 開発を単純化するように新しく定義された標準で、Java アノテーションと POJO (Plain Old Java Object) を使用して RESTful なサービスを実装するという点に重点を置いています。これまでも、サーブレットを使用して RESTful なサービスを実装することはできましたが、ビジネス・ロジックの実装に HTTP が大きな妨げとなるのが常でした。

JAX-RS はそのような HTTP をすべて隠し、サーブレットを Java クラスの個々のメソッドに簡潔にバインドします。アノテーションが動的に HTTP リクエストから情報を抽出し、アプリケーションによって生成された例外を HTTP レスポンス・コードにマッピングすることも可能です。この他にも、JAX-RS が RESTful な Java Web サービスを実装する効果的な手段となる理由はさまざまにあります。


Apache Wink と REST

REST と出会った私が JAX-RS を経て最終的に辿り着いたのは Apache Wink です。Apache Wink 1.0 は JAX-RS 1.0 仕様の実装で、この仕様に完全に準拠するようにゼロから設計されました。この実装は使いやすくて、本番環境に即しているだけでなく、コアとなる JAX-RS 仕様を拡張する一連の機能を提供します。

Apache Wink ランタイムのアーキテクチャーは、JAX-RS 1.0 仕様にそのまま従った実装です。Java EE (Java Platform, Enterprise Edition) 環境にデプロイされる Apache Wink は、大まかに言うと以下の 3 つのコンポーネントからなります。

  • Apache Wink の RestServletRestServlet は、Web アプリケーションの Java EE web.xml 記述子ファイルに構成されます。このサーブレットはすべての HTTP Web サービス・リクエストの主要なエントリー・ポイントとしての役割を持ち、リクエストおよびレスポンス・オブジェクト・インスタンスのその後の処理をリクエスト・プロセッサーに委任します。
  • リクエスト・プロセッサー。RequestProcessor は、Apache Wink の RestServlet によって初期化されるコア Apache Wink エンジンです。リクエスト・プロセッサーはリクエストの URI を使用して、対応するリソースのクラスおよびメソッドを検索し、突き合わせ、呼び出します。リクエストの処理中に例外が発生すると、RequestProcessor はその例外を処理するためにエラー・ハンドラー・チェーンを呼び出します。
  • リソース。REST では、Web サービスを表すコンポーネントやオブジェクトのすべてがリソースと呼ばれます。リソースは、そのリソースを表す多くの表現のいずれかによってデータの取得と操作を可能にします。リソースを実装する POJO は、リソース・クラスとして知られています。これらのリソース・クラスが、基礎となるビジネス・ロジックを実際に処理するリソース・メソッドを実装します。

このリクエスト・サイクル全体が、Apache Wink ロジック・フローと呼ばれます (図 1 を参照)。

図 1. Apache Wink ロジック・フロー
ロジック・フローを示す図。データは、リクエスト・プロセッサー、Apache Wink ランタイム、Apache Wink REST サーブレット、HTTP クライアント、そしてリソースおよびアプリケーション・コードとの間で受け渡されます。

Apache Wink は RESTful な Web サービスの実装に役立つだけではありません。強力なクライアント・ライブラリーによって、RESTful な Web サービスを容易に使用できるようにします。さらに、Apache Wink と一緒にパッケージ化された一連の組み込みプロダイバーが、開発者が業界標準のデータ・フォーマット (XML、Atom、RSS、JSON、CSV、HTML) をサポートする際に支援します。


RESTful な設計

それでは、実際にコーディングを行ってみましょう。作業を面白くするために、これから Apache Wink 1.0 で一風変わった RESTful なサービスを設計、実装、デプロイします。このサービスは、PayPal の Payflow 支払いゲートウェイ・サービスの RESTful なラッパーです。Payflow はインターネット上でのクレジット・カード決済を可能にするサービスですが、このサンプル・アプリケーションではトランザクションに関する問い合わせ機能にだけ焦点を絞ります。この機能によって、認証済みユーザーの固有 ID を指定すると、そのユーザーに関するトランザクションのステータスを調べることができます。


リソース/URI の設計

まずは、このサービスのインターフェース・モデルを定義して URI を割り当て、正式に REST のリソースにするところから取り掛かります。このサービスで扱うのはトランザクションのステータスだけなので、リスト 1 に記載する URI を公開することになります。

リスト 1. トランザクション・サービスの URI パターン
/transactions
/transactions{id}

/transactions という URI は、システム内でのすべてのトランザクションを表します。個々のトランザクションのステータスを検索するには、/transactions{id} を使用します。ここで、{id} は、トランザクション・モデルのトランザクション ID に対応する英数字からなる一意の値です。また、特定のユーザーを認証する場合には、リスト 2 のパターンを使用します。このパターンに含まれる UNAMEVNAMEPNAME、および PWD は、サインアップ時にユーザーに割り当てられる Payflow ゲートウェイのログイン資格情報の一部です。ただし、これらの資格情報がネットワーク上でインターセプトされたり、キャッシュされたりするのを避けるには、暗号化された HTTPS 接続を使用し、リクエスト・ヘッダーのパラメーターとして資格情報を渡すようにすることをお勧めします。

リスト 2. クエリー・ストリングにユーザー資格情報を設定した URI パターン
GET /transactions{id}
username=UNAME
vendor=VNAME
partner=PNAME
password=PWD

一般に、URI の構造が外部に公開されると、クライアント開発者によってその URI への接続が行われる可能性があり、サーバーが URI 空間を自由に変更できなくなる可能性があります。しかしこの記事では、その設計上の制約を無視することにします。


データの設計

あらゆる RESTful なインターフェースは、クライアントに対してサポートする各種の表現を決定しなければなりません。Apache Wink 1.0 でサポートできるオプションには XML、JSON、HTML、Atom などがありますが、この例では JSON を使用します。JSON はよく使用されているフォーマットで、Ajax アプリケーションでは JavaScript コードを利用しやすいからです。一例として、リスト 3 に JSON ストリングとしてフォーマットされたトランザクションのステータスの表現を記載します。

リスト 3. JSON ストリングとしてフォーマットされたトランザクションのステータスのレスポンス
{
 "RESULT":19,"PNREF":"V19A2A1A7CC5",
 "RESPMSG":"Original transaction ID not found: V19A2A192BE9",
 "AUTHCODE":null,"CVV2MATCH":null,"AVSADDR":null,
 "AVSZIP":null,"IAVS":null,"CARDSECURE":null
}

レスポンス用のデータ・フォーマットとして JSON を使用すると、実際に使われている JSON 構造に関する追加の情報をサービス・レベルで持たなければならない可能性があることは、覚えておくとよいでしょう。


HTTP メソッドの設計

最後に、どの HTTP メソッドを使用してリソースとその機能を操作するかを決定しなければなりません。ここで重要な点は、HTTP メソッドの従来の使用方法に従うことです。その方法から逸脱しないようにしてください。例えば、GET メソッドは安全な読み取り専用のべき等呼び出しであるべきなので、リソースの状態をいかなる形でも変更してはなりません。この指針に従わないと、複雑なことになり、クライアントに混乱を招きます。この例の場合に必要な操作は、単一のトランザクションのステータスを読み取り専用で検索することなので、URI パターンを使用した GET メソッドがふさわしいのは明らかです (リスト 4 を参照)。

リスト 4. トランザクション・サービスの URI パターンの例
/transactions{id}

それぞれの GET 呼び出しによって、クエリー対象のトランザクションのステータスが JSON フォーマットのデータとして返されます (リスト 5 を参照)。

リスト 5. トランザクション ID が設定された GET リクエスト
GET /transactions/V19A2A192BE9 HTTP/1.1

ただし、トランザクションのステータスの問い合わせを行うこのモデルには、1 つの問題があります。それは、このサービスには、トランザクションのステータスを問い合わせるユーザーが本当にそのトランザクションの所有者であることを認証する手段がないことです。この問題を解決するには、クライアントがその固有のログイン資格情報をリクエスト・ヘッダーのパラメーターとして URI で渡せるようにすることで、ユーザー認証を可能にする必要があります (リスト 6 を参照)。

リスト 6. GET リクエストと、リクエスト・ヘッダーのパラメーターとして組み込まれたセキュリティー資格情報
GET /transactions/V19A2A192BE9 HTTP/1.1
user=winktest
vendor=winktest
partner=PayPal
pwd=wink123

Apache Wink サービスの実装

Apache Wink サービスは、POJO またはプレーン Java クラスとして実装されます。POJO やプレーン Java クラスは、JAX-RS アノテーションを使用して、受信した HTTP リクエストを Java メソッドにマッピングします。デフォルトで、サービスはシングルトンとなるはずですが、それが可能でなければリクエストごとにサービスが作成されます。この例では、Apache Wink の RESTful なサービスを実装する TransactionResource クラスを作成します。このクラスは受信したステータス検索リクエストを構文解析し、ユーザー資格情報を認証してから、Payflow ゲートウェイ・サービスを呼び出して、JSON オブジェクト・フォーマットでトランザクションのステータスを返します。リスト 7 に、TransactionResource クラスから抜粋したコード・スニペットを記載します。

リスト 7. Apache Wink サービスの Java クラスのスニペット
package org.openengine.wink.example.payflow;
import ...;
	
@Path("/transactions")
public class TransactionResource {   
	
@GET
@Path("{pnref}")
@Produces(MediaType.APPLICATION_JSON)
public JSONObject doInquiry(@PathParam("pnref") String pnref,  
	@HeaderParam("user") String userName, 
	@HeaderParam ("vendor") String vendorName, 
	@HeaderParam ("partner") String partnerName,
	@HeaderParam ("pwd") String password) {
	try {
		if(userName!=null && vendorName!=null 
                  && partnerName!=null && password!=null)
        	return getTxnStatus(pnref, userName, 
                            vendorName, partnerName, password).toString();
        	else
                    throw new WebApplicationException(Response.Status.UNAUTHORIZED);	
	} catch (JSONException e) {
		throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
	}
} 
....

@javax.ws.rs.Path アノテーションは、このクラスが JAX-RS サービスであることを示します。すべての JAX-RS サービスには、このアノテーションが必要です。@Path アノテーションの値として設定されている /transactions は、トランザクション・サービスの URI の相対パスを示します。

@GET アノテーションが意味するのは、メソッド自体のマッピング先となる HTTP 動詞です。メソッド・レベルでの @Path アノテーションの値は、メイン URI との相対サブルートを参照します。メソッド・レベルでの @Path@PathParam に含まれる {pnref} は、トランザクションの固有 ID の値です。例えば、受信した URI が /transactions/V19A2A192BE9 の場合、V19A2A192BE9 ストリングが getTxnStatus メソッドの {pnref} パラメーターに注入されます。

@javax.ws.rs.HeaderParam アノテーションは @PathParam と似ていますが、個々のリクエスト・ヘッダーのパラメーターを Java パラメーターに注入するという点が異なります (リスト 8 を参照)。

リスト 8.URI とリクエスト・ヘッダーのパラメーター
/transactions/V19A2A192BE9
user=winktest
vendor=winktest
partner=PayPal
pwd=wink123

Apache Wink サービスの構成

Apache Wink アプリケーションは一般に Apache Tomcat のようなサーブレット・コンテナーにデプロイされ、WAR ファイルとしてパッケージ化されます。他のあらゆる Web アプリケーションと同じく、Apache Wink サービスにも web.xml ファイルが必要です。リスト 9 に、サンプル Apache Wink サービスで使用する web.xml ファイルの内容を記載します。

リスト 9. Web 構成ファイルである web.xml
<web-app>
	<display-name>Wink demo</display-name>
	<description>Demonstration of SDK features</description>

	<!-- Wink SDK servlet configuration. 
		This servlet handles HTTP requests
		of SDK web service on application server.-->
				
	<servlet>
		<servlet-name>restSdkService</servlet-name>
		<servlet-class>
			org.apache.wink.server.internal.servlet.RestServlet
		</servlet-class>
		<init-param>
			<param-name>applicationConfigLocation</param-name>
			<param-value>/WEB-INF/application</param-value>
		</init-param>
	</servlet>

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

ご覧のように、web.xml ファイルでは、Apache Wink RestServlet がその url-pattern と併せて定義されています。また、ここには RestServlet の初期化パラメーターもあり、その値は /WEB-INF/application ディレクトリー内にあるファイルを指しています。このファイルには、JAX-RS がデプロイするはずのクラスとオブジェクトのすべてが記載されています。この構成ファイルがなくても、Apache Wink サービスで実装しているリソースをプログラムによって一覧にするアプリケーション・クラスを実装することはできますが、この例ではアプリケーション構成ファイルの手法を使用します (リスト 10 を参照)。

リスト 10. アプリケーション構成ファイル
org.openengine.wink.example.payflow.TransactionResource

Apache Wink サービスの実行

このサービスを実行するには、アプリケーションをビルドして Tomcat にデプロイする必要があります。それには以下の手順に従ってください。

  1. ダウンロード」から PayFlow サンプル・プロジェクトをダウンロードします。
  2. PayFlow プロジェクトのコンテンツを C ドライブのフォルダーに抽出します。C:\PayFlow ディレクトリーは図 2 のような構造になっているはずです。
    図 2. PayFlow サンプル・プロジェクトのディレクトリー構造
    dist、lib、source の 3 つのディレクトリーと build.xml ファイルが表示されたウィンドウ
  3. JAVA_HOME 変数と ANT_HOME 変数をそれぞれ、Java インストール・ディレクトリー、Apache Ant インストール・ディレクトリーに設定します
  4. システム PATH 変数に JAVA_HOME/bin および ANT_HOME/bin を追加します。
  5. C:\PayFlow ディレクトリーから Ant を実行し、PayFlow プロジェクトの Ant ビルドを開始します。

    このステップによって、PayFlow プロジェクトがビルドされ、PayFlow.war という名前のファイルが作成されます (図 3 を参照)。

    図 3. Ant スクリプトのビルドによる出力
    Ant スクリプト・ビルド・コードを示すコマンド・プロンプト。PayFlow.war ファイルが正常にビルドされたことが示されています。
  6. PayFlow.war ファイルを、TOMCAT ホームの下にある webapps デプロイメント・ディレクトリーにコピーします (図 4 を参照)。
    図 4. Tomcat サーバーへの PayFlow プロジェクトのデプロイメント
    webapps ディレクトリーのサブディレクトリー docs、examples、host-manager、および ROOT と、PayFlow.war ファイルが表示されたウィンドウ
  7. TOMCAT_HOME\bin フォルダー内にある startup.bat ファイルを実行して、Tomcat Web サーバーを起動します。
  8. DOS コマンド・プロンプトを立ち上げます。
  9. コマンド・プロンプトから telnet localhost 8080 と入力します(この URI は、Tomcat Web サーバーがポート 8080 でリッスンするように構成されていることを前提とします)。
  10. 自分が行っている内容を確認するには Ctrl+] を押す (Ctrl キーを押下した状態で右角括弧を押します) のに続けて set localecho と入力することで、ローカル・エコーを有効にします。
  11. 空白行で Enter キーを押します。
  12. 以下の内容を入力します。
    GET /PayFlow/rest/transactions/V19A2A192BE9 HTTP/1.1
    user: winktest
    vendor: winktest
    partner: PayPal
    pwd: wink123
    Host: localhost
  13. Enter キーを 2 回押します。

    telnet の出力には JSON フォーマットのトランザクション・ステータスが表示されるはずです (図 5 を参照)。

    図 5. トランザクション・ステータスが含まれている JSON レスポンス
    トランザクション・ステータスが含まれている DOS プロンプト

まとめ

この記事では、REST アーキテクチャーの基本と、RESTful なサービスの実装を単純化することを目的とした新たな Java 標準 JAX-RS について概説しました。具体的に焦点としたのは、JAX-RS 1.0 仕様に完全に準拠した、使いやすい実装としてゼロから設計された新しいフレームワーク Apache Wink 1.0 です。Apache Wink の基本的なアーキテクチャーを説明した後、実際に新しいサンプル Apache Wink Web サービスを設計、実装し、このサービスをデプロイして実行するために必要な手順を説明しました。REST、JAX-RS、Apache Wink 1.0 フレームワークについてさらに詳しく学ぶには、この記事の「参考文献」を参照してください。


ダウンロード

内容ファイル名サイズ
Apache Wink service implementationPayFlow.zip2.51MB

参考文献

学ぶために

製品や技術を入手するために

  • Apache Wink: Apache Wink をダウンロードして、最新バージョンのソース・コードとバイナリー、そしてその他のサンプル・プロジェクトを入手してください。
  • Apache Tomcat Web Server バージョン 6.x: Tomcat をダウンロードしてください。
  • Apache Ant:Ant をダンロードしてください。
  • IBM Java JDK: IBM の JDK をダウンロードしてください。
  • 製品評価用 IBM 試用版ソフトウェア: developerWorks から直接ダウンロードできる試用版ソフトウェアで、次のプロジェクトを構築してください。DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® によるアプリケーション開発ツールおよびミドルウェア製品の試用版が揃っています。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=467965
ArticleTitle=Apache Wink による RESTful な Web サービス: 第 1 回 Apache Wink REST サービスを作成する
publish-date=02092010