[Java] JAX-RS 2.1 Reactive Client API

原文はこちら。
https://blogs.oracle.com/PavelBucek/entry/jax_rs_2_1_reactive

Marekに代わって、JAX-RSの共同Spec leadに選ばれたことを発表できうれしく思っています。ってわけで、この先数ヶ月間、おおよそJavaOne 2017までの間に関するエントリを記載します。

様々な仕様における議論をフォローしているのであれば、昨年のJAX-RSの議論は非常に閑散としたものだったことにお気づきかもしれません。しかし、変わりつつあります。いや、既に変わりました。Expert Group (EG) はアップデートされたスケジュールで、主として以下の3件について作業をしています。
  • Reactive Client API
  • Server Sent Events
  • Non-blocking I/O
最初の2件は、既に提案済みではあるものの、まだExpert Groupから祝福されてはいませんでした。そのため、(必要であれば)アップデートし、レビューの上、そのコメントを反映する必要がありますが、実際にReactive Client APIで発生しましたので、このエントリではその内容をまとめます。

JAX-RS Reactive Client API

まず、この機能の目的は、クライアント側でのリアクティブスタイルのプログラミングのサポートを含めることであって、それ以外のことはありません。また、別のクライアントを作成したくはありません。既存のものは既に同期および非同期のリクエスト実行をサポートしており、これをリアクションスタイルで拡張したいと考えています。
簡単な例を見てみましょう。
CompletionStage<Response> csResponse = ClientBuilder.newClient()
                                       .target("http://oracle.com")
                                       .request()
                                       .rx()
                                       .get();
何か新しいものがあることに気付かれたことでしょう。戻り型がjavax.ws.rs.Responseでも、(rx()がasync()に置き換えられた場合には)Future <Response>でもなく、Client fluent API呼び出しチェーンにある新しいメソッド、rx()です。
javax.ws.rs.Response
http://docs.oracle.com/javaee/7/api/javax/ws/rs/core/Response.html 
CompletionStageは、Java 8で導入された新しいインターフェースです。これはプラットフォームに組み込まれた唯一のリアクティブ標準です(詳細は後で)。今回、rx() メソッドが追加されたことにより、SyncInvoker/AsyncInvokerから、新しいRxInvokerに切り替えることができるようになりました。
Interface SyncInvoker
https://docs.oracle.com/javaee/7/api/javax/ws/rs/client/SyncInvoker.html
Interface AsyncInvoker
https://docs.oracle.com/javaee/7/api/javax/ws/rs/client/AsyncInvoker.html
RxInvokerは他のメソッドと同じメソッドを定義しますが、同じ方法で指定された戻り値の型は持ちません。CompletionStageRxInvokerという、現在提案中のAPIで実施しているように、CompletionStageに対してサブクラスを作成し、再定義することができます。
CompletionStageRxInvoker.java
https://github.com/jax-rs/api/blob/master/jaxrs-api/src/main/java/javax/ws/rs/client/CompletionStageRxInvoker.java
rx() メソッドにはいくつかのバリエーションがあります。1つはExecutorServiceの提供に関連し、もう1つはRxInvokerクラスの提供に関するものです。
ExecutorService
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html 
前者は簡単に説明ができます。つまり、リアクティブな呼び出しは本質的に非同期であって、スレッドプールやExecutorServiceを指定できるようにしたい、ということです(例えば、後で再度呼び出されたり、クライアント全体にわたる非同期executorサービス構成を許可することによって削除されたりする可能性があります)。後者は拡張性に関するものです。

Reactive Extensions

リアクティブなアプリケーションをJavaで実装する場合、さまざまなフレームワークが提供する他のデータ型を知っていることがほとんどでしょう。Guava、RxJavaなどといった、これらのフレームワークは、CompletionStageと同様の機能を提供しますが、APIが異なります。特に、他の非標準フレームワークを使って作成されたアプリケーションを有していて、JAX-RSができるだけ簡単に使用できるようにしたい場合は、これらを使用すると便利です。 コード例を見てみましょう。
Client client = ClientBuilder.newClient();
client.register(FlowableProvider.class);

Flowable<Response> csResponse = client.target("http://oracle.com")
                                .request()
                                .rx(FlowableInvoker.class)
                                .get();
ここで、JAX-RSのResponseを取得する際に、RxJava2のFlowableを利用できることがわかります。
Flowable
http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html 
FlowableProvider、FlowableInvokerとも、第三者が提供しています。たとえば、RxJava2の開発者コミュニティのJAX-RSが十分に重要と考える場合、これらのクラスを含む拡張モジュールがリリースされる可能性があります。また、いつものように、任意のJAX-RS実装は機能を選択でき、同様のプロバイダを実装の一部として提供することができます。
変更される可能性があるため、詳細に入ることは避けますが、現時点では、これが拡張性の提供に関する最善の方法であるとの結論に達したようです。議論の経緯を知りたい方は、JAX-RS仕様のExpert Groupメーリングリストをご覧ください。

新たに提案されたAPIを気に入ってもらえることを願っています。何かコメントがありましたら、JAX-RSプロジェクトのユーザーメーリングリストに投稿してください。

Links, mailing lists, etc.

0 件のコメント:

コメントを投稿