home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

Java/JAX-RS/勉強メモ(JAX-RS 2.0)

Java/JAX-RS/勉強メモ(JAX-RS 2.0)

Java / JAX-RS / 勉強メモ(JAX-RS 2.0)
id: 1283 所有者: msakamoto-sf    作成日: 2014-04-29 23:30:54
カテゴリ: Java 

JAX-RS 2.0 (JSR 339)の使い心地について調べたのでメモ。

実装:

  • Jersey
    • https://jersey.java.net/
      • GlassFish プロジェクトでも使われてる、Sunマイクロシステムズ時代からのJAX-RSのリファレンス実装。ライセンスはCDDLv1.1とGPLv2のデュアルライセンス。
  • Apache CXF -- Index
    • http://cxf.apache.org/
      • JAX-RSだけでなく、JAX-WSも含めたWebサービスの実装。ライセンスは当然ASL2.0
  • RESTEasy - JBoss Community

雑多なトピック

JAX-RSを一般的なWebアプリケーションのためのフレームワークとしてはどう評価されているのか?

結論:まずます良さげ。

JAX-RS関連調べてて気になったトピック

JAX-RSでのユーザ認証について

Servletコンテナで提供しているRoleベースの認証機能を使う。JAX-RSでは"@Context"アノテーションでSecurity Contextにアクセスできるよう定められているため、Servletコンテナ側でBasic認証など設定していれば、FilterなどのProviderや、リソースから"@Context"経由で参照し、処理出来る。

→結論は↓のトピックに持ち越し

RESTfulなAPIサービスと、HTTPセッションについて

以下、RESTfulなAPIサービスで認証をどう実装すればよいのか、Stack Overflowでも賑わってました:

→結論は↓のトピックに再度持ち越し

RESTとステートレス性についてのそもそもの話

RESTではスケーラビリティ等を考慮して、ステートレスにしよう、という思想がある。そこで、CookieによるセッションIDで認証状態を管理してしまうと、サーバ側でのスケーラビリティで色々制約や工夫の必要が生じてしまうので、なるべくクライアント側だけでステートを持たせようね、という話があるようです。

結論・・・というかとりあえずの検討結果:

  • ステートレス性を犠牲にしてスケーラビリティで苦労するのを受け入れた上で、普通にServletのCookieによるセッション管理機能をフィルタとかで組み込む方向性はアリだと思いました。
  • Ajaxを使ったRIAで、AjaxだけBasic認証というのはかなり辛いと思いますので、OAuth2.0系を使ってtokenをクライアント側で管理してGET以外のパラメータでやりとりするのもありかなと。GETでやりとりしてしまうとプロキシやサーバログとかに残ってセキュリティ上問題になるので、GET禁止・・・となるとまたRESTの特性の一部が失われますが。
  • Railsがやってるように、Client側のCookieの中にセッション状態を詰め込むのもアリだと思いますが、これはもう言語やプラットフォームごとにこのアプローチの得手不得手が出てきてしまいます。うかつに独自実装すると、セキュリティ上穴が出来てしまわないか怖いですし・・・。
  • どちらにしても、原理主義でいくか、現場主義でいくか、バランス取らないとやってけないと思いました。

JAX-RS 2.0のフィルタ機能の参考

フィルタ中から、ContainerRequestContext#setProperty()経由でセットしたオブジェクトを、リソースクラスから読み出せるか?

結論:JAX-RS 2.0としての仕様ではそうしたアクセス用APIは(多分)提供されてない(っぽい)。
一応、Servletアプリ上で動かす場合はContainerRequestContext#setProperty()/getProperty()は ServletRequest の Attribute と連動しているよう定められているため、リソースクラスに "@Context" で HttpServletRequest をインジェクションして、そこから取り出す方法はある。
なお、JAX-RSのApplicationクラスが提供しているgetProperties()は、JAX-RSアプリ全体のconfigurationだったり、Servlet実装の場合は<context-param>や<init-param>と連動してたりするため、フィルタ機能とは関係ない。ただし、アプリ全体の設定値を取得する際には活用できそう。

Jersey使った時に、アプリ全体の初期化処理用のフックとかあるかな?(Servletのinitみたいな)

結論:仕様としては、無い。

ただし、例えばFilterはライフサイクル上、ひとつのアプリで1インスタンスだけなので、コンストラクタでグローバルな設定を初期化するのはアリだろう。
また、Servletコンテナ上で動かすのであれば、普通にServletのinit中で、Singletonで初期化するのもアリ。Servlet中のClassLoader上で動作するのであれば、JAX-RSアプリ内からも参照できるはず。Singletonを上手く使うのもちょっと色々工夫がいるだろうけど・・・。
あとはSpringやGuiceなどのDIコンテナと上手く組み合わせて工夫するとか。

エラー・例外のカスタマイズ

リソースクラスの処理内で発生した例外についてはこんな感じかな?

  1. 自力でtry-catchした後に、カスタマイズした専用のWebApplicationException派生の例外クラスをthrowする。
  2. カスタマイズしたException派生の例外クラスをthrowし、それに対応するExceptionMapperをProviderとして用意しておく。
  3. カスタマイズしたException派生の例外クラスをthrowし、実行環境(Servletコンテナなど)のデフォルトの例外処理に委譲する。

また、JAX-RS側のデフォルトの404例外などをカスタマイズしたい場合は、内部的に以下のような例外が定められていてthrowされるので、それに対応するExceptionMapperを自分たちで準備しておけば良いっぽい。(単にJavaDocからそれっぽいのを引っ張ってきてるだけのため、本当にそうなのかは不明。)

  • NoContentException
  • NotAcceptableException
  • NotAllowedException
  • NotAuthorizedException
  • NotFoundException
  • NotSupportedException

こういうのがあるのを知っておけば、カスタム例外を作る手間が省けて、JAX-RS側で用意してくれてるこれらの例外で済ませられるケースもあるかも?

レスポンスHTTPヘッダーやボディのカスタマイズ

結論としては、HTTPレスポンスのカスタマイズ性は非常に自由度が高い状態にある。
まず、Response#status()でステータスコードを指定してResponseBuilderのインスタンスを取得する。
ResponseBuilderには、以下のようにレスポンスをカスタマイズできるメソッドが公開されている。

  • entity() : byte[]やStringやObjectなど、レスポンスBODYを設定出来る。
  • header() : レスポンスヘッダをカスタマイズ出来る。
  • type() : Content-Typeヘッダをカスタマイズできる。"text/html"や"application/octet-stream"など頻用される値についてはMediaTYpeのstaticインスタンスとして定義済みなので、いちいち正確な綴りを思い出す必要がない。"charset"指定も、自然な形でメソッドとして統合されている。
  • location() : 基本的にリダイレクト系は、Response#seeOther(URI), temporaryRedirect(URI), created(URI) でステータスコードも一緒に設定してくれるが、フルカスタマイズで個別にLocationヘッダーを設定したい場合はこちらのメソッドが使える。
  • encoding() : ガラケーサイト向けにSJISで出力したい、という場合に、entity()にはJava世界の文字列をそのままStringで渡して、こちらのencoding()で実際に出力するときのエンコーディングを指定する。Content-Typeのcharsetが自動的に連動してくれるかは不明なので、自分でtype()で指定しておくのが無難か。

上記メソッドは、いずれもそのメソッドで更新されたResponseBuilder()を返してくるので、メソッドコールのチェインをつなげていく格好になり、最後に"build()"メソッドを呼べば、最終的なResponseクラスのインスタンスが返される。これを単純にreturnすればよい。

※"@Context"でHttpServletResponseをインジェクとしてもらって、それも合わせて操作した場合に、何か衝突など発生しないか、については未検証。セッション管理系のCookie操作とか大丈夫かな?



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-04-29 23:32:12
md5:a81f82b9eab50f378180a203e0cda1af
sha1:7d766c11f4bf66fa0a08b9e803a186486cf4ac2e
コメント
コメントを投稿するにはログインして下さい。