Java 開発 2.0: Gretty を使った超軽量の Java Web サービス

Gretty はアプリケーション開発をまさに迅速化するために Web スタックを放棄します

Gretty は、Web サービスを構築するために作られた新しいタイプの超軽量フレームワークの 1 つです。超高速の Java NIO API をベースにした Gretty は、Web エンドポイントのドメイン特化言語として Groovy を使用し、Grape を使用して Maven スタイルの依存性管理を行います。この記事を読んで、Gretty を使用して Java Web サービス・アプリケーションを構築してデプロイする方法を学んでください。

Andrew Glover, Author and developer, Beacon50

Andrew GloverAndrew Glover は、ビヘイビア駆動開発、継続的インテグレーション、アジャイル・ソフトウェア開発に情熱を持つ開発者であるとともに、著者、講演者、起業家でもあります。また、easyb BDD (Behavior-Driven Development) フレームワークの創始者、そして『継続的インテグレーション入門 開発プロセスを自動化する47の作法』、『Groovy in Action』、『Java Testing Patterns』の 3 冊の本の共著者でもあります。詳細は彼のブログにアクセスするか、Twitter で彼をフォローしてください。



2011年 9月 16日

連載「Java 開発 2.0」では、これまで数回にわたって単純なクラウド用モバイル・アプリケーションをベースに話を進めてきました。Magnus と名付けたこのアプリケーションは、モバイル機器の位置情報をリッスンする HTTP エンドポイントの役割を果たします。Magnus が機能するためには、特定の時点でのアカウントの位置を示す JSON 文書が含まれる HTTP PUT リクエストを受信しなければなりません。この Magnus を開発し、拡張するために今まで使ってきた Web フレームワークは、Play です (「参考文献」を参照)。

この連載について

Java 技術が初めて登場してから現在に至るまでに、Java 開発の様相は劇的に変化しました。成熟したオープンソースのフレームワーク、そしてサービスとして提供される信頼性の高いデプロイメント・インフラストラクチャーを利用できる (借りられる) おかげで、今では Java アプリケーションを短時間かつ低コストでアセンブルし、テスト、実行、保守することが可能になっています。この連載では Andrew Glover が、この新たな Java 開発パラダイムを可能にする多種多様な技術とツールを詳しく探ります。

Play は、MVC スタックを提供するという点で Grails とよく似ています。Play ではビュー (JSP、GSP、テンプレートなど) を使用するコントローラー (サーブレット) を簡単に定義して、何らかの方法でモデルを操作することができます。これらのモデルを実装するには、Hibernate、JPA、あるいはその他の巧妙な ORM 風の技術で強化した POJO (Plain Old Java Object) を使用します。

MVC は以前からの標準ですが、Grails や Play のようなフレームワークの登場によって、大幅に変化しています。かつて、Web でのリクエストとレスポンスによる単純な対話を (例えば Struts を使用して) できるようにするために必要だった作業量を思い出してください。それだけでも、MVC Web アプリケーションをいかに短時間で構築できるようになったか実感するはずです。そうは言っても、すべての Web アプリケーションで MVC インフラストラクチャーが機能していなければならないわけではありません。最近では、MVC スタックがまったく必要ない Web アプリケーションもあります。

このような異端の意見に抗議してブラウザーを閉じる前に、Magnus を思い出してください。Magnus はあくまでもデモ用に考案されたものですが、このクラウド用モバイル・アプリケーションには従来のビュー・コンポーネントは一切含まれていません。その大部分は、すでに成功を収めている実在のサービスを手本にしています。例えば Twitter や Foursquare のように、Magnus は世界中のさまざまな機器からのメッセージを受信します。大まかに言うと、Magnus は Web サービスです。すべての Web サービスがその役目を果たすために MVC スタックを必要とするわけではありません。場合によっては、Web スタックがなくても、超軽量 Web フレームワークで必要を満たせるものもあります。

今月は、このような超軽量 Web フレームワークの 1 つである Gretty を見て行きます。この迅速な開発が可能なフレームワークはごく最近登場したばかりで、専用のホーム・ページもないほどですが、そもそもホーム・ページは必要ないかもしれません。Gretty が受け継いでいる系統 (Netty) と関連性 (Groovy) だけで、Gretty を Java 2.0 Web 開発ファミリーの一員と見なすにはすでに十分だからです。Gretty は多くの開発者がまだ気付いてもいない必要性を満たします。(それは、真の Web 2.0 スタイルです。ご存知でしたか?) Gretty は本番環境で使用するのにも十分安定しています。ただし、さまざまな環境がまだ十分には整っていないのを承知で使用する気があれば、の話です。

これまでの迅速な Java 開発

大量のコードやそれに伴う JAR ファイルもなしに、単純なサーブレットだけで Web サービスを構築できるという新しい「軽量」のパラダイムに対して、Servlets API が初めて登場した頃のことを覚えている開発者が懐疑的な態度をとるのは無理もありません。例えば、Restlet および Jersey といった Web サービス・フレーワークは、開発を迅速化する手法として他とは少し異なる手法を取っていて、クラス継承、アノテーション、さらには標準 JSR をベースに RESTful な Web サービスを作成します。シナリオによっては、この 2 つは今でも優れた選択肢となります。

けれども、(かつての軽量フレームワークではなく) 新しい軽量フレームワークのいくつかは、Web サービス、あるいは単純な HTTP エンドポイント (「ルート」とも呼ばれます) を驚くほど簡単に定義できることが明らかになっています。その単純さは、サーブレットさえも上回るほどです!

当初、これらの新しい軽量フレームワークは、Ruby 用の Sinatra や Node.js 用の Express をはじめ、Java 以外のプラットフォームで登場しましたが、Java プラットフォーム用の興味深いプロジェクトも登場し始めました。そのなかの 1 つが Gretty で、もちろん Groovy と JVM 向けに作成されたものです。


私は Gretty を支持します

Gretty には、私好みの点が少なくとも 2 つあります。その 1 つは、Groovy の Grape (後で詳しく説明します) を使用して依存関係を管理しやすくしているところで、もう 1 つは、単純な DSL のような構文でエンドポイントを定義できるところです。Gretty では、実際のビジネス・ロジックを処理する実用的な Web ルーティング・フレームワークをあっという間に (2、3 行の短いコードで) 定義してデプロイすることができます。一例として、リスト 1 に標準的な Hello World アプリケーションを素早く作成してみます。

リスト 1. Hello, World: これが Gretty です!
import org.mbte.gretty.httpserver.* 

@GrabResolver(name='gretty', 
  root='http://groovypp.artifactoryonline.com/groovypp/libs-releases-local')
@Grab('org.mbte.groovypp:gretty:0.4.279') 

GrettyServer server = [] 
server.groovy = [ 
    localAddress: new InetSocketAddress("localhost", 8080), 
    defaultHandler: { 
        response.redirect "/" 
    }, 
    "/:name": {
        get {
            response.text = "Hello ${request.parameters['name']}"
        } 
    } 
] 
server.start()

リスト 1 では、ポート 8080 をリッスンするサーバーを作成した後、単純なルート・エンドポイントをセットアップして、そこに nameパラメーターを含めています。他のエンドポイントに対するリクエストは、defaultHandler によって / に戻されます。このデフォルト・ハンドラーは基本的に、リクエスト側クライアントに / の位置と併せて HTTP 301「moved permanently」コードを送信します。すべてのリクエストが受信する (コンテンツ・タイプが text/plain に設定された) レスポンスには、「Hello」および渡されたパラメーターの値からなるストリングが含まれます。例えばパラメーターの値が「/Andy」だとすると、「Hello Andy」というストリングになります。

Gretty と NIO

Gretty を作成するために使用された Netty は、Java の NIO ライブラリーを多用するクライアント・サーバー・フレームワークです。I/O ライブラリーに含まれる NIO (New I/O) パッケージは、Java 1.4 が登場する際に導入されました。NIO が最も注目を浴びている点は、その非ブロッキング IO 処理です。これによってスケーラブブルなサーバーの構築が可能になるため、Netty や Gretty のようなフレームワークで重宝します。

リスト 1 の興味深いところは、何よりもまず、アプリケーションに必要なのはこのリストで目にする内容だけだということです。構成ファイルもなければ、(Groovy 1.8 を除けば) 直接ダウンロードまたはインストールしなければならないものもありません。このサンプル・アプリケーションは、groovy server.groovy と入力するだけで起動することができます。

単純なテキストによるレスポンスではなく、多少高度なレスポンスにしたい場合はどうでしょう?その場合、Gretty にはいくつもの方法があり、そのうちの 2 つはかなり簡単な方法です。その 1 つは、リスト 2 で行っているように、レスポンス・タイプを HTML に設定することです。

リスト 2. Gretty での HTML レスポンス
"/:name": {
 get {
  response.html = "Hello ${request.parameters['name']}"
 } 
}

この場合、レスポンスのコンテンツ・タイプは text/html に設定されます。もう 1 つの方法として、Gretty では静的テンプレートと動的テンプレートを使用できるようになっています。例えば、単純な JSP/GSP 風の構造を使用してテンプレートを定義することができます (リスト 3 を参照)。

リスト 3. Gretty での HTML テンプレート
<html>
 <head>
  <title>Hello!</title>
 </head>
 <body>
  <p>${message}</p>
 </body>
</html>

これで、レスポンスの本体でこのテンプレートを参照することができます。

リスト 4. Gretty での Groovy++ テンプレート
"/:name" {
  get {
   response.html = template("index.gpptl", 
     [message: "Hello ${request.parameters['name']}"])
  }
}

Gretty と Grape による依存関係管理

Gretty による迅速な開発の素晴らしさには、その一部に Grape (「参考文献」を参照) が貢献しています。Gretty は Grape を使用してバイナリー依存関係、すなわち JAR ファイルを自動的にダウンロードします。すべてのファイルは、Maven スタイルの推移的依存関係によってロードされます。そのため、リスト 1 ではアノテーション @Grab('org.mbte.groovypp:gretty:0.4.279') を入力するだけで、Gretty の依存関係と合わせて、Gretty に関連付けられた JAR ファイルを取得することができました。アノテーション @GrabResolver(name='gretty', root='http://groovypp.artifactoryonline.com/groovypp/libs-releases-local') では、Grape が必要なファイルを見つけられる場所を示しています。

Gretty は Groovy 専用ではありません

Gretty は Groovy 言語でしか使用できないわけではありません。JVM 上で実行されるすべてのものと同じく、Java 言語、あるいは Scale でも Gretty アプリケーションを作成してみることができます。

Grape は単純そうに見えますが、だからと言って本番環境に適していないということはありません。実のところ、Grape による必要な依存関係の自動ダウンロード機能は、Maven の同様の機能と何の違いもありません。Mavenは必要な依存関係をビルド時にダウンロードしますが、Grape はアプリケーションを初めて実行するときに、そのアプリケーションの実行中に依存関係をダウンロードするというだけです。Grape が必要な依存関係をローカルで検出できる場合、ダウンロードは必要ありません。必要な JAR は自動的にアプリケーションのクラスパスに配置されます。そのため、パフォーマンスが犠牲になるのは、Grape で構成したアプリケーションを最初に実行するときだけです。もちろん、指定された依存関係の必要とするバージョンを変更した場合にも、パフォーマンスに多少の影響があります。


Gretty と Magnus を組み合わせる

これまでの説明で、Gretty の単純さは理解してもらえたと思います。この単純さは、開発時間の大幅な短縮をいとも簡単に実現するだけではありません。Gretty (あるいは同様のフレームワーク) は、Magnus のようなアプリケーション (データをリッスンする HTTP エンドポイント) にも申し分なく適しています。そこでこれから、Play や Grails といったかなり軽量なフレームワークを、Gretty で作成したさらに軽量なアプリケーションでまるごと置き換えるとどうなるのかを見てみましょう。

この Magnus の改造バージョンには、Morphia と MongoHQを使用します。記憶にあるかもしれませんが、この 2 つは Amazon Elastic Beanstalk を紹介する記事でも使用しました。Groovy の Grape ユーティリティーを新しい構成で使用するには、リスト 5 に記載するアノテーションをサーバーに追加する必要があります。

リスト 5. Morphia およびその依存関係の追加
@GrabResolver(name='morphia', root='http://morphia.googlecode.com/svn/mavenrepo/')
@Grab(group='com.google.code.morphia', artifactId='morphia', module="morphia", 
  version='0.99')

今回使用する Morphia のクラスは、これまでの Magnus 改造バージョンでも使用してきたAccountLocation です。つまり、この Gretty によるエンドポイントでは、指定されたアカウントの位置情報の更新のみを行います。Morphia のクライアントは Gretty によるエンドポイントに JSON 文書を送信することになるため、Jackson も使用します。Jackson は、Gretty 内部にすでに組み込まれている、優れた JSON 処理フレームワークです。Grape が推移的依存関係を処理してくれるので、受信される JSON 文書を構文解析して単純な Java Map に変換するために必要なすべてのものにアクセスすることができます。

リスト 6. Gretty での位置情報の更新
def server = new GrettyServer().localAddress(new InetSocketAddress("localhost", 8080)).
 "/location/:account" {
  put {
    def jacksonMapper = new ObjectMapper()
    def json = jacksonMapper.readValue(request.contentText, Map.class)
    def formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm")
    def dt = formatter.parse(json['timestamp'])
    def res = [:]
    try{
      new Location(request.parameters['account'], dt, json['latitude'].doubleValue() , 
          json['longitude'].doubleValue() ).save()
	  res['status'] = 'success'
    }catch(exp){
      res['status'] = "error ${exp.message}"
    }
    response.json = jacksonMapper.writeValueAsString(res)
  }
}
server.start ()

リスト 6 を見るとわかるように、受信される JSON 文書の Map (json という名前を付けてあります) が作成されます。それに応じて、リスト 7 に示された Location クラスによって、位置情報が MongoDB に挿入されるというわけです。

リスト 7. 位置情報文書の作成 — Gretty バージョン
import com.google.code.morphia.annotations.Entity

@Entity(value = "locations", noClassnameStored = true)
class Location extends AbstractModel {
 String accountId
 double latitude
 double longitude
 Date timestamp

 public Location(String accountId, Date timestamp, double lat, double lon) {
  this.accountId = accountId
  this.timestamp = timestamp
  this.latitude = lat
  this.longitude = lon
 }
}

その上、この Location にはリスト 8 に示す Groovy スーパークラスがあります。

リスト 8. Location の基底クラス
import com.google.code.morphia.Morphia
import com.google.code.morphia.annotations.Id
import com.mongodb.Mongo
import org.bson.types.ObjectId

abstract class AbstractModel {
  @Id
  private ObjectId id;

  def save() throws Exception {
    def mongo = new Mongo("fame.mongohq.com", 32422)
    def datastore = new Morphia().createDatastore(mongo, "xxxx", 
      "xxxx", "xxxx".toCharArray())
    datastore.save(this)
    return this.id
  }
}

読者の中には、リスト 7 のコードに見覚えがある方がいらっしゃるかもしれません。この今回の Gretty 実装で、「Elastic Beanstalk という伸縮自在な豆の木に登る」のリスト 3 に対して行った主な変更は、実際のファイル名を Location.java から Location.groovy にするといったことぐらいなので、サーバーを起動する前にファイルをコンパイルする必要がありません。また、基底クラスも追加しました。位置情報は、URI から取得した受信パラメーター account によってアカウントに結び付けられます。

成功を示すレスポンスは JSON で送信されます。エラーが発生した場合には、別のレスポンスが生成されることになります。


まとめ: Gretty はすぐに使用できます

Gretty は可能な限り軽量になっています。ORM フレームワークは組み込まれていません。単純なテンプレートを別とすれば、堅牢なビュー・フレーワークもありません。しかし、他のフレームワークを組み込むことは可能です。こうした点は、Gretty を日常的に使用するのは時期尚早だということを意味するのでしょうか?テスト・フレームワークがないということも同様のことを意味するのでしょうか?その答えは「ノー」です。第一に、Gretty は Netty の評判の高いコードから作成されているので、当初からある程度は保証されています。そして第二に、自動テストであるかどうかに関わらず、他のあらゆる Web エンドポイントと同じように、Gretty をテストすることができます。実際、Gretty のテスト方法を確かめるには、そのソース・コードを見てください。ソース・コードにはテストが溢れていることがわかるはずです。

すべてのスタックが必要ではないこともあるからこそ、Gretty は、最近のフルスタックの Web フレームワークとはまったく逆の立場をとっています。Gretty のようなフレームワークを使うと必要な作業の量が増えすぎると思ったら、十分なドキュメントがある数多くのフルスタックの Java Web フレームワークのいずれかを使用したほうが楽かもしれません。それと同じく、Web サービス・リクエストおよびレスポンスを処理するのにスタック全体が必要であるかどうか疑問に思ったら、Gretty だけで十分に必要を満たせるかもしれません。

参考文献

学ぶために

  • Groovy++ in action: Gretty/GridGain/REST/Websockets」(Alex Tkachman 著、DZone、2011年5月): これまで Gretty を話題にした出版物は、ごく少ししかありません。この紹介記事に、記事の著者が Groovy++ で実装したいくつかのサンプル・アプリケーションが記載されています。
  • 連載「Java 開発 2.0」: この dW の連載では Java 開発の様相を塗り替える技術を詳しく探っています。今まで取り上げた話題には、Amazon Elastic Beanstalk (2011年2月)、Java 開発者のための JavaScript (2011年4月)、MongoDB (2010年9月)、NoSQL (2010年5月) などがあります。
  • Grape ユーザー・ガイド: Grape に興味がありますか?この Codehaus によるユーザー・ガイドでその概要を理解してください。
  • Netty のホーム・ページ: この Java NIO クライアント・サーバー・ソケット・フレームワークについて学んでください。
  • Getting started with new I/O (NIO)」(Greg Travis 著、developerWorks、2003年7月): この実践的チュートリアルでは、NIO ライブラリーのバッファーおよびチャネル、非同期 I/O、ダイレクト・バッファーなどを説明しています。
  • ナレッジ・パス「Cloud computing fundamentals」(2011年3月): クラウド・コンピューティングの概念、および IaaS、PaaS、SaaS という 3 つのサービス・モデルについて解説しています。
  • 連載「多忙な Java 開発者のための Scala ガイド」(Ted Neward 著、2008から2009年): Ted Neward が Scala プログラミング言語について掘り下げるこの連載では、単刀直入にこの言語機能の実際を検討しています。
  • JJava Technology bookstore で、この記事で取り上げた技術やその他の技術に関する本を探してください。
  • developerWorks Java technology ゾーン: Java プログラミングのあらゆる側面を網羅した記事が豊富に用意されています。

製品や技術を入手するために

議論するために

  • developerWorks コミュニティーに参加してください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者が主導するブログ、フォーラム、グループ、ウィキを調べることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology, Cloud computing, Web development, Open source
ArticleID=756664
ArticleTitle=Java 開発 2.0: Gretty を使った超軽量の Java Web サービス
publish-date=09162011