日々常々

ふつうのプログラマがあたりまえにしたいこと。

JAX-RSのClientAPIを眺めてみて

導入

もう随分前の話になるのだけれど、JAX-RS2.0にはClient APIが仕様に入っております。

それはそれとして、各実装は個別にClient APIを提供したりしておました。 個別に実装していたClientAPIには当然違いがあるわけです。で、どんな差があるんだろーと見てみることにした。

JSRさん

斜め読みすると「Clientを取得してWebTargetを生成し、WebTargetからrequestを作って送信する。」ものらしい。なるほど。 あとはWebTarget使ったらいろんなアドレスへアクセスできるよーとか、レスポンスはResponseだけじゃなくいろんなタイプが使えるよ!とか、buildGetbuildPostInvocationを使ったら非同期的なことできんじゃね?とか、Configurableインタフェース使って設定できるよーとか、インターセプター使えるよーとか、そんな感じ。

印象として、WebTargetを使用したURIの指定方法がいろいろ用意されているのはREST APIゆえなのかなと思う一方で、FluentインタフェースだけだとJAX-RSとして入っている理由はあんまりなく、他に絡むのはProviderFilterくらいなように見えます。クライアントとしては十分なのかもだけど。

各実装

目に付いた実装のドキュメントを読んだり試してみたりしつつ。

Jerseyさん

参照実装であるJerseyさん。これを元に仕様化したということで、特にいびつさはないです。表面に出てくるのはJAX-RSのインタフェースだけなので、この書き方は全てのJAX-RS2.0実装で使えます。

Station station = ClientBuilder.newClient()
    .target(BASE_URL)
    .queryParam("number", number)
    .request()
    .get(Station.class);

他には、rx(Reactive Extension)の実装があります。

詳しくは @backpaper0 さんちに書いて……

Jersey ClientのRxサポートを軽〜く試す — 裏紙

……詳しくなかったわ。

RESTEasyさん

RESTEasyさんは元々ProxyFrameworkと言う別のクライアント実装を提供していた。それと仕様化されたクライアントの共存みたいな感じになっている。 このProxyFrameworkの強みはServerとClientでインタフェースを共有できる点かな。あとは一つのサービスの多くの種類のAPIを叩く場合にはインタフェースに分かれてるとやりやすいかもしれない。コードでURIを組み立てるか、インタフェースにアノテートするかの選択ができる。Jerseyのところで挙げた書き方もできるし、次のようにも書ける。

Station station = new ResteasyClientBuilder().build()
    .target(BASE_URL)
    .proxy(StationServiceProxy.class)
    .station(number);

ResteasyClientBuilderは先に挙げたClientBuilderのサブクラスだけど、ビルド手順が標準化されたのと違う感じになるので、どうしても歪さは出てくる。ClientBuilder#newClient()からいってもいいんだけど、途中でResteasyWebTargetにキャストしなきゃいけなくなるのはダサい……

Apache CXFさん

ごめん、CXFのことはよく知らないんだ(なぜ書いた)。サイトを見る限り、JAX-RS2.0のClientAPIの他に2種類提供している模様。

  • Proxy-based API
  • CXF WebClient API

Proxy-basedはRESTEasyのところで書いたのと同じ感じっぽい。これを残すのはかわる。 けれど、CXF WebClientAPIは標準のClientAPIとの差がわかりません。何か差別化できるところがあるんだろうか……。

まとめ

軽く使う分にはClient APIとしては標準のはそれなりに使いやすいし、特にはまりどころもなさそうな感じはする。 JAX-RS自体に慣れていないとProvider周りは困るだろうけど、それはそれ。

昔のバージョンから更新するときは、どの実装でも手作業で置き換えることになりそうだけど、標準に寄せるなら大したことしてないし、一から書き直しても知れているように思います。また、Proxyのを使ってるところはそのままで良いかなと。