2.2. JAX-RS Client
2.2.1. JAX-RS Client API
JAX-RS 2.0 では、HTTP リクエストをリモート RESTful Web サービスに送信する新しいクライアント API が導入されました。3 つの主要クラスを持つ fluent request-building API です。
-
Client
-
WebTarget
-
Response
Client
インターフェイスは WebTarget インスタンスのビルダーです。WebTarget
は、サブリソース WebTargets をビルドしたり、リクエストを呼び出すための固有の URL または URL テンプレートを表します。
クライアントを作成する方法は、標準の方法か、ResteasyClientBuilder
クラスを使用する方法です。ResteasyClientBuilder
クラスを使用する利点は、クライアントを設定するヘルパーメソッドが他にもいくつか提供されることです。
ResteasyClientBuilder
クラス はこれらのヘルパーメソッドを提供しますが、クラスは JBoss EAP API に固有のものです。アプリケーションを新しいサーバーに移行する場合は、アプリケーションを再構築する必要があります。ResteasyClientBuilder
クラスは RESTEasy に依存し、クラスは移植できません。
JAX-RS および Java EE API 仕様の両方に準拠するクライアントを作成する標準的な方法は、JAX-RS 実装間で移植可能です。
JAX-RS アプリケーションが移植可能な状態に保つには、Java EE API 仕様に従い、可能な場合は Java EE API アプリケーションを使用します。ユースケースが Java EE API の使用をサポートしない場合は、JBoss に固有の API のみを使用してください。
これらのガイドラインに従うと、アプリケーションを別のサーバーに移行する場合や、新しい Java EE と互換性のある JBoss 実装に移行する際に発生する可能性のある問題の数を減らすことができます。
標準の方法を使用したクライアントの作成
以下の例は、クライアントを作成するための標準的な方法のいずれかを示しています。
Client client = ClientBuilder.newClient();
また、別の標準的な方法を使用して、以下の例のようにクライアントを作成することもできます。
Client client = ClientBuilder.newBuilder().build(); WebTarget target = client.target("http://foo.com/resource"); Response response = target.request().get(); String value = response.readEntity(String.class); response.close(); // You should close connections!
ResteasyClientBuilder クラスを使用したクライアントの作成
以下の例は、ResteasyClientBuilder
クラスを使用してクライアントを作成します。
ResteasyClient client = new ResteasyClientBuilder().build(); ResteasyWebTarget target = client.target("http://foo.com/resource");
JAX-RS 2.1 では、2 つのタイムアウトメソッドを ClientBuilder
クラスに追加できます。タイムアウトメソッドは仕様に準拠したメソッドであり、RESTEasy メソッドを使用する代わりに使用することができます。
以下の ClientBuilder
仕様に準拠したメソッドは、非推奨となった RESTEasy メソッドを置き換えます。
connectTimeout
メソッドはestablishConnectionTimeout
メソッドに置き換わります。connectTimeout
メソッドは、新しいサーバー接続を行うときにクライアントが待機する時間を決定します。readTimeout
メソッドはsocketTimeout
メソッドに置き換わります。readTimeout
メソッドは、クライアントがサーバーからの応答を待つ時間を決定します。
以下の例は、connectTimeout
メソッドおよび readTimeout
メソッドの指定された値を示しています。
import javx.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Client; Client client = ClientBuilder.newBuilder() .connectTimeout(100, TimeUnit.SECONDS) .readTimeout(2, TimeUnit.SECONDS) .build();
readTimeout
は、既存の接続で実行されたリクエストに適用されることに注意してください。
timeout パラメーターの値をゼロに設定すると、サーバーは永久に待機します。
RESTEasy は、META-INF/services/javax.ws.rs.ext.Providers
ファイルにリストされているすべてのクラスを含むデフォルトのプロバイダーのセットを自動的に読み込みます。また、Client.configuration()
メソッド呼び出しによって提供される設定オブジェクトを使用して、他のプロバイダー、フィルター、インターセプターを手動で登録できます。設定では、必要になる可能性のある設定プロパティーを設定することもできます。
各 WebTarget
には、親インスタンスに登録されているコンポーネントおよびプロパティーを継承する設定インスタンスがあります。これにより、ユーザー名やパスワードなど、各ターゲットリソースに特定の設定オプションを設定できます。
その他のリソース
-
ResteasyClientBuilder
クラスおよびそのメソッドの詳細 は、Class ResteasyClientBuilder を参照してください。
RESTEasy クライアントクラスの使用
RESTEasy クライアントの以下の依存関係を Maven pom.xml
ファイルに追加する必要があります。
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>VERSION_IN_EAP</version>
</dependency>
RESTEasy クライアントクラスを使用する作業例は、JBoss EAP に同梱される jaxrs-client
および resteasy-jaxrs-client
クイックスタートを参照してください。
クライアント側のフィルター
クライアント側のフィルターには、以下のタイプがあります。
ClientRequestFilter
-
ClientRequestFilter
は、HTTP リクエストがサーバーへネットワーク経由で送信される前に実行されます。ClientRequestFilter
は、要求の実行を中止し、サーバーへの接続を行わずに、実行可能な応答を提供することもできます。 ClientResponseFilter
-
ClientResponseFilter
は、サーバーから応答を受信した後、応答本体がマーシャリング解除される前に実行されます。ClientResponseFilter
は、応答オブジェクトをアプリケーションコードに移動する前に変更できます。以下の例は、これらの概念を示しています。
// execute request filters for (ClientRequestFilter filter : requestFilters) { filter.filter(requestContext); if (isAborted(requestContext)) { return requestContext.getAbortedResponseObject(); } } // send request over the wire response = sendRequest(request); // execute response filters for (ClientResponseFilter filter : responseFilters) { filter.filter(requestContext, responseContext); }
クライアントリクエストへのクライアント側のフィルターの登録
以下の例は、クライアント側のフィルターをクライアント要求に登録する方法を表しています。
client = ClientBuilder.newClient(); WebTarget base = client.target(generateURL("/") + "get"); base.register(ClientExceptionsCustomClientResponseFilter.class).request("text/plain").get();
クライアント側のキャッシュ
RESTEasy には、クライアント側のキャッシュを設定する機能があります。このキャッシュは、サーバーの応答と共に送信されるキャッシュ制御ヘッダーを検索します。cache-control ヘッダーがクライアントが応答のキャッシュを許可するように指定すると、RESTEasy はローカルメモリー内にこれをキャッシュします。
ResteasyWebTarget target = client.target(generateBaseUrl()); target.register(BrowserCacheFeature.class);
チャンク化されたエンコーディングサポート
RESTEasy は、リクエストを チャンク 転送モードで送信するよう指定する機能をクライアント API に提供します。以下のように、チャンク された転送モードを指定する方法を使用できます。
org.jboss.resteasy.client.jaxrs.ResteasyWebTarget
を設定して、すべてのリクエストをチャンクモードで送信することができます。ResteasyClient client = new ResteasyClientBuilder().build(); ResteasyWebTarget target = client.target("http://localhost:8081/test"); target.setChunked(b.booleanValue()); Invocation.Builder request = target.request();
または、特定のリクエストをチャンクモードで送信するように設定することもできます。
ResteasyClient client = new ResteasyClientBuilder().build(); ResteasyWebTarget target = client.target("http://localhost:8081/test"); ClientInvocationBuilder request = (ClientInvocationBuilder) target.request(); request.setChunked(b);
javax.ws.rs.client.Invocation.Builder
クラスとは異なりorg.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder
は RESTEasy クラスです。
チャンクモードでリクエストを送信する機能は、基盤のトランスポート層によって異なります。特に、使用されている org.jboss.resteasy.client.jaxrs.ClientHttpEngine
クラスの実装によって異なります。現時点では、デフォルトの実装 ApacheHttpClient43Engine
と以前の実装の ApacheHttpClient4Engine
のみが、チャンクモードをサポートします。これらはいずれも org.jboss.resteasy.client.jaxrs.engines
パッケージで利用できます。詳細は、Implementing RESTEasy with HTTP Client を参照してください。
2.2.2. HTTP クライアントによる RESTEasy の実装
クライアントとサーバー間のネットワーク通信は、RESTEasy でデフォルトで処理されます。Apache HttpComponents
プロジェクトの HttpClient HttpClient
を使用します。RESTEasy クライアントフレームワークとネットワークの間のインターフェイスは、ClientHttpEngine
インターフェイスによって定義されます。
RESTEasy には、このインターフェイスの 4 つの実装が同梱されています。デフォルトの実装は ApacheHttpClient43Engine
です。この実装は Apache 4.3 を使用します。
ApacheHttpClient4Engine
は、Apache 4.3 よりも前のバージョンを使用する実装です。このクラスは後方互換性を提供します。RESTEasy は、Apache バージョンの検出に基づいて、これらの 2 つの ClientHttpEngine
実装のいずれかを自動的に選択します。InMemoryClientEngine
は、同じ JVM のサーバーにリクエストをディスパッチする実装で、URLConnectionEngine
は java.net.HttpURLConnection
を使用する実装です。
クライアントエグゼキューターは、特定の ClientRequest
に渡すことができます。
ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
RESTEasy および HttpClient
は、HttpClient
を参照せずに、デフォルトのクライアントフレームワークを使用するように決定します。ただし、一部のアプリケーションでは、HttpClient
の詳細を閲覧する必要がある場合があります。ApacheHttpClient43Engine
および ApacheHttpClient4Engine
は、org.apache.http.client.HttpClient
と org.apache.http.protocol.HttpContext
のインスタンスで提供できます。これは、HttpClient
レイヤーに追加の設定詳細を実行できます。たとえば、認証は以下のように設定できます。
// Configure HttpClient to authenticate preemptively // by prepopulating the authentication data cache. // 1. Create AuthCache instance AuthCache authCache = new BasicAuthCache(); // 2. Generate BASIC scheme object and add it to the local auth cache AuthScheme basicAuth = new BasicScheme(); authCache.put(new HttpHost("sippycups.bluemonkeydiamond.com"), basicAuth); // 3. Add AuthCache to the execution context BasicHttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.AUTH_CACHE, authCache); // 4. Create client executor and proxy HttpClient httpClient = HttpClientBuilder.create().build(); ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient, localContext); ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
HttpContextProvider
は RESTEasy が提供するインターフェイスで、これを使用してカスタム HttpContext
を ApacheHttpClient43Engine
および ApacheHttpClient4Engine
実装に提供できます。
コネクションの解放とコネクションのクローズの違いを理解しておくことが重要となります。接続を解放すると、接続が再利用できるようになります。接続を閉じると、そのリソースが解放され、使用できなくなります。
RESTEasy は通知なしで接続をリリースします。唯一のカウンター例は、応答が InputStream
のインスタンスであるケースです。これは明示的に閉じる必要があります。
一方、呼び出しの結果が Response
のインスタンスである場合は、Response.close()
メソッドを使用して接続を解放する必要があります。
WebTarget target = client.target("http://localhost:8081/customer/123"); Response response = target.request().get(); System.out.println(response.getStatus()); response.close();
これは try-finally
ブロックで実行できます。接続を解放すると、接続を別のことに利用できるようになります。通常、ソケットを閉じることはありません。
ApacheHttpClient4Engine.finalize()
は、使用中の HttpClient
を作成した場合に、開いているソケットを閉じます。finalize()
を呼び出すために JDK を使用するのは安全ではありません。HttpClient
が ApacheHttpClient4Executor
に渡される場合、ユーザーは以下のように接続を閉じる必要があります。
HttpClient httpClient = new HttpClientBuilder.create().build(); ApacheHttpClient4Engine executor = new ApacheHttpClient4Engine(httpClient); ... httpClient.getConnectionManager().shutdown();
ApacheHttpClient4Engine
が HttpClient
の独自のインスタンスを作成した場合は finalize()
がオープンソケットを閉じるのを待つ必要はありません。ClientHttpEngine
インターフェイスには、この目的のために close()
メソッドがあります。
最後に、javax.ws.rs.client.Client
クラスがエンジンを自動的に作成している場合は、Client.close()
を呼び出します。この呼び出しにより、ソケット接続がクリーンアップされます。
2.2.2.1. HTTP リダイレクト
Apache HttpClient をベースとする ClientHttpEngine
実装 は HTTP リダイレクトをサポートします。この機能はデフォルトで無効になっています。これを有効にするには、以下のように setFollowRedirects
メソッドを true
に設定します。
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine(); engine.setFollowRedirects(true); Client client = new ResteasyClientBuilder().httpEngine(engine).build();