JavaEEでもできる!JAX-RSでお手軽REST開発


最近のWebアプリケーションはRESTインターフェイスによるAPIを備えることが多くなってきました。

APIはWebアプリケーションの用途を大きく広げる重要な要素であり、また、これをシンプルなインターフェイスであるREST形式で提供することは、より APIを利用しやすくするための重要な手法となっています。

本エントリではJavaEEでRESTインターフェイスを提供するための仕様であるJAX-RSをご紹介します。

JAX-RSとは

前述のように、RESTによるAPI提供の重要性は増すばかりです。JavaEEにおいても、JavaEE6からRESTインターフェイスを開発するための仕様であるJAX-RSが提供されるようになりました。

JAX-RSの特徴として、アノテーションを使ったシンプルな開発スタイルが挙げられます。まずは基本的な使い方を見てみましょう。

最小のサンプル

それではJAX-RSの最小のサンプルを作ってみましょう。JavaEEコンテナ環境下であれば、たった2つのファイルを作るだけで済みます。

JAX-RSの設定クラス

まずはJAX-RSの設定を持つクラスを作りましょう。

ポイントは2つ。

  1. @ApplicationPath("/api")というアノテーションにより/api以下がJAX-RSで扱うURLになります
  2. javax.ws.rs.core.Applicationクラスを継承します。

クラス名はどんな名前でも構いません。また実装は何も必要ありません。

リソースクラス

JAX-RSによる開発の主たる作業は、リソースクラスを作ることです。

リソースというのは情報の断片のことで、URLで識別されるものです。リソースクラスは、リソースに対する操作をリクエストに従って処理するクラスとなります。

ここでは次のような仕様のリソースを、リソースクラスで実装してみましょう。

  • Hello, Worldというテキストをリソースとする
  • /api/hello/textというパスに対するGETメソッドでテキストが得られる
  • テキストのContent-Typeはtext/plain

クラス名は何でもいいのですが、ここでは分かりやすくHelloResourceとしましょう。

仕様がそのままアノテーションで表現されていますね。

ではブラウザで次のURLにアクセスしてみましょう。

http://localhost:8081/api/hello/text

次のような画面が表示されるはずです。

jax-rs_first

リソースクラスのポイント

JAX-RSの根幹、リソースクラスを詳しく見てみましょう。とはいえ非常に直感的なコードになっていますので、読み解きやすいと思います。

@PathアノテーションとURLの関係

クラスとメソッドに@Pathアノテーションを付与することで、このリソースクラスにアクセスするためのパス(≒URLの一部)を表現しています。

クラス宣言の@Pathアノテーションは、このリソースが/helloというパスで表されることを示しています。

メソッド宣言の@Pathアノテーションは、このリソースに実際にアクセスするためのパスを示しています。

実際にアクセスするためのパスは、JAX-RSの設定クラスに付与した@ApplicationPathアノテーションにも影響されることに注意してください。

/api/hello/textというパスの階層毎に対応するアノテーションをまとめてみましたので、イメージしてみてください。

jax-rs_url_path_mapping

メソッドに付与された@GET/@Producesアノテーション

リソースクラスのメソッドには、@Pathの他にも2つのアノテーションが付いています。いずれも重要なアノテーションです。

@GETアノテーションは、メソッドが動作するHTTPメソッドがGETであることを示しています。HTTPメソッドに該当するアノテーションとして、他にも@PUT/@POST/@DELETEなどがあります。

@Producesアノテーションは、このメソッドが返す値をどのようなデータ形式で返すかを示していて、HTTP応答ヘッダ内のContent-Typeを指定していることに相当します。


 

このようにJAX-RSによるREST開発は、HTTPインターフェイスをアノテーションを駆使して表現するというスタイルになります。

それではJAX-RSが提供する様々な機能を見ていきましょう。多数の機能があるのですが、重要なものに絞ってご紹介します。

POSTメソッドに対応する

POSTメソッドでアクセスされた時に動くメソッドには@POSTアノテーションを付与します。

パラメータを@FormParamアノテーションで受け取っています。これは後ほど、もっと詳しく解説します。

同じ考え方で、PUTメソッドやDELETEメソッドにも対応できます。単に@PUT@DELETEアノテーションを付与すればいいのです。直感的ですね。

@QueryParamアノテーションでクエリパラメータを受け取る

クエリパラメータとは、URLの?以降の部分を言います。例えば以下のURLのクエリパラメータはformat=jsonです。

これをリソースクラスで受け取るには、メソッド引数に@QueryParamアノテーションを付与します。

ブラウザで次のURLにアクセスしてみてください。

http://localhost:8081/api/hello/text-with-format?format=json

jax-rs_resource-class_queryparameter

確かにクエリパラメータが受け取れていますね。

@FormParamアノテーションでformのパラメータを受け取る

HTMLのformタグで送信するデータはapplication/x-www-form-urlencodedという形式であり、次のような書式のデータです。

JAX-RSではこの形式のデータは特別扱いであり、メソッドの引数に@FormParamアノテーションを付与することで値を受け取ることができます。

少し横道・JAX-RSのクライアントAPIによるテスト

RESTインターフェイスのテストを実施する際、GETであればブラウザで手軽にテストできますが、POSTやPUT、DELETEはそうはいきません。ところがJAX-RSにはクライアント用のAPIが備わっており、手軽にリソースクラスをテストすることができます。

JAX-RSのクライアント APIを使ってPOSTを送るサンプルを掲載しておきます。

パスパラメータを受け取る

URLの一部がパラメータになっているケースがよくあります。例えばよくあるブログエントリのURLがこれに相当します。

http://example.com/blog/2015/12/17

2015年12月17日のエントリという意味ですね。JAX-RSでこのようなパラメータを受け取るには、2つのアノテーションを併用します。

  1. メソッドの@PathアノテーションでURLパラメータを表現
  2. メソッド引数に@PathParamアノテーションを付与し値を受け取る

以下、サンプルです。

@Pathアノテーションに{パラメータ名}というスタイルでパラメータを表現しているのが分かると思います。

ブラウザで次のURLにアクセスしてみてください。

http://localhost:8081/api/hello/date/2015/12/17

jax-rs_pathparam

HTTPリクエストのヘッダ情報を受け取る

時にはクライアントから送信されてきたHTTPヘッダの情報が必要な時があります。この場合、HttpHeaders型のメソッド引数を作り@Contextアノテーションを付与します。するとHttpHeadersを通してヘッダ情報が得られます。

ブラウザで次のURLにアクセスしてみてください。

http://localhost:8081/api/hello/headers/accept

jax-rs_header

Servlet APIにアクセスする

リソースクラスの中でServlet APIにアクセスしたい場合、メソッド引数にServlet APIのオブジェクトを指定し、そこに@Contextアノテーションを付与します。

上記のように、HttpServletRequestServletContextは取得可能ですが、HttpSessionはこの方法では取得できません。本来、RESTとHttpSessionは相容れないものですのでこの仕様は妥当と言えますが、どうしてもHttpSessionが必要な場合は、次のようにして取得してください。

CDIの適用

リソースクラスはJavaEEコンテナ管理であるためCDI連携が可能です。ただ、CDI対象であることをコンテナに示すために、クラス宣言に@Dependentアノテーションを付与する必要があることに注意してください。

このことを踏まえると、リソースクラスは下記のようなコードになります。

なおCDIの詳しいことについては本ブログの「JavaEE屈指の便利機能、CDIを触ってみよう」というエントリをご参照ください。

JSONでデータをやり取りする

最後に、実践的な内容としてJSONでデータをやり取りする方法をご紹介します。

昨今のWebAPIの多くはJSON形式でデータをやり取りしますが、JAX-RSはデフォルトではJSONを扱えません。多少の設定追加が必要ですので、この章で見て行きましょう。

データ変換用のクラスを作成する

JAX-RSには、Content-Typeに応じてJavaオブジェクトを変換する処理を選択/実行する機能が備わっています。

ここではContent-Typeがapplication/jsonの時に動作する変換用クラスを作成します。MessageBodyReaderMessageBodyWriterインターフェイスを実装し、@Providerアノテーションを付与するのがポイントです。

実装すべきメソッドは5つあります。各メソッドの意味はコメントに書いておきました。どれも引数が多く見にくいかもしれませんが、実際のメソッドの中身はどれも1行ですので、臆さず読んでみてください。

なおこJSONとJavaオブジェクトの変換にはJSONICというライブラリを使っています。

リソースクラスでJSONレスポンスを返す

それではリソースクラスにJSON形式でデータを返すメソッドを追加しましょう。

@Produces(MediaType.APPLICATION_JSON)というアノテーションにより、レスポンスをJSON形式にすることを示しています。

それではブラウザで次のURLにアクセスして下さい。

http://localhost:8081/api/hello/json

jax-rs_json_01

 

レスポンスがJSON形式のデータであることや、レスポンスヘッダのContent-Typeがapplication/jsonになっていることが確認できます。

リソースクラスでJSONを受け取る

次にJSON形式のデータをPOSTで受け取るメソッドを作ってみましょう。

@Consumes(MediaType.APPLICATION_JSON)というアノテーションで、リクエストのContent-Typeがapplication/jsonである場合にこのメソッドが動作することを示しています。

クライアントAPIで動作確認をしてみましょう。

このメソッドを実行すると、リソースクラスのpostJson()メソッドが動作することが確認できるはずです。

まとめ

駆け足でJAX-RSを見てきました。実にシンプルな上、RESTの考え方にマッチした分かりやすい仕様になっているため、学びやすいと思います。

本エントリでは紹介しきれなかった機能の中には、サブリソースやキャッシュ制御、レスポンスの詳細な制御など重要なものがあります。幸い、オライリーから良いJAX-RSの指南書が出ています。分量が少なく読みやすいため、ぜひご一読をおすすめします。

冒頭に書いたように、Web APIの重要性は増すばかりです。JAX-RSを使ってRESTフルなAPIをどんどん開発し、Webサービスの価値を高めましょう。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">