47.2. JAX-RS API の使用
47.2.1. JAX-RS アノテーションタイプ
標準の JAX-RS API は、値をフィールド、Bean プロパティー、およびメソッドパラメーターに注入するために使用できるアノテーションを指定します。アノテーションは、以下の 3 つのタイプに分割できます。
47.2.2. リクエスト URI からのデータの注入
概要
RESTful Web サービスを設計するためのベストプラクティスの 1 つとして、各リソースに一意の URI を設定する必要があります。開発者はこの原則を使用して、基盤となるリソースの実装に適量の情報を提供できます。リソースの URI テンプレートを設計する場合には、開発者は、リソースの実装に注入できるパラメーター情報を含めるようにテンプレートを作成できます。また、開発者はクエリーおよびマトリックスパラメーターを使用して、情報をリソース実装にフィードすることもできます。
URI のパスからのデータ取得
リソースの URI テンプレートの作成に使用される変数でリソースに関する情報を取得することが一般的なメカニズムです。これは、javax.ws.rs.PathParam
アノテーションを使用して実現されます。@PathParam
アノテーションには、データの注入元となる URI テンプレート変数を識別する単一のパラメーターがあります。
例47.1「URI テンプレート変数からのデータの注入」 では、@PathParam
アノテーションは URI テンプレート変数 color
の値が itemColor
フィールドにインジェクトされることを指定します。
例47.1 URI テンプレート変数からのデータの注入
import javax.ws.rs.Path; import javax.ws.rs.PathParam ... @Path("/boxes/{shape}/{color}") class Box { ... @PathParam("color") String itemColor; ... }
@PathParam
アノテーションでサポートされるデータ型は、「サポートされるデータタイプ」 で説明されているものとは異なります。@PathParam
アノテーションがデータを注入するエンティティーは、以下の型のいずれかでなければなりません。
PathSegment
値は、パスに一致する部分の最後のセグメントになります。
List<PathSegment>
この値は、名前付きの template パラメーターに一致するパスセグメントに対応する PathSegment オブジェクトの一覧です。
-
int
、char
、またはlong
などのプリミティブ -
単一の
String
引数を受け入れるコンストラクターを持つオブジェクト -
単一の
String
引数を受け入れる静的valueOf()
メソッドを持つオブジェクト
クエリーパラメーターの使用
Web に情報を渡す一般的な方法は、URI で クエリーパラメーター を使用することです。クエリーパラメーターは URI の最後に表示され、疑問符 (?
) で URI のリソース場所部分から区切られます。これらは、名前と値が等号 (=
) で区切られた 1 つ以上の名前と値のペアで設定されます。複数のクエリーパラメーターを指定すると、ペアはセミコロン (;
) またはアンパサンド (&
) で区切られます。例47.2「クエリー文字列のある URI」 は、クエリーパラメーターが含まれる URI の構文を示しています。
例47.2 クエリー文字列のある URI
http://fusesource.org?name=value;name2=value2;...
セミコロンまたはアンパサンドの いずれか を使用してクエリーパラメーターを区切ることができますが、両方は使用できません。
javax.ws.rs.QueryParam
アノテーションは、クエリーパラメーターの値を抽出し、それを JAX-RS リソースに注入します。アノテーションでは、パラメーターを 1 つ使用できます。このパラメーターをもとに、値の抽出、指定されたフィールド、Bean プロパティー、またはパラメーターにインジェクトされるクエリーパラメーターの名前が識別されます。@QueryParam
アノテーションは、「サポートされるデータタイプ」で説明されている型をサポートします。
例47.3「クエリーパラメーターのデータを使用したリソースメソッド」 は、クエリーパラメーター id
の値をメソッドの id
パラメーターに注入するリソースメソッドを示しています。
例47.3 クエリーパラメーターのデータを使用したリソースメソッド
import javax.ws.rs.QueryParam; import javax.ws.rs.PathParam; import javax.ws.rs.POST; import javax.ws.rs.Path; ... @Path("/monstersforhire/") public class MonsterService { ... @POST @Path("/{type}") public void updateMonster(@PathParam("type") String type, @QueryParam("id") String id) { ... } ... }
HTTP POST
を /monstersforhire/daikaiju?id=jonas に処理するには、updateMonster()
メソッドの type
は daikaiju
に設定され、id
は jonas
に設定されます。
マトリクスパラメーターの使用
URI クエリーパラメーターと同様に、URI マトリックスパラメーターは、リソース選択用の追加情報を提供できる名前と値のペアです。クエリーパラメーターとは異なり、マトリクスパラメーターは URI のどこにでも置くことができ、セミコロン (;
) を使用して URI の階層パスセグメントから区別されます。/mostersforhire/daikaiju;id=jonas には id
という 1 つのマトリクスパラメーターがあり、/monstersforhire/japan;type=daikaiju/flying;wingspan=40 には type
および wingspan
という 2 つのマトリクスパラメーターがあります。
リソースの URI を計算するときには、マトリックスパラメーターは評価されません。そのため、要求 URI /monstersforhire/japan;type=daikaiju/flying;wingspan=40 は /monstersforhire/japan/flying の処理に適したリソースを見つけるために使用される URI です。
マトリクスパラメーターの値は、javax.ws.rs.MatrixParam
アノテーションを使用してフィールド、パラメーター、または Bean プロパティーに注入されます。アノテーションでは、パラメーターを 1 つ使用できます。このパラメーターをもとに、値の抽出、指定されたフィールド、Bean プロパティー、またはパラメーターにインジェクトされるマトリックスパラメーターの名前が識別されます。@MatrixParam
アノテーションは、「サポートされるデータタイプ」で説明されている型をサポートします。
例47.4「マトリックスパラメーターのデータを使用するリソースメソッド」 は、マトリクスパラメーター type
および id
の値をメソッドのパラメーターに注入するリソースメソッドを表しています。
例47.4 マトリックスパラメーターのデータを使用するリソースメソッド
import javax.ws.rs.MatrixParam; import javax.ws.rs.POST; import javax.ws.rs.Path; ... @Path("/monstersforhire/") public class MonsterService { ... @POST public void updateMonster(@MatrixParam("type") String type, @MatrixParam("id") String id) { ... } ... }
HTTP POST
を /monstersforhire;type=daikaiju;id=whale に処理するには、updateMonster()
メソッドの type
は daikaiju
に設定され、id
は whale
に設定されます。
JAX-RS は URI の全マトリックスパラメーターを一度に評価するため、URI のマトリックスパラメーターの場所に、制約を適用することはできません。たとえば、/monstersforhire/japan;type=daikaiju/flying;wingspan=40 , /monstersforhire/japan/flying;type=daikaiju;wingspan=40, and /monstersforhire/japan;type=daikaiju; wingspan=40/flying はすべて、JAX-RS API を使用して実装される RESTful Web サービスと同等のものとして処理されます。
URI のデコードの無効化
デフォルトでは、すべてのリクエスト URI がデコードされます。そのため、URI /monster/night%20stalker と URI /monster/night stalker は同等です。自動 URI デコードを使用すると、ASCII 文字セット以外の文字をパラメーターとして送信しやすくなります。
URI を自動的にデコードしたくない場合は、javax.ws.rs.Encoded
アノテーションを使用して URI のデコードを非アクティブ化できます。アノテーションは、以下のレベルで URI のデコードを非アクティブにするために使用できます。
-
クラスレベル -
@Encoded
アノテーションでクラスをデコードすると、クラス内のすべてのパラメーター、フィールド、および Bean プロパティーの URI デコードが無効になります。 -
メソッドレベル -
@Encoded
アノテーションでメソッドをデコードすると、クラスのすべてのパラメーターの URI デコードが無効になります。 -
パラメーター/フィールドレベル - パラメーターまたはフィールドを
@Encoded
アノテーションでデコレートすると、クラスのすべてのパラメーターの URI デコードが無効になります。
例47.5「URI のデコードの無効化」は、getMonster()
メソッドが URI デコードを使用しないリソースを示しています。addMonster()
メソッドは、type
パラメーターの URI デコードのみを無効にします。
例47.5 URI のデコードの無効化
@Path("/monstersforhire/") public class MonsterService { ... @GET @Encoded @Path("/{type}") public Monster getMonster(@PathParam("type") String type, @QueryParam("id") String id) { ... } @PUT @Path("/{id}") public void addMonster(@Encoded @PathParam("type") String type, @QueryParam("id") String id) { ... } ... }
エラー処理
URI インジェクションアノテーションのいずれかを使用してデータを注入しようとすると、元の例外をラップする WebApplicationException 例外が生成されます。WebApplicationException 例外のステータスは 404
に設定されます。
47.2.3. HTTP メッセージヘッダーからのデータの注入
概要
通常、要求メッセージの HTTP ヘッダーとメッセージに関する一般的な情報、送信方法、および予想される応答の詳細を渡します。いくつかの標準ヘッダーが一般的に認識されて使用されていますが、HTTP 仕様では、任意の名前/値ペアを HTTP ヘッダーとして使用できます。JAX-RS API には、HTTP ヘッダー情報をリソース実装に注入する簡単なメカニズムがあります。
最も一般的に使用される HTTP ヘッダーの 1 つがクッキーです。Cookie を使用すると、HTTP クライアントとサーバーが複数の要求/応答シーケンスで静的情報を共有できます。JAX-RS API には、クッキーから直接リソース実装にデータを注入するアノテーションがあります。
HTTP ヘッダーからの情報の注入
javax.ws.rs.HeaderParam
アノテーションは、HTTP ヘッダーフィールドのデータをパラメーター、フィールド、または Bean プロパティーに注入するために使用されます。値が抽出され、リソース実装にインジェクトされる HTTP ヘッダーフィールドの名前を指定する単一のパラメーターがあります。関連するパラメーター、フィールド、または Bean プロパティーは、「サポートされるデータタイプ」 で説明されているデータタイプに準拠している必要があります。
If-Modified-Since ヘッダーの挿入 は、HTTP If-Modified-Since
ヘッダーの値をクラスの oldestDate
フィールドに注入するコードを示しています。
If-Modified-Since ヘッダーの挿入
import javax.ws.rs.HeaderParam; ... class RecordKeeper { ... @HeaderParam("If-Modified-Since") String oldestDate; ... }
クッキーからの情報の挿入
クッキーは特別な HTTP ヘッダータイプです。これらは、最初の要求でリソース実装に渡される 1 つ以上の名前と値のペアで設定されます。最初の要求後に、クッキーは各クッキーでプロバイダーとコンシューマーの間を行き来します。コンシューマーだけがリクエストを生成するため、Cookie を変更できます。クッキーは通常、複数の要求/応答シーケンス間でセッションを維持し、ユーザー設定やその他の永続化可能なデータを保存するために使用されます。
javax.ws.rs.CookieParam
アノテーションは、クッキーのフィールドから値を抽出し、これをリソース実装に注入します。このアノテーションでは、値が抽出される Cookie のフィールドの名前を指定する単一のパラメーターを使用できます。「サポートされるデータタイプ」に示されているデータ型に加え、@CookieParam
が付けられたエンティティーも Cookie
オブジェクトになることができます。
例47.6「クッキーの挿入」は、handle
クッキーの値を CB
クラスのフィールドに注入するためのコードを示しています。
例47.6 クッキーの挿入
import javax.ws.rs.CookieParam; ... class CB { ... @CookieParam("handle") String handle; ... }
エラー処理
HTTP メッセージのインジェクションアノテーションのいずれかを使用してデータを注入しようとすると、元の例外をラップする WebApplicationException 例外が生成されます。WebApplicationException 例外のステータスは 400
に設定されます。
47.2.4. HTML フォームからのデータの挿入
概要
HTML フォームでは、ユーザーから情報を簡単に取得する方法で、作成も簡単です。フォームデータは、HTTP GET
リクエストおよび HTTP POST
リクエストに使用できます。
- GET
-
フォームデータが HTTP
GET
リクエストの一部として送信されると、データはクエリーパラメーターのセットとして URI に追加されます。クエリーパラメーターからのデータの注入については、「クエリーパラメーターの使用」 で説明します。 - POST
-
フォームデータが HTTP
POST
の一部として送信されると、データは HTTP メッセージボディーに配置されます。フォームデータは、対象のフォームデータをサポートする通常のエンティティーパラメーターを使用して処理できます。また、@FormParam
アノテーションを使用してデータを抽出し、リソースメソッドのパラメーターに注入することによって処理することもできます。
@FormParam アノテーションを使用したフォームデータの挿入
javax.ws.rs.FormParam
アノテーションは、フィールド値をフォームデータから抽出し、値をリソースメソッドパラメーターに注入します。このアノテーションでは、値を抽出するフィールドのキーを指定する単一のパラメーターを指定できます。関連するパラメーターは、「サポートされるデータタイプ」 に記載のデータタイプに準拠する必要があります。
JAX-RS API Javadoc には、@FormParam
アノテーションをフィールド、メソッド、およびパラメーターに配置できると記載されています。ただし、@FormParam
アノテーションは、リソースメソッドパラメーターに配置する場合にのみ意味があります。
例
リソースメソッドパラメーターへのフォームデータの挿入 は、フォームデータをパラメーターに注入するリソースメソッドを示しています。このメソッドは、クライアントのフォームに文字列データが含まれる title
、tags
、および body
の 3 つのフィールドが含まれていることを前提としています。
リソースメソッドパラメーターへのフォームデータの挿入
import javax.ws.rs.FormParam; import javax.ws.rs.POST; ... @POST public boolean updatePost(@FormParam("title") String title, @FormParam("tags") String tags, @FormParam("body") String post) { ... }
47.2.5. 挿入するデフォルト値の指定
概要
より堅牢なサービス実装を提供するために、任意のパラメーターをデフォルト値に設定することができます。長い URI 文字列を入力するとエラーが発生しやすいため、これはクエリーパラメーターとマトリックスパラメーターから取得される値に特に役立ちます。また、要求側のシステムに適切な情報がないまま、すべての値を使用してクッキーを構築している可能性があるので、クッキーから抽出されたパラメーターにデフォルト値を設定すると良いでしょう。
javax.ws.rs.DefaultValue
アノテーションは、以下のインジェクションアノテーションと併用できます。
-
@PathParam
-
@QueryParam
-
@MatrixParam
-
@FormParam
-
@HeaderParam
-
@CookieParam
@DefaultValue
アノテーションは、インジェクションアノテーションに対応するデータがリクエストに存在しない場合に利用するデフォルト値を指定します。
構文
パラメーターのデフォルト値を設定するための構文に、@DefaultValue
アノテーションを使用するための構文を示します。
パラメーターのデフォルト値を設定するための構文
import javax.ws.rs.DefaultValue; ... void resourceMethod(@MatrixParam("matrix") @DefaultValue("value) int someValue, ... ) ...
このアノテーションは、パラメーター、Bean、フィールドの前に配置する必要があります。これは有効になります。付属のインジェクションアノテーションに対する @DefaultValue
アノテーションの位置は重要ではありません。
@DefaultValue
アノテーションは、単一のパラメーターを取ります。このパラメーターは、インジェクションアノテーションに基づいて適切なデータを抽出できない場合にフィールドに注入される値です。値は、任意の String
値にすることができます。この値は、関連付けられたフィールドのタイプと互換性がある必要があります。たとえば、関連付けられたフィールドが int
型である場合、blue
のデフォルト値では例外が発生します。
リストとセットの処理
アノテーション付きのパラメーター、Bean、またはフィールドのタイプが List、Set、または SortedSet の場合に、生成されるコレクションには指定されたデフォルト値から 1 つのエントリーがマッピングされます。
例
デフォルト値の設定 は、@DefaultValue
を使用して値が中ニュされるフィールドのデフォルト値を指定する 2 つの例を示しています。
デフォルト値の設定
import javax.ws.rs.DefaultValue; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/monster") public class MonsterService { @Get public Monster getMonster(@QueryParam("id") @DefaultValue("42") int id, @QueryParam("type") @DefaultValue("bogeyman") String type) { ... } ... }
デフォルト値の設定 の getMonster()
メソッドは、GET
リクエストが baseURI/monster に送信されると呼び出されます。メソッドでは、id
と type
の 2 つのクエリーパラメーターが URI に追加されることが想定されます。そのため、URI baseURI/monster?id=1&type=fomóiri を使用する GET
リクエストは 1 の ID で Fomóiri を返します。
@DefaultValue
アノテーションは両方のパラメーターに配置されるため、クエリーパラメーターが省略されると getMonster()
メソッドが機能できます。baseURI/monster に送信された GET
リクエストは、URI baseURI/monster?id=42&type=bogeyman を使用する GET
リクエストと同等です。
47.2.6. Java Bean へのパラメーターの挿入
概要
REST 経由で HTML フォームを投稿する場合は、サーバー側で一般的なパターンで Java Bean を作成して、フォームで受け取ったすべてのデータをカプセル化します (場合によっては他のパラメーターや HTML ヘッダーからでもデータもカプセル化します)。通常、この Java Bean の作成は 2 段階のプロセスになります。リソースメソッドはインジェクションによって (たとえば、@FormParam
メソッドパラメーターにアノテーションを追加することによって) フォームの値を受け取り、リソースメソッドは Bean のコンストラクタを呼び出し、フォームデータを渡します。
JAX-RS 2.0 @BeanParam
アノテーションを使用すると、このパターンを 1 段階で実装できます。フォームデータは bean クラスのフィールドに直接挿入でき、Bean 自体は JAX-RS ランタイムによって自動的に作成されます。これは、例を使用することで最も簡単に説明できます。
挿入ターゲット
@BeanParam
アノテーションは、リソースメソッドパラメーター、リソースフィールド、または Bean プロパティーに追加できます。ただし、パラメーターターゲットは、すべてのリソースクラスのライフサイクルで使用できる唯一の種類のターゲットです。他の種類のターゲットは、要求別のライフサイクルに制限されます。この状況は、表47.1「@BeanParam Injection Targets」 にまとめられています。
ターゲット | リソースクラスのライフサイクル |
---|---|
| すべて |
| per-request(デフォルト) |
| per-request(デフォルト) |
BeanParam アノテーションのない例
以下の例は、従来のアプローチ (@BeanParam
を使用しない) を使用して Java Bean でフォームデータを取得する方法を表しています。
// Java import javax.ws.rs.POST; import javax.ws.rs.FormParam; import javax.ws.rs.core.Response; ... @POST public Response orderTable(@FormParam("orderId") String orderId, @FormParam("color") String color, @FormParam("quantity") String quantity, @FormParam("price") String price) { ... TableOrder bean = new TableOrder(orderId, color, quantity, price); ... return Response.ok().build(); }
この例では、orderTable
メソッドは家具の Web サイトからある数量のテーブルを注文するために使用されるフォームを処理します。注文フォームが投稿されると、フォームの値は orderTable
メソッドのパラメーターに注入され、orderTable
メソッドは注入されたフォームデータを使用して TableOrder
クラスのインスタンスを明示的に作成します。
BeanParam アノテーションの使用例
上記の例は、@BeanParam
アノテーションを利用するためにリファクタリングできます。@BeanParam
のアプローチを使用する場合、フォームパラメーターは Bean クラスの TableOrder
フィールドに直接注入できます。実際、@PathParam
、@QueryParam
、@FormParam
、@MatrixParam
、@CookieParam
、および @HeaderParam
などの、Bean クラスの標準の JAX-RS パラメーターアノテーションを使用できます。フォームを処理するコードは、以下のようにリファクタリングできます。
// Java import javax.ws.rs.POST; import javax.ws.rs.FormParam; import javax.ws.rs.core.Response; ... public class TableOrder { @FormParam("orderId") private String orderId; @FormParam("color") private String color; @FormParam("quantity") private String quantity; @FormParam("price") private String price; // Define public getter/setter methods // (Not shown) ... } ... @POST public Response orderTable(@BeanParam TableOrder orderBean) { ... // Do whatever you like with the 'orderBean' bean ... return Response.ok().build(); }
これでフォームアノテーションが Bean クラス TableOrder に追加され、以下のようにリソースメソッドの署名にある @FormParam
アノテーションをすべて単一の @BeanParam
アノテーションで置き換えることができるようになりました。フォームが orderTable
リソースメソッドに投稿されると、JAX-RS ランタイムは TableOrder
インスタンス orderBean
を自動的に作成し、Bean クラスのパラメーターアノテーションが指定するすべてのデータを注入するようになりました。