46.5. サブリソースの操作

概要

サービスは複数のリソースで処理する必要がある場合が多いです。たとえば、注文処理サービスのベストプラクティスでは、各顧客を一意のリソースとして処理することを提案しています。各注文は、一意のリソースとしても処理されます。

JAX-RS API を使用して、顧客リソースと注文リソースを サブ リソースとして実装します。サブリソースは、ルートリソースクラスを介してアクセスされるリソースです。これらは、@Path アノテーションをリソースクラスのメソッドに追加して定義されます。サブリソースは、次の 2 つの方法のいずれかで実装できます。

サブリソースの指定

サブリソースを指定するには、@Path アノテーションをメソッドに付けます。サブリソースの URI は次のように設定されます。

  1. サブリソースの @Path アノテーションの値を、サブリソースの親リソースの @Path アノテーションの値に追加します。

    親リソースの @Path アノテーションは、サブリソースを含むクラスのオブジェクトを返すリソースクラスのメソッドにある場合があります。

  2. ルートリソースに到達するまで、前の手順を繰り返します。
  3. 組み立てられ URI は、サービスがデプロイされるベース URI に追加されます。

たとえば、例46.6「サブリソースの注文」 に示されているサブリソースの URI は、baseURI/customerservice/order/12 である可能性があります。

例46.6 サブリソースの注文

...
@Path("/customerservice/")
public class CustomerService
{
  ...
  @Path("/orders/{orderId}/")
  @GET
  public Order getOrder(@PathParam("orderId") String orderId)
  {
    ...
  }
}

サブリソースメソッド

サブリソースメソッドには、@Path アノテーションと HTTP 動詞アノテーションのいずれが付けられます。れます。サブリソースメソッドは、指定された HTTP 動詞を使用してリソースに対して行われた要求の処理を直接担当します。

例46.7「サブリソースメソッド」 は、3 つのサブリソースメソッドを持つリソースクラスを示しています。

  • getOrder() は、URI が /customerservice/orders/{orderId}/ に一致するリソースの HTTP GET リクエストを処理します。
  • updateOrder() は、URI が /customerservice/orders/{orderId}/ に一致するリソースの HTTP PUT リクエストを処理します。
  • newOrder() は、/customerservice/orders/ でリソースの HTTP POST 要求を処理します。

例46.7 サブリソースメソッド

...
@Path("/customerservice/")
public class CustomerService
{
  ...
  @Path("/orders/{orderId}/")
  @GET
  public Order getOrder(@PathParam("orderId") String orderId)
  {
    ...
  }

  @Path("/orders/{orderId}/")
  @PUT
  public Order updateOrder(@PathParam("orderId") String orderId,
                           Order order)
  {
    ...
  }

  @Path("/orders/")
  @POST
  public Order newOrder(Order order)
  {
    ...
  }
}
注記

URI テンプレートが同じサブリソースメソッドは、サブリソースロケーターによって返されるリソースクラスと同じです。

sub-resource ロケーター

サブリソースロケーターは、HTTP 動詞アノテーションの 1 つが追加されておらず、サブリソースでの要求は直接処理されません。代わりに、サブリソースロケーターは、要求を処理できるリソースクラスのインスタンスを返します。

HTTP 動詞アノテーションがないことに加えて、サブリソースロケーターはエンティティーパラメーター指定できません。サブリソースロケーターメソッドで使用されるすべてのパラメーターは、47章リソースクラスとメソッドへの情報の受け渡し で説明されているアノテーションの 1 つを使用する必要があります。

例46.8「特定のクラスを返すサブリソースロケーター」 に示すように、サブリソースロケーターを使用すると、すべてのメソッドを 1 つのスーパークラスに配置する代わりに、リソースを再利用可能なクラスとしてカプセル化できます。processOrder() メソッドはサブリソースロケーターです。URI テンプレート /orders/{orderId}/ に一致する URI でリクエストが実行されると、Order クラスのインスタンスが返されます。Order クラスには、HTTP 動詞アノテーションが付いたメソッドがあります。PUT リクエストは updateOrder() メソッドによって処理されます。

例46.8 特定のクラスを返すサブリソースロケーター

...
@Path("/customerservice/")
public class CustomerService
{
  ...
  @Path("/orders/{orderId}/")
  public Order processOrder(@PathParam("orderId") String orderId)
  {
    ...
  }

  ...
}

public class Order
{
  ...
  @GET
  public Order getOrder(@PathParam("orderId") String orderId)
  {
    ...
  }

  @PUT
  public Order updateOrder(@PathParam("orderId") String orderId,
                           Order order)
  {
    ...
  }

}

ポリモーフィズムをサポートできるように、サブリソースロケーターは実行時に処理されます。サブリソースロケーターの戻り値は、汎用 Object、抽象クラス、またはクラス階層の最上位になります。たとえば、サービスで PayPal の注文とクレジットカードの注文の両方を処理する必要がある場合、例46.8「特定のクラスを返すサブリソースロケーター」からの processOrder() メソッドの署名は変更されません。Order クラスを拡張した ppOrderccOder の 2 つのクラスを実装することのみが必要になります。processOrder() の実装は、必要なロジックを基づいて、サブリソースの必要な実装をインスタンス化します。