49.4. 要求と応答の解析

概要

HTTP 呼び出しを行う際の重要な側面は、クライアントが送信要求メッセージと受信応答を解析できる必要があることです。JAX-RS 2.0 では、主要な概念は、メディアタイプでタグ付けされた raw メッセージを表す Entity クラスです。未加工メッセージを解析するために、メディアタイプと特定の Java タイプとの間で変換できる複数の エンティティープロバイダー を登録できます。

つまり、JAX-RS 2.0 のコンテキストでは、Entity は raw メッセージの表現で、エンティティープロバイダーは (メディア型に基づく) raw メッセージを解析する機能を提供するプラグインです。

Entities

Entity は、メタデータ (メディア型、言語、およびエンコーディング) によって拡張されたメッセージボディーです。Entity インスタンスはメッセージを raw 形式で保持し、特定のメディア型に関連付けられます。Entity オブジェクトのコンテンツを、 Java オブジェクトに変換するには、指定のメディア型を必要な Java 型にマッピングできる エンティティープロバイダー が必要です。

バリアント

javax.ws.rs.core.Variant オブジェクトは、以下のように Entity に関連付けられたメタデータをカプセル化します。

  • メディアタイプ
  • 言語
  • エンコーディング

実質的に、Entity は HTTP メッセージの内容で設定され、Variant メタデータによって拡張されると考えることができます。

エンティティープロバイダー

エンティティープロバイダーは、メディアタイプと Java 型間のマッピング機能を提供するクラスです。実際には、エンティティープロバイダーは、特定のメディアタイプ (または複数のメディアタイプ) のメッセージを解析できるクラスと考えることができます。エンティティープロバイダーには、以下の 2 つの異なるバリアントがあります。

MessageBodyReader
メディアタイプから Java 型へのマッピング機能を提供します。
MessageBodyWriter
Java 型からメディアタイプへのマッピング機能を提供します。

標準のエンティティープロバイダー

次の Java とメディアタイプの組み合わせのエンティティープロバイダーが標準として提供されています。

byte[]
すべてのメディア型 (*/*)
java.lang.String
すべてのメディア型 (*/*)
java.io.InputStream
すべてのメディア型 (*/*)
java.io.Reader
すべてのメディア型 (*/*)
java.io.File
すべてのメディア型 (*/*)
javax.activation.DataSource
すべてのメディア型 (*/*)
javax.xml.transform.Source
XML 型 (text/xmlapplication/xml、および application/*+xml フォームのメディア型)。
javax.xml.bind.JAXBElement およびアプリケーションが提供する JAXB クラス
XML 型 (text/xmlapplication/xml、および application/*+xml フォームのメディア型)。
MultivaluedMap<String,String>
フォームコンテンツ (application/x-www-form-urlencoded)。
StreamingOutput
すべてのメディア型 (*/*)、MessageBodyWriter のみ。
java.lang.Booleanjava.lang.Characterjava.lang.Number
text/plain のみ対象。ボックス/アンボックス変換でサポートされるプリミティブタイプ。

Response オブジェクト

デフォルトの戻り値型は javax.ws.rs.core.Response 型で、型付けされていない応答を表します。Response オブジェクトは、メッセージボディー、HTTP ステータス、HTTP ヘッダー、メディア型など、完全な HTTP 応答へのアクセスを提供します。

応答ステータスへのアクセス

応答の状態には、getStatus メソッド (HTTP ステータスコードを返す) からアクセスできます。

int status = resp.getStatus();

または、説明文字列も提供する getStatusInfo メソッドでアクセスすることもできます。

String statusReason = resp.getStatusInfo().getReasonPhrase();

返されるヘッダーへのアクセス

以下の方法のいずれかを使用して HTTP ヘッダーにアクセスできます。

MultivaluedMap<String,Object>
getHeaders()

MultivaluedMap<String,String>
getStringHeaders()

String
getHeaderString(String name)

たとえば、ResponseDate ヘッダーがあることが分かっている場合は、以下のようにアクセスできます。

String dateAsString = resp.getHeaderString("Date");

返されるクッキーへのアクセス

以下のように、getCookies メソッドを使用して、Response で設定された新しいクッキーにアクセスできます。

import javax.ws.rs.core.NewCookie;
...
java.util.Map<String,NewCookie> cookieMap = resp.getCookies();
java.util.Collection<NewCookie> cookieCollection = cookieMap.values();

返されるメッセージコンテンツへのアクセス

Response オブジェクトの readEntity メソッドのいずれかを呼び出すと、返されるメッセージコンテンツにアクセスできます。readEntity メソッドは利用可能なエンティティープロバイダーを自動的に呼び出し、メッセージを要求された型 (readEntity の最初の引数として指定) に変換します。たとえば、メッセージコンテンツに String 型としてアクセスするには、次のように指定します。

String messageBody = resp.readEntity(String.class);

コレクションの戻り値

返されたメッセージを Java 汎用型 (例: List または Collection 型) としてアクセスする必要がある場合、javax.ws.rs.core.GenericType<T> コンストラクションを使用してリクエストメッセージ型を指定できます。以下に例を示します。

import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Client;
import javax.ws.rs.core.GenericType;
import java.util.List;
...
GenericType<List<String>> stringListType = new GenericType<List<String>>() {};

Client client = ClientBuilder.newClient();
List<String> bookNames = client.target("http://example.org/bookstore/booknames")
                     .request("text/plain")
                     .get(stringListType);