Grails をマスターする: 初めての Grails アプリケーションのビルド

この小さな Web フレームワーク・パッケージに詰め込まれた大いなる力を体験する

最新の Web 開発フレームワークを採用するために、Java™ プログラマーが好みの言語や既存の開発インフラストラクチャーを放棄する必要はありません。毎月 1 回お届けする新連載、「Grails をマスターする」の第 1 回目では、Java のエキスパートである Scott Davis が Grails を紹介し、初めての Grails アプリケーションをビルドする方法を手ほどきします。

Scott Davis , Editor in Chief, AboutGroovy.com

Scott DavisScott Davis は国際的に知られた著者、講演者、そしてソフトウェア開発者です。彼の著書には、『Groovy Recipes: Greasing the Wheels of Java』、『GIS for Web Developers: Adding Where to Your Application』、『The Google Maps API』、『JBoss At Work』などがあります。



2008年 1月 15日

Grails を紹介する手段として、別のオープンソースの Web 開発フレームワーク、Ruby on Rails を引き合いに出させてください。Rails がリリースされたとき、それは開発者の心を奪いました。Rails の scaffold 機能は、それまで新しいプロジェクトを立ち上げるのにかかっていた時間をほんのわずかな時間に短縮させてくれるからです。Rails の根底にある「Convention over Configuration (設定より規約)」という思想は、アプリケーションの自動構成が、厄介でエラーの根源となりがちな XML 構成ファイルに基づいて行われるのではなく、一般的な命名スキームに基づいて自動的に行われることを意味します。ソース・コードを散在させなくても、Ruby のメタプログラミング機能によってオブジェクトは実行時に必要なメソッドとフィールドをまるで魔法のように自動的に継承することができます。

Rails は当時 (今でも変わらず)、それに値する賞賛と崇拝を集めましたが、その一方、Java 開発者には難しい選択を迫ります。つまり、約束された新しいプラットフォームのために、使い慣れた Java プラットフォームを使うのを止めるかどうか、そして既存の Java コードや既存の実動サーバー、それに経験豊かな Java 開発者からなるスタッフをどうするか、という選択です。

この連載について

Grails は、Spring や Hibernate などのよく知られた Java 技術に「Convention over Configuration」といった現代のプラクティスを盛り込んだ最新の Web 開発フレームワークです。Groovy で作成された Grails は既存の Java コードをシームレスに統合するだけでなく、スクリプト言語ならではの柔軟性と動的機能を与えてくれます。Grails を学んだら、Web 開発に対する今までの見方がまったく違ってくるはずです。

Grails に目を向けてみると、Grails は実証された Java 技術にしっかり根差している一方で、Rails の開発経験を提供してくれます。とは言え、Grails は単に Rails を「真似て」 Java プラットフォームへ移植したというわけではありません。Grails は Rails での教訓を生かし、それを最新の Java 開発のきめ細かさと融合させています。つまり、形を変えたものではなく、発想を糧にしていると考えてください。

連載「Grails をマスターする」を開始するにあたって、この第 1 回目の記事では Grails フレームワークを紹介し、そのインストール方法を説明した上で、初めての Grails アプリケーションをビルドする手順を案内します。今回ビルドするこの旅行プラン作成用のアプリケーションは、連載の今後の記事でも引き続き取り組んでいくことになります。

Groovy の威力

Rails が Ruby プログラミング言語と深く結び付いているのと同じく、Grails も Groovy (「参考文献」を参照) の力がなければ存在していません。Groovy は JVM で実行される動的言語で、Java 言語とシームレスに統合されます。developerWorks に長期にわたって掲載された連載「実用的な Groovy」を読んだことがあれば、この言語の威力はもうご存知でしょう。この連載を読んだことがなくてもご心配なく。Grails について学ぶうちに、Groovy についても多くのことがわかるはずです。Groovy は明らかに Java 開発者を対象に設計されているので、理解しにくいわけがありません。

例えば、Groovy を使用すると、作成する Java コードの量を通常と比べて大幅に減らすことができます。フィールドのゲッターやセッターを作成する必要はありません。なぜなら Groovy が自動的に提供してくれるからです。さらに、項目のリストをループするための Iterator i = list.iterator() も不要です。同じことを、list.each でより簡潔かつよりわかりやすい表現を使って実行できます。簡単に言えば Groovy とは、21 世紀に Java 言語が作成されていたら Groovy のようになっていたであろう、そういった言語なのです。

Groovy を利用するためにアプリケーション全体を一から作り直さなければならなかったとしたら、Java 開発者にはほとんど見向きもされなかったでしょう。嬉しいことに、Groovy は Java 開発者の既存のコードベースとシームレスに統合されます。Groovy は Java 言語になり変わるものではなく、Java 言語を拡張するものです。Groovy コードは結局のところ Java コードなので、Groovy は簡単に習得することができます。この 2 つの言語は互換性が高く、例えば Person.java を Person.groovy という名前に変更するなど作業中の .java ファイルを .groovy に名前変更しても、(Groovy が提供するシンタックス・シュガーはまったく利用しないファイルにせよ) 完全に有効な (そして実行可能な) Groovy ファイルとして使えるほどです 。

このような Groovy と Java 言語との緊密な互換性は、ベースに使われている主要技術に関しては Grails がはじめからやり直す必要がないことを意味します。それどころか、Grails は使い慣れた Java ライブラリーを Groovy 的な観点で見させてくれます。JUnit の TestCase は Groovy にラップされ、GroovyTestCase として表されます。また、Grails は Ant の純粋な Groovy 実装である GANT によって新しく改良した Ant ビルドを提供します。さらに Grails は Hibernate をシン Groovy ファサードにラップし、これを GORM (Grails Object/Relational Mapper) と呼んでいます。今挙げた 3 つの例は、Grails が最新の Web 開発プラクティスを利用するかたわらで、既存の Java エクスペリエンスのすべてをどのように活用できるのかを示す、ほんの一例でしかありません。

Grails のありがたさは、実際に経験してみないと十分に理解することはできません。そこで、早速 Grails をインストールして、Grails を利用した初めての Web アプリケーションの作成に取り掛かることにしましょう。


Grails のインストール方法

Grails アプリケーションを実行するために必要なものは、すべて 1 つの ZIP ファイルに含まれています。すべての依存ライブラリー (Groovy、Spring、Hibernate 他、多数) もすでに配置されていて、すぐに使用できる状態になっています。以下の手順に従って、Grails をインストールしてください。

  1. Grails のサイト (「参考文献」を参照) から grails.zip をダウンロードし、解凍します。
  2. GRAILS_HOME 環境変数を作成します。
  3. PATH に $GRAILS_HOME/bin を追加します。

これだけの作業ですが、JDK がインストールされている必要はあります (Grails は優れていますが、そこまで優れているわけではありません)。Grails 1.0 はJava 1.4、1.5、1.6 上で実行します。インストールされている Java バージョンがわからなければ、コマンド・プロンプトに java -version と入力することで調べることができます。必要な場合には、Grails 対応バージョンの JDK (「参考文献」を参照) をダウンロードしてインストールしてください。

インストール手順を完了したら、grails -version と入力してインストールの結果をチェックしてください。以下の親しみのある表示がされれば、すべては正しく構成されています。

Welcome to Grails 1.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /opt/grails

付属の Web サーバーとデータベース

無料サンプルの利用

この記事のアプリケーションには、Grails が無料で提供している Web サーバーとデータベースを使用します。独自のサーバーに対して Grails を実行する方法については、今後の記事で手順を追って説明する予定です。それまでの間は、遠慮せずに grails.org サイトを調べ、優れたオンライン資料 (「参考文献」を参照) を閲覧してください。

興味深いことに、Grails アプリケーションを実行するために別個の Web サーバーをインストールする必要はありません。Grails には独自の組み込み Jetty サーブレット・コンテナーが付属しているため、grails run-app と入力すれば、いつものデプロイメント手順を踏まなくても Jetty コンテナー (「参考文献」を参照) でアプリケーションが起動します。また、既存の実動サーバーでも問題なく Grails アプリケーションを実行することができます。その場合には grails war と入力すると、Tomcat、JBoss、Geronimo、WebSphere®、そして他のあらゆる Java EE 2.4 準拠のサーブレット・コンテナーにデプロイすることのできる標準ファイルが作成されます。

データベースにしても、別途インストールする必要はありません。Grails にはピュア Java データベース、HSQLDB (「参考文献」を参照) が付属しているからです。そのまま使用できるデータベースが用意されているということは生産性が一気に向上するということですが、Hibernate と GORM のおかげで MySQL、PostgreSQL、Oracle Database、DB2 などといった別のデータベースも簡単に使用することができます。JDBC ドライバーの JAR と通常の接続設定が用意されていれば、DataSource.groovy に 1 箇所変更を加えるだけですぐに独自のデータベースとの通信が可能になります。


初めての Grails アプリケーションの作成

私は旅行することが多く、その回数は最低でも年に 40 回を数えるほどです。そのなかで気付いたのは、カレンダーはいつその現地に着いていなければならないかを教えてくれるという点では大いに役立ちますが、その場所がどこにあるのかを示すには役不足だということです。オンライン・マップはこれとは逆で、場所を示すには優れていても、日程を示すにはあまり役に立たないという問題があります。そこでこの連載では、今回から以降の数回の記事で、旅行を計画する際に日程と場所の両方を知らせる上で役立つカスタム Grails アプリケーションを組み立てることにします。

ネタバレ注意

この連載の今後の記事では Grails を Google Calendar および Google Maps と連動させる方法について説明することがわかってしまいましたか?

まずは空のディレクトリーで、grails create-app trip-planner と入力してください。一連の動作が終わると、trip-planner というディレクトリーが出来上がっているはずです。Maven や Rails、そして AppFuse と同様に、Grails は自動的に標準ディレクトリー構造を組み立てます。この制約がどうしても窮屈に感じられ、独自のカスタム・ディレクトリー・ツリーをきめ細かく設計できるフレームワークでなければ扱えないというのであれば、Grails での作業はあまり楽しめないかもしれません。「Convention over Configuration」の「Convention」の部分は、どんな Grails アプリケーションでも何がどこに格納されているのかをすぐにわかるようにするためのものだからです。

次は trip-planner ディレクトリーに移動して、grails create-domain-class Trip と入力します。万事順調に行くと、grails-app/domain/Trip.groovy と grails-app/test/integration/TripTests.groovy という 2 つの新しいファイルが作成されるはずです。テストについては今後の記事で説明するとして、今回はドメイン・クラスに焦点を絞ります。このクラスは、最初はリスト 1 のようになっています。

リスト 1. Grailsによって生成されたドメイン・クラス
class Trip{

}

ご覧のように、このクラスはほとんど見応えのないものです。そこで、次のようにフィールドを Trip に追加します (リスト 2 を参照)。

リスト 2. フィールドを追加した Trip クラス
class Trip { 
  String name
  String city
  Date startDate
  Date endDate
  String purpose
  String notes
}

前述したとおり、ゲッターとセッターを作成することについては心配する必要ありません。Groovy が両方とも動的に生成してくれます。Trip クラスには新しくて便利な動的メソッドも数多く提供されますが、これらのメソッドには一目でその内容がわかる名前が付けられています。

  • Trip.save() は、HSQLDB データベースの Trip テーブルにデータを保存します。
  • Trip.delete() は、Trip テーブルからデータを削除します。
  • Trip.list() は、Trip のリストを返します。
  • Trip.get() は、Trip を 1 つ返します。

上記のメソッドの他にも、必要なときに使えるようにメソッドが用意されています。注目すべき点として、Trip は親クラスを拡張したり、魔法のようなインターフェースを実装したりすることはありません。Groovy のメタプログラミング機能のおかげで、これらのメソッドは適切なクラスの適切な場所に自動的に実装されます (grails-app/domain ディレクトリーにあるクラスのみに、これらのパーシスタンス関連のメソッドを取得します)。

コントローラーとビューのビルド

ドメイン・クラスを作成しても、まだアプリケーション作成全体の半分でしかありません。すべてのモデルには、優れたコントローラーと、それに相当するビューがいくつか必要です (ここでは、読者がモデル・ビュー・コントローラーについて十分理解しているという前提で説明していますが、必要な場合は「参考文献」を参照してください)。grails generate-all Trip と入力すると、grails-app/controllers/TripController.groovy クラスと、それに対応する GSP (Groovy Server Page) のセットが grails-app/views/Trip 内に作成されます。コントローラー内のすべての list アクションには対応する list.gsp ファイルがあり、create アクションには create.gsp ファイルがあるはずです。このことから、「Convention over Configuration」の実際のメリットがわかります。つまり、これらの要素を対応させるための XML ファイルは必要ないということです。すべてのドメイン・クラスは、名前をベースにコントローラーと対になります。コントローラー内のすべてのアクションも名前をベースにビューと対になります。この名前をベースにした構成を望まないのであれば、回避することもできますが、規約にそのまま従っていれば大抵の場合、アプリケーションはすぐに機能します。

リスト 3 の grails-app/controller/TripController.groovy を見てください。

リスト 3. TripController
class TripController {
    ...
    def list = {
        if(!params.max) params.max = 10
        [ tripList: Trip.list( params ) ]
    }
    ...
}

Java 開発者がまず注目しそうな点は、これほど少ない行数のコードでかなりの実行内容が達成されているということです。list アクションを例に取ると、このメソッドで重要なのは最後の行で、Grails は tripList という名前の要素を 1 つ持つハッシュ・マップを返しています (Groovy メソッドの最終行は暗黙的な return 文です。もちろん、return と入力しても構いません)。tripList 要素は、Trip.list() メソッドによってデータベースから取得した Trip オブジェクトの ArrayList です。通常、このメソッドはテーブルのすべてのレコードを返しますが、そのすぐ上の行で、「URL に max パラメーターが渡されたら、それを使って返される Trip の数を制限すること。それ以外の場合は、Trip の数を 10 に制限すること」と指定しています。このアクションを呼び出す URL は http://localhost:8080/trip-planner/trip/list なので、例えば http://localhost:8080/trip-planner/trip/list?max=3 と設定すると、通常のように 10 件ではなく 3件の旅行プランが表示されます。表示する旅行プランがそれ以上にある場合には、Grails が前のページと次のページを表示するためのリンクを自動的に作成してくれます。

では、このハッシュ・マップはどこで使用されるのでしょうか。リスト 4 に記載する grails-app/views/list.gsp を見てください。

リスト 4. list.gsp
<g:each in="${tripList}" status="i" var="trip">
  <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
    <td>
      <g:link action="show" id="${trip.id}">${trip.id?.encodeAsHTML()}</g:link>
    </td>
  </tr>
</g:each>

list.gsp の大部分は従来の HTML ですが、いくつか GroovyTagLib があります。接頭辞 g: が付けられたものは、いずれも GroovyTag です。リスト 4 では、<g:each>tripList ArrayList に含まれるそれぞれの Trip をウォークスルーして整形された HTML の表を作成します。

コントローラーを理解する決め手は 3 つの「R」、つまり return (リターン)、redirect (リダイレクト)、そして render (レンダリング) です。一部のアクションは暗黙の return 文を利用して、同じ名前の GSP ページにデータを返します。また、リダイレクトを行うアクションもあります。その一例として、index は URL にアクションを指定しなかった場合に呼び出されるアクションです。

def index = { redirect(action:list,params:params) }

この場合、TripController によって list アクションにリダイレクトされ、params ハッシュ・マップにすべてのパラメーター (QueryString) を渡します。

最後に、save アクション (リスト 5 を参照) には対応する save.gsp ページがありません。レコードがエラーなしでデータベースに保存された場合、このアクションによって show アクション・ページにリダイレクトされます。エラーが発生した場合には create.gsp ページがレンダリングされるので、このページでエラーを確認して再試行することができます。

リスト 5. save アクション
def save = {
  def trip = new Trip(params)
  if(!trip.hasErrors() && trip.save()) {
    flash.message = "Trip ${trip.id} created"
    redirect(action:show,id:trip.id)
  }
  else {
    render(view:'create',model:[trip:trip])
  }
}

Grails が機能する仕組みについての説明はここまでとして、ここからは実際の動作を見てみます。


実際のアプリケーション

コマンド・ラインで grails run-app と入力してください。一連の Log4j メッセージがコンソールに立て続けに表示された後、以下のメッセージが表示されるはずです。

Server running. Browse to http://localhost:8080/trip-planner

ポート 8080 ですでにサーバーが実行中の場合には、コア・ダンプとともにエラーの内容が表示され、最後に以下のメッセージが表示されます。

Server failed to start: java.net.BindException: Address already in use

Jetty を実行するポートは、2 通りの方法で簡単に変更することができます。1 つは一時的に変更する方法で、grails -Dserver.port=9090 run-app と入力します。もう 1 つの方法では永続的な変更として、$GRAILS_HOME/scripts/Init.groovy のなかで serverPort から始まる行を探し、その値を変更します。

serverPort = System.getProperty('server.port') ? 
             System.getProperty('server.port').toInteger() : 9090

選択したポートで Grails が実行中になったら、Web ブラウザーに URL を入力します。すると図 1 のウェルカム画面が表示され、そこにすべてのコントローラーがリストされます。

図 1. Grails アプリケーションのウェルカム画面
Grails アプリケーションのウェルカム画面

TripController リンクをクリックすると、すぐに使える完全な CRUD (作成、読み取り、更新、削除) アプリケーションが表示されるので、いろいろといじってみてください。

図 2 は、新しい旅行プランを作成するためのページです。

図 2. Create Trip ページ
Create Trip ページ

旅行を編集する場合には、図 3 に示すページを使います。

図 3. Trip List ページ
Trip List ページ

アプリケーションを立ち上げるまでにかかった時間、そのために使用されたコードの行数がおわかりですか? それを調べる方法は以下のとおりです。

  1. Ctrl-C を押して Grails をシャットダウンします。
  2. grails stats と入力します。

画面上に以下の出力が表示されます。

  +----------------------+-------+-------+
  | Name                 | Files |  LOC  |
  +----------------------+-------+-------+
  | Controllers          |     1 |    66 | 
  | Domain Classes       |     1 |     8 | 
  | Integration Tests    |     1 |     4 | 
  +----------------------+-------+-------+
  | Totals               |     3 |    78 | 
  +----------------------+-------+-------+

見てのとおり、100 行に満たないコードでアプリケーションの機能すべてが実装されています。なかなかの成績ですが、記事を締めくくる前に、もう 1 つ芸当を披露させてください。

コントローラーとビューを生成するのは素晴らしい体験学習となり、ディスク上に物理的なファイルがあれば全体的なつながりがわかりやすくなります。しかし、ここでお願いがあります。TripController クラスの中身を削除して、以下の内容に置き換えてください。

  class TripController{
    def scaffold = Trip
  }

この 1 行のコードは Grails に以前のコントローラーで行っていたすべてのことを実行するように指定し、実行時に listsaveedit アクションのすべてを動的にメモリー内に生成させます。66 行ではなく 3 行のコードだけで、このすべての動作が実現されます。

もう一度 grails run-app と入力してください。当然すべてのデータは消えてしまいますが、心配には及びません。Ctrl-C を押して Grails をシャットダウンし、今度は grails prod run-app と入力します。これで実動モードでの実行となります。すなわちサーバーを再起動してもデータは保存されるということです。ウェルカム画面に戻って TripController をクリックし、いくつかレコードを追加で保存してください。アプリケーションの動作には何の違いも出てきません。このように、ブラウザーに表示されるすべての内容が 15 行のコードで実現されていることを知ると、Grails のすごさがわかるはずです。


まとめ

初めての Grails 体験を楽しんでいただけたでしょうか。小さなパッケージに詰め込まれた驚くべき処理能力については、まだその表面をかじっただけに過ぎません。フレームワークのインストールに必要なのは、ファイルを解凍する作業ぐらいです。アプリケーションを一から作成するにしても、数少ないコマンドを入力するだけで済みます。今回の Grails の特徴をかいつまんだ説明が読者の興味をそそることになり、Grails をもっとよく知りたいという気になってくれたことを願います。その興味こそが、このサンプル・アプリケーションを拡張して、あらゆる類の新しく興味深い方向へと導く土台となります。

GORM についての詳細を説明する次回の記事では、データを MySQL データベースに保存し、データ検証を導入し、そして 1 対多の関係を設定します。多数のコード行を追加することなく、trip-planner アプリケーションの機能を格段に充実させる予定です。

それまでは、Groovy と Grails をいろいろと試してみてください。そうするうちに、Web 開発の見方が今までと変わってくるに違いありません。

参考文献

学ぶために

  • Grails: Grails の Web サイトにアクセスしてください。
  • 実用的な Groovy」: developerWorks のこの連載記事では、実用的な Groovy の使用方法を探り、それぞれの方法をいつ、どんな場合に適用するかを伝授しています。
  • Groovy: Groovy の Web サイトで、このプロジェクトの詳細を学んでください。
  • AboutGroovy.com: Groovy に関する最新のニュースと記事へのリンクが記載されています。
  • What's the secret sauce in Ruby on Rails?」(Bruce Tate 著、developerWorks、2006年5月): Bruce Tate による developerWorks の連載「境界を超える」のこの記事では、Rails が何故それほど大きな話題を呼んだのか、その理由を説明しています。
  • HSQLDB および Jetty: Grails に付属している純粋な Java データベースおよびサーブレット・コンテナーについて調べてください。
  • モデル・ビュー・コントローラー: Grails はこの人気の高いアーキテクチャー・パターンに従っています。
  • テクノロジーのブックストアで、この記事で取り上げた技術やその他の技術に関する本を探してください。
  • developerWorks Java technology ゾーン: Java プログラミングのあらゆる側面を網羅した記事が豊富に用意されています。

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

  • Grails: Grails の最新リリースをダウンロードしてください。
  • Java SE: Grails 対応の JDK をダウンロードしてください。
  • IBM developer kits for the Java platform: Grails を IBM Developer Kit と併せて使用する場合は、まずこの FAQ でヒントを読んでください。

議論するために

コメント

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, Web development, Open source
ArticleID=288780
ArticleTitle=Grails をマスターする: 初めての Grails アプリケーションのビルド
publish-date=01152008