17.1.1 ルートリソースクラス

ルートリソースクラスは,リソースメソッド,サブリソースメソッド,またはサブリソースロケータのどれかを一つ以上持ち,クラスレベルでPathアノテーションでアノテートされたJavaのpublicのクラスです。

リソースメソッドとサブリソースロケータを持つルートリソースクラスの例を次に示します。

package com.sample.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

//ルートリソースクラス
@Path("/root")
public class Resource2 {

 //コンテキストルート+ "/root/sub1"への要求に対応するサブリソースロケータ
 @Path("/sub1")
 public SubResource1 subResourceLocator1() {
   //処理するサブリソースクラスのインスタンスを戻す
   return new SubResource1();
 }

 //コンテキストルート+ "/root/sub2"への要求に対応するサブリソースロケータ
 @Path("/sub2")
 public SubResource2 subResourceLocator2() {
   //処理するサブリソースクラスのインスタンスを戻す
   return new SubResource2();
}
 //リソースメソッド
 @GET
 public String getValue() {
   String returnValue = "";
   //戻り値を構築する
   return returnValue;
 }

}

com.sample.resources.Resource2はルートリソースクラスです。クラスレベルでPathアノテーションでアノテートされていることに注意してください。このルートリソースクラスは,二つのサブリソースロケータsubResourceLocator1()とsubResourceLocator2()およびHTTP GETリクエストを処理するリソースメソッドgetValue()を持ちます。サブリソースロケータがPathアノテーションでアノテートされ,リソースメソッドが要求メソッド識別子でアノテートされていることに注意してください。二つのクラスSubResource1とSubResource2はサブリソースクラスです。詳細は,次の項目を参照してください。

サブリソースメソッドを持つルートリソースクラスの例を次に示します。

package com.sample.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

// ルートリソースクラス
@Path("/root")
public class Resource3 {

 // コンテキストルート+ "root/sub1"への要求に対応するサブリソースメソッド
 @Path("/sub1")
 @GET
 public String subResourceMethod1() {
   String value = "";
   // 処理を実行して,実行結果を返す
   return value;
 }

 // コンテキストルート+ "root/sub2"への要求に対応するサブリソースメソッド
 @Path("/sub2")
 @GET
 public String subResourceMethod2() {
   String value = "";
   // 処理を実行して,実行結果を返す
   return value;
 }
}

com.sample.resources.Resource3はルートリソースクラスです。このルートリソースクラスは,二つのサブリソースメソッドsubResourceMethod1()とsubResourceMethod2()を持ちます。サブリソースメソッドは,Pathアノテーションと要求メソッドの両方でアノテートされます。

PathアノテーションのURLにアスタリスク(*)を指定されている場合は,リソースメソッドだけを呼び出すことができます。サブリソースメソッド,およびサブリソースロケータを呼び出した場合は,例外マッピングプロバイダで処理できるjava.lang.StringIndexOutOfBoundsExceptionがスローされます。

<この項の構成>
(1) ライフサイクル
(2) コンストラクタ
(3) フィールドおよびbeanプロパティ
(4) リソースメソッド
(5) サブリソースメソッド
(6) サブリソースロケータ

(1) ライフサイクル

JAX-RSエンジンは,Webリソースに対する要求ごとにルートリソースクラスをインスタンス化します。ルートリソースクラスのライフサイクルは次のとおりです。

  1. コンストラクタが呼び出される
  2. 必要なインジェクションが行われる
  3. 適切なメソッドが呼び出される
  4. GC(ガーベージコレクション)の対象になる

(2) コンストラクタ

ルートリソースクラスは,publicデフォルトコンストラクタ(明示的に宣言されないコンストラクタ)も含めて,少なくとも一つ以上のpublicコンストラクタを持つ必要があります。

パラメタを持つpublicコンストラクタの例を次に示します。

package com.sample.resources;

import javax.ws.rs.DefaultValue;
import javax.ws.rs.Encoded;
import javax.ws.rs.QueryParam;
import javax.ws.rs.Path;
import javax.ws.rs.GET;

//ルートリソースクラス
@Path("/root")
public class Resource1 {
 private String query1;

 //パラメタを持つpublicコンストラクタ
 public Resource1(@Encoded @DefaultValue("abc") @QueryParam("query") String query){
   this.query1 = query;
 }

 //リソースメソッド
 @GET
 public String getValue() {
   return "Your requested query parameter ¥"query¥" is: " + this.query1;
 }
}

この例では,ルートリソースクラスcom.sample.resources.Resource1は,QueryParamアノテーションでアノテートされたパラメタqueryを持つpublicコンストラクタResource1()によってインスタンス化されます。

パラメタqueryを自動でURLデコードされるのを無効化するためにEncodedアノテーションが使用されています。また,クライアントから送信された要求にパラメタqueryにインジェクトする値がない場合のデフォルト値を指定するためにDefaultValueアノテーションが組み合わされて使用されています。

パラメタを持たないpublicコンストラクタの例を次に示します。

package com.sample.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

//ルートリソースクラス
@Path("/root")
public class Resource2 {
 //パラメタを持たないpublicコンストラクタ
 public Resource2() {
   // 処理を実行する
 }

//リソースメソッド
 @GET
 public String getValue(){
   return "Your request was accepted.";
 }
}

この例では,ルートリソースクラスcom.sample.resources.Resource2は,パラメタを持たないpublicコンストラクタResource2()によってインスタンス化されます。

パラメタを持つpublicコンストラクタが一つ以上宣言されている例を次に示します。

package com.sample.resources;

import javax.ws.rs.Encoded;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;

//ルートリソースクラス
@Path("/root/")
public class Resource3 {
 private String matrix1;
 private String query1;

 //パラメタを持たないpublicコンストラクタ
 public Resource3() {
   // 処理を実行する
 }

 //パラメタを持つpublicコンストラクタ(1番目)
 @Encoded
 public Resource3(@MatrixParam("matrix1") String matrix1) {
   this.matrix1 = matrix1;
 }

 //パラメタを持つpublicコンストラクタ(2番目)
 @Encoded
 public Resource3(@FormParam("form1") String form1,
     @QueryParam("query1") String query1) {
   this.form1 = form1;
   this.query1 = query1;
 }

 //リソースメソッド
 @GET
 public String getValue() {
   return "Your requested matrix parameter ¥"matrix1¥" is: " + this.matrix1 +  "¥n" +
     "Your requested query parameter ¥"query1¥" is: " + this.query1;
 }
}

この例では,ルートリソースクラスcom.sample.resources.Resource3は,それぞれMatrixParamアノテーションおよびQueryParamアノテーションでアノテートされたパラメタmatrix1およびパラメタquery1を持つ,2番目のpublicコンストラクタによってインスタンス化されます。

パラメタmatrix1とパラメタquery1を自動でURLデコードされるのを無効化するために,Encodedアノテーションがコンストラクタのレベルで使用されています。

デフォルトコンストラクタの例を次に示します。

package com.sample.resources;

import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;

//ルートリソースクラス
@Path("/root")
public class Resource4 {

 //リソースメソッド
 @POST
 public String getValue(@FormParam("form1") String form1) {
   return "Your requested form parameter ¥"form1¥" is: " + form1;
 }
}

この例では,ルートリソースクラスcom.sample.resources.Resource4は,暗黙的に宣言されているデフォルトコンストラクタResource4()によってインスタンス化されます。

デフォルトコンストラクタでjava.io.IOExceptionが発生した場合,エラーとなり(KDJJ10039-E),ルートリソースクラスはインスタンス化されません。HTTPステータスコードには500が返されます。

publicコンストラクタが一つも宣言されていない場合,エラーとなり(KDJJ10006-E),ルートリソースクラスはインスタンス化されません。HTTPステータスコードには500が返されます。

なお,次に示すコンストラクタはpublicコンストラクタではありません。

コンストラクタのパラメタで使用できるインジェクション用アノテーションと,オプションのアノテーションの組み合わせを次の表に示します。

表17-2 コンストラクタのパラメタで使用できるアノテーション

項番インジェクション用アノテーションオプションのアノテーション
EncodedDefaultValue
1MatrixParam
2QueryParam
3PathParam×
4CookieParam×
5HeaderParam×
6FormParam×
7Context××
(凡例)
○:インジェクション用アノテーションと組み合わせて使用できることを示します。
×:インジェクション用アノテーションが使用できないことを示します。

オプションのEncodedアノテーションを使用すると,インジェクション対象のコンストラクタのパラメタが自動でURLデコードされるのを無効化できます。

オプションのDefaultValueアノテーションを使用すると,インジェクション対象のコンストラクタのパラメタにインジェクトする値がない場合に仮定されるデフォルト値を指定できます。

ルートリソースクラスがパラメタを持つpublicコンストラクタを一つ以上持つ場合,JAX-RSエンジンは,最もパラメタ数が多いコンストラクタを使用してルートリソースクラスをインスタンス化します。最もパラメタ数が多いコンストラクタを二つ以上持つ場合,最初に定義されているコンストラクタを使用してルートリソースクラスをインスタンス化します。このとき,警告メッセージがログに出力されます(KDJJ20010-W)。

次のどちらかの場合,HTTPリクエストは処理されません。HTTPステータスコードには500が返されます。なお,ログを確認するときは,JAX-RS機能のログファイルではなくJ2EEサーバのログファイルを確認してください。

(3) フィールドおよびbeanプロパティ

ルートリソースクラスのフィールドおよびbeanプロパティで使用できるインジェクション用アノテーションと,オプションのアノテーションの組み合わせを次の表に示します。JAX-RSエンジンは,ルートリソースクラスをインスタンス化する際に,アノテーションに基づいてアノテートされたフィールドおよびbeanプロパティに値をインジェクトします。なお,Beanプロパティは,読み取り専用プロパティでなくても構いません。

表17-3 フィールドおよびbeanプロパティで使用できるアノテーション

項番インジェクション用アノテーションオプションのアノテーション
EncodedDefaultValue
1MatrixParam
2QueryParam
3PathParam×
4CookieParam×
5HeaderParam×
6FormParam×
7Context××
(凡例)
○:インジェクション用のアノテーションと組み合わせて使用できることを示します。
×:インジェクション用のアノテーションが使用できないことを示します。

オプションのEncodedアノテーションを使用すると,インジェクション対象のフィールドまたはbeanプロパティが自動でURLデコードされるのを無効化できます。

オプションのDefaultValueアノテーションを使用すると,インジェクション対象のフィールドまたはbeanプロパティにインジェクトする値がない場合に仮定されるデフォルト値を指定できます。

ルートリソースクラスのフィールドでDefaultValueアノテーションを使用する例を次に示します。

private @DefaultValue("value1") @QueryParam("id") String id;

この例では,クエリパラメタidがURLに指定されていない場合,フィールドidは"value1"になります。

ルートリソースクラスのbeanプロパティでDefaultValueアノテーションを使用する例を次に示します。

private String property1;
 
@DefaultValue("10") @QueryParam("prop1")
public void setProperty1(String property1) {
 this.property1 = property1;
}

この例では,クエリパラメタprop1がURIに指定されていない場合,beanプロパティproperty1の値は"10"になります。

ルートリソースクラスのフィールドでEncodedアノテーションを使用する例を次に示します。

private @Encoded @QueryParam("id") String id;

この例では,フィールドidの値は,自動でURLデコードされません。

ルートリソースクラスのbeanプロパティでEncodedアノテーションを使用する例を次に示します。

private String property1;
 
@Encoded @QueryParam("prop1")
public void setProperty1(String property1) {
 this.property1 = property1;
}

この例では,beanプロパティproperty1の値は,自動でURLデコードされません。

ルートリソースクラスのフィールド,またはbeanプロパティのうち,インジェクション用アノテーションとDefaultValueアノテーションが使用されているパラメタで,JAX-RSエンジンがインジェクトするときにランタイム例外が発生した場合,HTTPリクエストは処理されません。HTTPステータスコードには500が返されます。なお,ログを確認するときは,JAX-RS機能のログファイルではなくJ2EEサーバのログファイルを確認してください。

(4) リソースメソッド

リソースメソッドは,JAX-RS仕様で定義された要求メソッド識別子のどれかでアノテートされた,ルートリソースクラスのメソッドです。ルートリソースクラスは,一つ以上のリソースメソッドを持つことができます。

JAX-RS仕様で定義された要求メソッド識別子を次に示します。

一つのリソースメソッドに対し,二つ以上の要求メソッド識別子を使用している場合,エラーとなり(KDJJ10006-E),ルートリソースクラスはインスタンス化されません。HTTPステータスコードには500が返されます。

二つ以上のリソースメソッドに対し,同じ要求メソッド識別子を使用している場合,エラーとなり(KDJJ10006-E),ルートリソースクラスはインスタンス化されません。HTTPステータスコードには500が返されます。

HTTPリクエストに対し,ディスパッチするリソースメソッドが一つもない場合,HTTPステータスコードに405が設定された,例外マッピングプロバイダで処理できるjavax.ws.rs.WebApplicationExceptionがスローされます。

リソースメソッドで要求メソッド識別子を使用している例を次に示します。

@GET
@Encoded
@Produces("text/plain")
public String echo(@QueryParam("id") String id){
 return "ID is: " + id;
}

この例では,echo()メソッドがGET要求メソッド識別子でアノテートされています。また,echo()メソッドは,Content-Typeが"text/plain"であるHTTPレスポンスを返すために,"text/plain"を値に持つProducesアノテーションでアノテートされています。なお,パラメタidは,クエリパラメタidを受け取るQueryParamアノテーションでアノテートされ,さらにクエリパラメタが自動でURLデコードされるのを無効化するためにEncodedアノテーションでアノテートされています。

(a) 可視性

リソースメソッドは,要求メソッド識別子が適用されたpublicメソッドである必要があります。次に示すメソッドは,要求メソッド識別子でアノテートされていてもリソースメソッドではありません。

要求メソッド識別子を上記のメソッドのどれかに適用した場合,警告メッセージまたはエラーメッセージがログに出力されます(KDJJ20003-WまたはKDJJ10006-E)。KDJJ20003-WおよびKDJJ10006-Eについては,「13.7.1 Webリソース初期化時の構文チェック(KDJJ20003-WとKDJJ10006-E)」を参照してください。

(b) パラメタのアノテーション

リソースメソッドのパラメタで使用できるインジェクション用アノテーションと,オプションのアノテーションの組み合わせを次の表に示します。

表17-4 リソースメソッドのパラメタで使用できるアノテーション

項番インジェクション用アノテーションオプションのアノテーション
EncodedDefaultValue
1MatrixParam
2QueryParam
3PathParam×
4CookieParam×
5HeaderParam×
6FormParam×
7Context××
(凡例)
○:インジェクション用のアノテーションと組み合わせて使用できることを示します。
×:インジェクション用のアノテーションが使用できないことを示します。

オプションのEncodedアノテーションを使用すると,インジェクション対象のリソースメソッドのパラメタが自動でURLデコードされるのを無効化できます。

オプションのDefaultValueアノテーションを使用すると,インジェクション対象のリソースメソッドのパラメタにアノテートされるアノテーションのデフォルト値を指定できます。

リソースメソッドのパラメタでアノテーションを使用する例を次に示します。

@GET
@Produces("text/plain")
public String echo(@Encoded @DefaultValue("10") @QueryParam("id") String id, @Encoded @MatrixParam("matrix1") String matrix1){
 return "ID is: " + id + "¥nMatrix1 is: " + matrix1;
}

この例では,リソースメソッドecho()は,QueryParamアノテーションでアノテートされたパラメタidおよびMatrixParamアノテーションでアノテートされたパラメタmatrix1を含みます。パラメタidは,自動でURLデコードされるのを無効化し,デフォルト値を指定するために,さらにEncodedアノテーションおよびDefaultValueアノテーションでアノテートされています。matrixパラメタは,さらに自動でURLデコードされるのを無効化するためにEncodedアノテーションでアノテートされています。

ルートリソースクラスのリソースメソッド,またはサブリソースメソッドのパラメタのうち,インジェクション用アノテーションとDefaultValueアノテーションが使用されているパラメタで,JAX-RSエンジンがインジェクトするときにランタイム例外が発生した場合,エラーとなり(KDJJ10009-E,KDJJ10006-E),HTTPリクエストは処理されません。HTTPステータスコードには500が返されます。

(c) エンティティパラメタ

エンティティパラメタの説明については,「17.1.2 エンティティパラメタ」を参照してください。

(d) 戻り値

戻り値の説明については,「17.1.3 戻り値」を参照してください。

(5) サブリソースメソッド

Pathアノテーションでアノテートされたリソースメソッドを,特に,サブリソースメソッドと呼びます。サブリソースメソッドとリソースメソッドの違いは,Pathアノテーションを使用しているかどうかだけです。

サブリソースメソッドの例を次に示します。

package com.sample.resources;

import javax.ws.rs.POST;
import javax.ws.rs.Path;

//ルートリソースクラス
@Path("/root/")
public class Resource1 {

 //サブリソースメソッド
 @Path("sub1")
 @POST
 public String doSomething(String entityBody) {
   return "By Sub-Resource Method.";
 }

 //リソースメソッド
 @POST
 public String doOthers(String entityBody){
   return "By Resource Method.";
 }
}

この例では,doSomething()メソッドがサブリソースメソッドです。ルートリソースクラスcom.sample.resources.Resource1を含むWebアプリケーション(WARファイル)のコンテキストルートが,"example"で,Webアプリケーションが"sample.com"というホストで公開されているとします。その場合,URL"http://sample.com/example/root/sub1"に対するHTTP POST要求は,サブリソースメソッドdoSomething()にディスパッチされます。

一方,URL"http://sample.com/example/root"に対するHTTP POST要求は,リソースメソッドdoOthers()にディスパッチされます。

(6) サブリソースロケータ

要求メソッド識別子が適用されていない,Pathアノテーションだけでアノテートされたルートリソースクラスのメソッドをサブリソースロケータと呼びます。

サブリソースロケータは,HTTPリクエストに対する残りの処理を行うサブリソースクラスを返します。サブリソースクラスについては,「17.1.7 サブリソースクラス」を参照してください。

ルートリソースクラスのサブリソースロケータの例を次に示します。

package com.sample.resources;

import javax.ws.rs.Encoded;
import javax.ws.rs.QueryParam;
import javax.ws.rs.PathParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

//ルートリソースクラス
@Path("/root/")
public class Resource {

 //コンテキストルート+ "/root/sub1"への要求に対応するサブリソースロケータ
 @Path("sub1")
 public SubResource getRequestHandler(@PathParam("id") String id,
     @Encoded @QueryParam("query1") String query1) {
   return new SubResource(id, query1);
 }
}

対応するサブリソースクラスの例を次に示します。

//サブリソースクラス
public class SubResource {
 private String id;
 private String query;

 public SubResource(String id, String query){
   this.id = id;
   this.query = query;
 }
 @GET
 public String getRequestParameter(){
   return "ID is: " + this.id + "¥nQuery is: " + this.query;
 }
}

この例では,ルートリソースクラスcom.sample.resources.Resourceは,HTTPリクエストを直接処理しません。サブリソースロケータgetRequestHandlerが返すサブリソースクラスは,com.sample.resources.SubResourceが処理します。

リソースクラスcom.sample.resources.Resourceを含むWebアプリケーション(WARファイル)のコンテキストルートが"example"で,Webアプリケーションが"sample.com"というホストで公開されているとします。その場合,URL"http://sample.com/example/root/sub1?query1=10"に対するHTTP GETリクエストは,ルートリソースクラスcom.sample.resources.ResourceのメソッドgetRequestHandler()にディスパッチされます。

HTTP GETリクエストに対する残りの処理は,サブリソースクラスcom.sample.resources.SubResourceのリソースメソッドgetRequestParameter()によって処理されます。

サブリソースロケータのパラメタとしてエンティティパラメタを使用した場合,エラーとなり(KDJJ10006-E),クライアントからのHTTPリクエストは処理されません。HTTPステータスコードには500が返されます。

サブリソースロケータがpublicでない場合の動作は,リソースメソッドと同じです。

サブリソースロケータの戻り値の型がvoidの場合,エラーとなり(KDJJ10006-E),クライアントからのHTTPリクエストは処理されません。HTTPステータスコードには500が返されます。

サブリソースロケータのパラメタのうち,インジェクション用アノテーションとDefaultValueアノテーションが使用されているパラメタで,JAX-RSエンジンがインジェクトするときにランタイム例外が発生した場合,HTTPリクエストは処理されません。HTTPステータスコードには500が返されます。なお,ログを確認するときは,JAX-RS機能のログファイルではなくJ2EEサーバのログファイルを確認してください。