1前書き
/resteasy-tutorial[前の記事]のリンクでは、 JAX-RS 2.0 の RESTEasy サーバー側の実装に焦点を当てました。
-
JAX-RS 2.0 ** では、リモートのRESTful WebサービスにHTTPリクエストを送信できるように、新しいクライアントAPIが導入されています。 Jersey、Apache CXF、Restlet、RESTEasyは、最も普及している実装の一部に過ぎません。
この記事では、 RESTEasy API を使用してリクエストを送信することによって REST API を消費する方法を探ります。
2プロジェクト設定
-
pom.xml ** に次の依存関係を追加します。
<properties>
<resteasy.version>3.0.14.Final</resteasy.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>${resteasy.version}</version>
</dependency>
...
</dependencies>
3クライアントサイドコード
クライアントの実装は、3つの主要クラスで構成されています。
-
クライアント
-
WebTarget
-
レスポンス
Client インターフェースは WebTarget インスタンスのビルダーです。
WebTarget は、より多くのサブリソースWebTargetsを作成したり、要求を呼び出したりできる、固有のURLまたはURLテンプレートを表します。
クライアントを作成する方法は2つあります。
-
標準的な方法では、
org.jboss.resteasy.client.ClientRequest RESTeasy Proxy Framework ** : ResteasyClientBuilder クラスを使用する
ここではRESTEasy Proxy Frameworkに焦点を当てます。
JAX-RSアノテーションを使用して着信要求をRESTFul Webサービスメソッドにマッピングする代わりに、クライアントフレームワークはリモートRESTful Webサービスで呼び出すために使用するHTTP要求を構築します。
それでは、Javaインターフェースを書き、メソッドとインターフェースにJAX-RSアノテーションを使ってみましょう。
3.1. ServicesClient インターフェース
@Path("/movies")
public interface ServicesInterface {
@GET
@Path("/getinfo")
@Produces({ MediaType.APPLICATION__JSON, MediaType.APPLICATION__XML })
Movie movieByImdbId(@QueryParam("imdbId") String imdbId);
@POST
@Path("/addmovie")
@Consumes({ MediaType.APPLICATION__JSON, MediaType.APPLICATION__XML })
Response addMovie(Movie movie);
@PUT
@Path("/updatemovie")
@Consumes({ MediaType.APPLICATION__JSON, MediaType.APPLICATION__XML })
Response updateMovie(Movie movie);
@DELETE
@Path("/deletemovie")
Response deleteMovie(@QueryParam("imdbId") String imdbId);
}
3.2. 映画クラス
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "movie", propOrder = { "imdbId", "title" })
public class Movie {
protected String imdbId;
protected String title;
//getters and setters
}
3.3. リクエスト作成
APIを利用するために使用できるプロキシクライアントを生成します。
String transformerImdbId = "tt0418279";
Movie transformerMovie = new Movie("tt0418279", "Transformer 2");
final String path = "http://127.0.0.1:8080/RestEasyTutorial/rest";
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target(UriBuilder.fromPath(path));
ServicesInterface proxy = target.proxy(ServicesInterface.class);
//POST
Response moviesResponse = proxy.addMovie(transformerMovie);
System.out.println("HTTP code: " + moviesResponse.getStatus());
moviesResponse.close();
//GET
Movie movies = proxy.movieByImdbId(transformerImdbId);
//PUT
transformerMovie.setTitle("Transformer 4");
moviesResponse = proxy.updateMovie(transformerMovie);
moviesResponse.close();
//DELETE
moviesResponse = proxy.deleteMovie(batmanMovie.getImdbId());
moviesResponse.close();
RESTEasyクライアントAPIはApache HttpClient に基づいています。
また、各操作の後、新しい操作を実行する前に応答を閉じる必要があります。デフォルトでは、クライアントが使用できるHTTP接続は1つだけなので、これは必要です。
最後に、DTOと直接連携していることに注意してください。 JSON や XML との間のマーシャル/アンマーシャルロジックは扱っていません。 Movie クラスは正しく __. とアノテートされているので、これは JAXB または Jackson__を使用した裏で起こります。
3.4. 接続プールを使用したリクエストの作成
前の例からの1つの注意点は、利用可能な接続が1つだけであることです。もしそうなら - 例えば、私たちはやろうとする:
Response batmanResponse = proxy.addMovie(batmanMovie);
Response transformerResponse = proxy.addMovie(transformerMovie);
batmanResponse で close() を呼び出さないで - 2行目が実行されると例外がスローされます。
java.lang.IllegalStateException:
Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
繰り返しますが、これは単にRESTEasyによって使用されるデフォルトの HttpClient が org.apache.http.impl.conn.SingleClientConnManager であるために起こります。
今度は - その制限を回避するために、 RestEasyClient インスタンスを(接続プールを使用して)別々に作成する必要があります。
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
cm.setMaxTotal(200);//Increase max total connection to 200
cm.setDefaultMaxPerRoute(20);//Increase default max connection per route to 20
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
ResteasyWebTarget target = client.target(UriBuilder.fromPath(path));
ServicesInterface proxy = target.proxy(ServicesInterface.class);
これで、適切な接続プールから** 利益を得ることができ、毎回接続を解放する必要なく、クライアントを介して複数の要求を実行することができます。
4結論
このクイックチュートリアルでは、 RESTEasy Proxy Framework を紹介し、それを使って超シンプルなクライアントAPIを構築しました。
このフレームワークは、クライアントを設定するためのヘルパーメソッドをいくつか提供します。これは、JAX-RSサーバーサイドの仕様とは反対のミラーとして定義できます。
この記事で使用した例はhttps://github.com/eugenp/tutorials/tree/master/resteasy[GitHubのサンプルプロジェクト]として入手できます。