RESTEasyクライアントAPI

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のサンプルプロジェクト]として入手できます。