まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。
この広告は、90日以上更新していないブログに表示しています。
JAX-RS を使ってJava で web アプリケーションを開発したい、と思っても、Java EE 周りに詳しくないと何をどうすればいいか全然わかんないですよね! そんなことないですか? 少なくとも私はよくわかんなかったです。
そんなわけなので、JAX-RS を使って web アプリケーションを開発しようと思った人のために、「Hello world!」 ってテキストを返すだけの web アプリケーションを作るところまで説明したいと思います。
GitHub 上にサンプルプロジェクトをおいています。
Git とJDK がインストールされていれば、次のように 3 つのコマンドを実行するだけでサンプルプロジェクトを手元のサーバーで動かすことができます。
# プロジェクトをクローンgit clone -b hello_world git@github.com:nobuoka/jax-rs-jersey-application-sample.git# ディレクトリ移動cd jax-rs-jersey-application-sample# ビルドしてサーバーを起動./gradlew jettyRun
Web ブラウザなどで http://localhost:8080/jax-rs-jersey-application-sample/ にアクセスすると、「Hello world!」 というテキストが返ってくるはずです。 このサンプルプロジェクトの詳細をこれ以降説明していきます。
RESTアーキテクチャにのっとって web アプリケーションを記述するためのJava のAPI です。Java EE の一部として定義されています。
JAX-RS 2.0 の仕様に書いている目標 (1.3 Goals) を簡単に紹介すると次のようなものがあります。
つまり、原則的にはJAX-RS で定義されているアノテーションなどを使ってJAX-RS アプリケーションを書くことになります。 そして、JAX-RS に対応した HTTP サーバーやサーブレットコンテナでそのアプリケーションを実行させることができるわけです。JAX-RS アプリケーションは (理想的には) サーバーの実装に依存しないので、移植性が高くなります。
Ruby やPerl でも Rack やPSGI といった仕様が定義されていますが、大体そんな感じです*2
本記事ではサーバーサイドの話のみを記述しますが、JAX-RS 2.0 ではクライアントサイド用のAPI も定義されました。
Servlet コンテナで実行されるJAX-RS アプリケーションを単純に実装すると上のコミットのような感じになります。JAX-RS アプリケーションとして重要な部分は、次の 2 つのクラスです。
Root
クラス: 「Hello world!」 を表すリソースクラス。 ルートパスに対応することをアノテーションで示している。 このようにアノテーションによって特定のURI と対応付けられたクラスをJAX-RS ではリソースクラスと呼ぶ。MyApplication
クラス: アプリケーションの設定等を含むクラス。 このgetClasses
メソッドの返り値に含まれるクラスがリソースクラスとして使われる。*3上のコミットでは、どちらのクラスもJAX-RS 仕様に含まれるアノテーションやクラスのみを使用しています。
最近のServlet 仕様では、ある条件下において web.xml デプロイメント記述子を省略できるらしくて*4、JAX-RS アプリケーションをServlet コンテナで実行させる場合も特定条件下では web.xml を省略できます。
例えば、上のコミットの例のように、Application
クラス のサブクラスが含まれていて、そのクラスに@ApplicationPath
アノテーション が付けられている場合で、Servlet 3 framework pluggability mechanism が使われるコンテナで使用する場合は web.xml を省略できます*5。 よって、上のコミットの内容で WAR ファイルを作ってGlassFish サーバーなどにデプロイすればJAX-RS アプリケーションが動くはずです。
JAX-RS アプリケーションを動作させるための実装の 1 つに Jersey があります。 Jersey はJAX-RS の参照実装でもあります。
Jersey はアプリケーションサーバー GlassFish の中に組み込まれているので、GlassFish 上でJAX-RS アプリケーションを動かす場合には Jersey を使用することになるでしょう。 また、Jersey はJAX-RS アプリケーションを実行することのできるServlet 実装も提供しているので、Jersey が提供しているServlet にJAX-RS アプリケーションをラップさせて、任意のServlet コンテナでJAX-RS アプリケーションを実行するということもできます。
また、単にJAX-RS アプリケーションを動かす側の実装だけでなく、JAX-RS アプリケーションを実装するために便利なAPI を提供してくれたりもします。 今回のサンプルプロジェクトでも Jersey の便利な機能を使っているので、この下で紹介します。
Application
のサブクラスをより簡易に実装するJersey にはResourceConfig
というApplication
クラス のサブクラスが含まれています。
これを使用することで、例えばgetClasses
メソッドを自分で実装する必要がなくなったりします。 今回のサンプルプロジェクトでは、packages
メソッドを使ってリソースクラスが入っているパッケージ名を指定し、リソースクラスをスキャニングさせるように変更しました。
上で書いたように、GlassFish などの一部のサーブレットコンテナでは明示的なServlet の指定をしなくてもJAX-RS アプリケーションを認識してくれるっぽいのですが、web.xml にちゃんとServlet を明示しないとだめなServlet 3.x コンテナもあるようです。 (Jetty 9 で試したところ web.xml にServlet を明示しないと動いてくれませんでした。 が、web 上を見てたら Jetty 9 でも web.xml 不要とか書いてる記事もあるので私の使い方がおかしいのかも。)
今回の例では、Jersey が提供するServletContainer
*6 を使って、任意のServlet 3.x コンテナにデプロイできるようにしました。
Servlet 3.x コンテナ用のサーバー側実装だけでなく、Servlet 2.x コンテナ用の実装など、他のJAX-RS アプリケーションコンテナの実装もあります。
ここまでは特に IDE には依存しないような感じで書いてきましたが、実際の開発では IDE を使うことになると思います。 Web 上で調べてみたところお、JAX-RS アプリケーションを書くならNetBeans 一択というような感じがしました。 実際、自分でもEclipse やNetBeans、IntelliJ を試してみましたが、JAX-RS アプリケーションを書くならNetBeans が使いやすいように感じました。
NetBeans を使う場合は開発用のサーバーはGlassFish が標準なので、GlassFish を使うことになると思います。NetBeans +GlassFish の開発環境を準備する話は次の記事が参考になりました。
NetBeans でJAX-RS に従った web アプリケーションを作る方法については次のチュートリアルが参考になります。
しかし、Gradle やMaven を使ってるプロジェクトをNetBeans にインポートするとき、プロジェクト管理をそのまま Gradle やMaven を使って行うのは難しいっぽい感じがしますね。 IDE によるプロジェクト管理と IDE に依存しないプロジェクト管理をどうするか、みたいなの悩ましい感じがします。
単に 「Hello world!」 を返すような web アプリケーションを例に、JAX-RS アプリケーションの基本的な作成方法を説明しました。 今回は次のようなものを使いました。
一口にJAX-RS アプリケーションといっても、どのサーバーで動かすかなどによって作法が変わってくるところもあるのでどうすればいいのか結構悩んでいたのですが、今のところ IDE に依存しない感じでプロジェクトを作るなら上のような感じが良さそうだなーと思っています。
JAX-RS の基本的なことを知るなら次の本がオススメです。
あとは次のような記事が参考になります。
*1:つまり、POJO (= 通常のJava クラス) としてリソースを表すクラスを定義できる
*2:厳密にいうとJAX-RS は HTTP リクエストやレスポンスそのものには触らないようになっているので、Rack やPSGI と比べると少し高度ではあります。
*3:Application
のサブクラスがアーカイブファイルに含まれていない場合や、getClasses
が空のSet
を返す場合にはアーカイブファイル内のリソースファイルを全て検索されたりするが、ここでは説明しない。
*4:詳しいことは知らない。
*5:JAX-RS 2.0 仕様を読むとそんな風に読み取れるけど違うかもしれない。
*6:ServletContainer
という名前ですが、Servlet コンテナではなくてJAX-RS アプリケーションのコンテナの役割をするServlet です。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。