Movatterモバイル変換


[0]ホーム

URL:


ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

この広告は、90日以上更新していないブログに表示しています。

Java における web アプリケーション開発ことはじめ (JAX-RS 2.0 / Jersey 2.4)

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!」 というテキストが返ってくるはずです。 このサンプルプロジェクトの詳細をこれ以降説明していきます。

Hello world!」 を返すJAX-RS/Jersey アプリケーションの作り方

そもそもJAX-RS とは?

RESTアーキテクチャにのっとって web アプリケーションを記述するためのJavaAPI です。Java EE の一部として定義されています。

JAX-RS 2.0 の仕様に書いている目標 (1.3 Goals) を簡単に紹介すると次のようなものがあります。

  • POJO-based:APIアノテーションの集合とそれに関連しており POJO と一緒に使えるようなクラスとインターフェイスを提供する*1
  • HTTP-centric: HTTP は基礎的なネットワークプロトコルであると考えており、JAX-RS は HTTP およびURI 要素とそれに対応するAPI クラスとアノテーションとのマップを提供する。
  • Format independence: 様々な HTTP エンティティボディコンテントの種類に対応する。
  • Container independence: 様々な種類の web 層のコンテナにデプロイ可能である。サーブレットコンテナやJAX-WS プロバイダへのデプロイ方法を定義する
  • Inclusion inJava EE: The specification will define the environment for a Web resource class hosted in aJava EE container and will specify how to useJava EE features and components within a Web resource class

つまり、原則的にはJAX-RS で定義されているアノテーションなどを使ってJAX-RS アプリケーションを書くことになります。 そして、JAX-RS に対応した HTTP サーバーやサーブレットコンテナでそのアプリケーションを実行させることができるわけです。JAX-RS アプリケーションは (理想的には) サーバーの実装に依存しないので、移植性が高くなります。

RubyPerl でも Rack やPSGI といった仕様が定義されていますが、大体そんな感じです*2

本記事ではサーバーサイドの話のみを記述しますが、JAX-RS 2.0 ではクライアントサイド用のAPI も定義されました。

Hello world!」 を返すシンプルなJAX-RS アプリケーション

Servlet コンテナで実行されるJAX-RS アプリケーションを単純に実装すると上のコミットのような感じになります。JAX-RS アプリケーションとして重要な部分は、次の 2 つのクラスです。

上のコミットでは、どちらのクラスもJAX-RS 仕様に含まれるアノテーションやクラスのみを使用しています。

最近のServlet 仕様では、ある条件下において web.xml デプロイメント記述子を省略できるらしくて*4JAX-RS アプリケーションをServlet コンテナで実行させる場合も特定条件下では web.xml を省略できます。

例えば、上のコミットの例のように、Application クラス のサブクラスが含まれていて、そのクラスに@ApplicationPath アノテーション が付けられている場合で、Servlet 3 framework pluggability mechanism が使われるコンテナで使用する場合は web.xml を省略できます*5。 よって、上のコミットの内容で WAR ファイルを作ってGlassFish サーバーなどにデプロイすればJAX-RS アプリケーションが動くはずです。

JAX-RS 実装 Jersey

JAX-RS アプリケーションを動作させるための実装の 1 つに Jersey があります。 Jersey はJAX-RS の参照実装でもあります。

Jersey はアプリケーションサーバー GlassFish の中に組み込まれているので、GlassFish 上でJAX-RS アプリケーションを動かす場合には Jersey を使用することになるでしょう。 また、Jersey はJAX-RS アプリケーションを実行することのできるServlet 実装も提供しているので、Jersey が提供しているServletJAX-RS アプリケーションをラップさせて、任意のServlet コンテナでJAX-RS アプリケーションを実行するということもできます。

また、単にJAX-RS アプリケーションを動かす側の実装だけでなく、JAX-RS アプリケーションを実装するために便利なAPI を提供してくれたりもします。 今回のサンプルプロジェクトでも Jersey の便利な機能を使っているので、この下で紹介します。

Jersey を使ってApplication のサブクラスをより簡易に実装する

Jersey にはResourceConfig というApplication クラス のサブクラスが含まれています。

これを使用することで、例えばgetClasses メソッドを自分で実装する必要がなくなったりします。 今回のサンプルプロジェクトでは、packages メソッドを使ってリソースクラスが入っているパッケージ名を指定し、リソースクラスをスキャニングさせるように変更しました。

Jersey のテストフレームワークを使用する

Jersey には、テスト用のフレームワークも含まれています。

JUnit ベースなので、Jersey のテストフレームワークを使う障壁は低いでしょう。 テスト時に使用されるJAX-RS アプリケーションのコンテナはいくつか用意されているので、その点でも扱いやすいです。 また、外部コンテナも使用できるようです。

今回のサンプルプロジェクトでは、「Hello world!」 という文字列がレスポンスとして返されるかどうかを調べるテストを書いてみました。

Servlet 3.x コンテナの中で Jersey アプリケーションを動かす

上で書いたように、GlassFish などの一部のサーブレットコンテナでは明示的なServlet の指定をしなくてもJAX-RS アプリケーションを認識してくれるっぽいのですが、web.xml にちゃんとServlet を明示しないとだめなServlet 3.x コンテナもあるようです。 (Jetty 9 で試したところ web.xmlServlet を明示しないと動いてくれませんでした。 が、web 上を見てたら Jetty 9 でも web.xml 不要とか書いてる記事もあるので私の使い方がおかしいのかも。)

今回の例では、Jersey が提供するServletContainer*6 を使って、任意のServlet 3.x コンテナにデプロイできるようにしました。

Servlet 3.x コンテナ用のサーバー側実装だけでなく、Servlet 2.x コンテナ用の実装など、他のJAX-RS アプリケーションコンテナの実装もあります。

HTTP サーバー Jetty で開発時の状況を確認する

開発中は手早く開発用のサーバーを起動したりホットデプロイしたりしたいですよね。 Gradle には jetty プラグインが標準でついているので、開発用サーバーとして Jetty を起動したりデプロイしたりということがしやすくなっています。

クラスファイルが更新されたときにはホットデプロイもされるようです。 IDE と併用して、IDE 側でリアルタイムコンパイルを走らせて Jetty にホットデプロイする、というような使い方が考えられます。

もちろん IDE 側に開発サーバーと連携する機能があるならそっちを使えばいいかもしれませんが。

開発環境の話

ここまでは特に IDE には依存しないような感じで書いてきましたが、実際の開発では IDE を使うことになると思います。 Web 上で調べてみたところお、JAX-RS アプリケーションを書くならNetBeans 一択というような感じがしました。 実際、自分でもEclipseNetBeansIntelliJ を試してみましたが、JAX-RS アプリケーションを書くならNetBeans が使いやすいように感じました。

NetBeans を使う場合は開発用のサーバーはGlassFish が標準なので、GlassFish を使うことになると思います。NetBeans +GlassFish の開発環境を準備する話は次の記事が参考になりました。

NetBeansJAX-RS に従った web アプリケーションを作る方法については次のチュートリアルが参考になります。

しかし、Gradle やMaven を使ってるプロジェクトをNetBeans にインポートするとき、プロジェクト管理をそのまま Gradle やMaven を使って行うのは難しいっぽい感じがしますね。 IDE によるプロジェクト管理と IDE に依存しないプロジェクト管理をどうするか、みたいなの悩ましい感じがします。

まとめ

単に 「Hello world!」 を返すような web アプリケーションを例に、JAX-RS アプリケーションの基本的な作成方法を説明しました。 今回は次のようなものを使いました。

  • JAX-RS アプリケーションの実装に Jersey が提供しているJAX-RS アプリケーション用の便利機能を使った
  • JAX-RS アプリケーションをServlet 3.x コンテナで実行するために、Jersey が提供しているServlet 実装を使った
  • JAX-RS アプリケーションを WAR に固めるために Gradle の war プラグインを使った
  • JAX-RS アプリケーションを開発時に簡単に動かせるように Gradle の jetty プラグインを使った

一口にJAX-RS アプリケーションといっても、どのサーバーで動かすかなどによって作法が変わってくるところもあるのでどうすればいいのか結構悩んでいたのですが、今のところ IDE に依存しない感じでプロジェクトを作るなら上のような感じが良さそうだなーと思っています。

参考文献

JAX-RS の基本的なことを知るなら次の本がオススメです。

JavaによるRESTfulシステム構築

JavaによるRESTfulシステム構築

あとは次のような記事が参考になります。

  • JAX-RSとかの話 — 裏紙 :Java EE 周りをある程度理解している人ならJAX-RS のとっかかりとしてこの記事がわかりやすいと思います。 本記事のサンプルコードでは Jersey 2.4 を使っていますが、この記事では Jersey 1 系が使われていることには注意が必要です。 (Jersey のパッケージ名が違うしコピペして動かない可能性がある)
  • [Java] Jetty9(Servlet3.0)でJAX-RS | ルクサエンジニアのブログ : Jetty 9 (Servlet 3.x) でJAX-RS アプリケーションを動かすという記事。 ちょっと参考にしたので参考文献として挙げましたが、間違ってる部分もあるということで削除しておきます。 詳しくは本記事のコメント参照。
  • JAX-RS実装のデプロイメントについて | OPENSQUARE.jp - BLOG :JAX-RS アプリケーションのデプロイに web.xml デプロイメント記述子は省略できるのかどうか、ということを試している記事。 「基本的に web.xml は必要」 という結論っぽいけど、必ずしも web.xml が必要というわけではないので注意が必要。 これに関してもコメント頂いたので、本記事のコメントの方がご覧ください。
  • eXtreme JAX-RS : HTTP とJAX-RS の関係といった基礎的なことから、デプロイ方法についてやJAX-RS における認証・認可についての話などが書かれたスライド。 わかりやすいです。
  • JAX-RS 2.0 ことはじめ - Programming Studio :JAX-RS 2.0 仕様についての概観。 上のスライドの方がオススメだと著者の Hasunuma さんからコメント頂きました。

*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 です。

注目記事
検索
最近のコメント
    カテゴリー

    引用をストックしました

    引用するにはまずログインしてください

    引用をストックできませんでした。再度お試しください

    限定公開記事のため引用できません。

    読者です読者をやめる読者になる読者になる

    [8]ページ先頭

    ©2009-2025 Movatter.jp