Grails をマスターする: Grails のイベント・モデル

アプリケーションのライフサイクル全体で振る舞いをカスタマイズする

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年 8月 12日

Web サイトを構築するということは、イベント・ドリブンの応答型アプリケーションの開発について学ぶことでもあります。アプリケーションはアイドル状態となって、ユーザーからリクエストが送信されてくるのを待ちわびます。リクエストが送信されてくるとレスポンスを返し、再び次の呼び出しまでスリープ状態に入ります。このような従来からの HTTP リクエスト/レスポンス型の Web ライフサイクルの他に、Grails はカスタムのタッチ・ポイントも提供しています。これらのタッチ・ポイントでイベント・モデルを操作することによって、Grails では独自の振る舞いを実現することが可能となっています。

この連載について

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

この記事を読むと、ビルド・プロセス中には無数のイベントがスローされることがわかります。この記事ではまずアプリケーションの起動とシャットダウンをカスタマイズし、最後に Grails ドメイン・クラスのライフサイクル・イベントについて詳しく検討します。

ビルド・イベント

Grails 開発者として最初に行うステップは、grails create-app と入力することです。そして最後に、grails run-app または grails war のいずれかを入力することになります。これらのコマンド、そして途中で入力するすべてのコマンドにはイベントがあり、そのイベントがプロセスの重要なポイントでスローされます。

$GRAILS_HOME/scripts ディレクトリーを見てください。このディレクトリーに置かれたファイルは、入力するコマンドにそれぞれ対応する Gant スクリプトです。例えば grails clean と入力すると、Clean.groovy が呼び出されます。

Gant の粋な計らい

皆さんが Gant スクリプトを初めて目にしたのは、この連載の最初の記事です。Gant は Apache Ant の薄い Groovy ファサードであることを思い出してください。Gant は Ant タスクを再実装するのではなく、まさに基礎となる Ant コードを呼び出すため、最大限の互換性が確実になります。つまり、Ant で実行可能なことは、同じく Gant でも実行できるということです。Gant スクリプトは XML ファイルではなく、Groovy スクリプトだという点が違うだけに過ぎません (Gant についての詳細は、「参考文献」を参照してください)。

Clean.groovy をテキスト・エディターで開いたときに、最初に目にするターゲットは、default ターゲットです (リスト 1 を参照)。

リスト 1. Clean.groovy の default
target ('default': "Cleans a Grails project") {
   clean()
   cleanTestReports()
}

上記の内容は見てのとおり単純で、clean ターゲットを実行した後に、cleanTestReports ターゲットを実行するというだけです。呼び出しスタックに従って、次はリスト 2 に記載する clean ターゲットを見てください。

リスト 2. Clean.groovy の clean ターゲット
target ( clean: "Implementation of clean") {
    event("CleanStart", [])
    depends(cleanCompiledSources, cleanGrailsApp, cleanWarFile)
    event("CleanEnd", [])
}

clean コマンドの振る舞いをカスタマイズするには、ここに独自のコードを追加することもできますが、この方法で問題となるのは、Grails をアップグレードするたびにカスタマイズをマイグレーションしなければならなくなることです。さらに、コンピューターの間を移動させるとビルドが壊れやすくなってしまうという問題もあります (Grails のインストール・ファイルがバージョン管理にチェックインされることはめったにありません。チェックインされるのはアプリケーション・コードだけです)。「でも私のマシンでは動作するのに」というあの恐ろしい事態を避けるため、私はこのような類のカスタマイズはプロジェクト内だけで行うようにしています。そうすれば、ソース管理からチェックアウトしたばかりのコードには常に正常なビルドに必要なカスタマイズがすべて含まれることになるからです。また、CruiseControl などの継続的インテグレーション・サーバーを使用している場合には、一貫性が維持されることにもなります。

clean ターゲットの実行中には、いくつかのイベントがスローされることに注目してください。プロセスの開始時には CleanStart が発生し、その後で CleanEnd が発生します。プロジェクトでこれらのイベントを利用すれば、カスタム・コードをプロジェクト・コードと調和させて、Grails インストール・ファイルには手をつけずに済みます。そのために必要なのは、リスナーを作成することだけです。

プロジェクトの scripts ディレクトリー内に Events.groovy という名前のファイルを作成し、リスト 3 に記載するコードを追加してください。

リスト 3. Events.groovy に追加するイベント・リスナー
eventCleanStart = {
  println "### About to clean"
}

eventCleanEnd = {
  println "### Cleaning complete"
}

grails clean と入力すると、リスト 4 のような出力が表示されます。

リスト 4. 新しいコメントを示すコンソール出力
$ grails clean

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

Base Directory: /src/trip-planner2
Note: No plugin scripts found
Running script /opt/grails/scripts/Clean.groovy
Environment set to development
Found application events script
### About to clean
  [delete] Deleting: /Users/sdavis/.grails/1.0.3/projects/trip-planner2/resources/web.xml
  [delete] Deleting directory /Users/sdavis/.grails/1.0.3/projects/trip-planner2/classes
  [delete] Deleting directory /Users/sdavis/.grails/1.0.3/projects/trip-planner2/resources
### Cleaning complete

もちろん、単純なメッセージをコンソールに書き込む代わりに実際の作業を行うのでも構いません。例えば、追加ディレクトリーのいくつかは削除できるはずです。また、新しい XML ファイルを既存の XML ファイルに上書きコピーすることで、XML ファイルを「リセット」するという手もあります。Groovy (あるいは Java プログラミング) で可能なことはすべて、ここでも可能です。

CreateFile イベント

ここで、ビルド・プロセス中に利用できる別のイベント例を紹介します。create- コマンド (create-controllercreate-domain-class など) のいずれかを入力すると、そのたびに CreatedFile イベントが起動されます。リスト 5 に記載する scripts/CreateDomainClass.groovy を見てください。

リスト 5. CreateDomainClass.groovy
Ant.property(environment:"env")
grailsHome = Ant.antProject.properties."env.GRAILS_HOME"

includeTargets << new File ( "${grailsHome}/scripts/Init.groovy" )  
includeTargets << new File( "${grailsHome}/scripts/CreateIntegrationTest.groovy")

target ('default': "Creates a new domain class") {
    depends(checkVersion)

   typeName = ""
   artifactName = "DomainClass"
   artifactPath = "grails-app/domain"
   createArtifact()
   createTestSuite() 
}

上記では CreatedFile イベントが呼び出されていることはわかりませんが、$GRAILS_HOME/scripts/Init.groovy 内の createArtifact ターゲットを調べれば明らかです ($GRAILS_HOME/scripts/CreateIntegrationTest.groovy に含まれる createTestSuite ターゲットによって、最終的に $GRAILS_HOME/scripts/Init.groovy 内の createArtifact ターゲットも呼び出されます)。createArtifact ターゲットの最後から 2 行目に、event("CreatedFile", [artifactFile]) の呼び出しが確認できるはずです。

このイベントは、イベント・ハンドラーに値を渡すという点で CleanStart イベントとは明らかに異なります。この場合に渡される値は、新規に作成されたファイルへの完全パスです (この後説明するように、2 番目の引数はリストで、このリストではカンマで区切った値をいくらでも渡すことができます)。したがって、イベント・ハンドラーは渡された値を受け取れるようにセットアップしなければなりません。

例えば、新しく作成されたファイルがソース管理に自動的に追加されるようにしたいとします。Groovy では、コマンドラインに通常入力するものであれば何でも引用符で囲んで execute()String で呼び出すことができるため、scripts/Events.groovy にはリスト 6 のようなイベント・ハンドラーを追加します。

リスト 6. 成果物の Subversion への自動追加
eventCreatedFile = {fileName ->
  "svn add ${fileName}".execute()
  println "### ${fileName} was just added to Subversion."  
}

grails create-domain-class Hotel と入力して出力を確認してください。Subversion を使用していなければ、このコマンドはただ単に失敗するだけです。Subversion を使用している場合には、svn status と入力すると、ファイル (ドメイン・クラスとそれに対応する統合テスト) が追加されたことが確認できます。

呼び出されるビルド・イベントを検出する

どのイベントがどのスクリプトによってスローされるのかを調べる最も手軽な方法は、event() 呼び出しに対応する Grails スクリプトを探すことです。UNIX® システムでは、Groovy スクリプト内で event ストリングを grep することができます (リスト 7 を参照)。

リスト 7. Grails スクリプト内でのイベント呼び出しの Grep
$ grep "event(" *.groovy
Bootstrap.groovy:       event("AppLoadStart", ["Loading Grails Application"])
Bootstrap.groovy:       event("AppLoadEnd", ["Loading Grails Application"])
Bootstrap.groovy:       event("ConfigureAppStart", [grailsApp, appCtx])
Bootstrap.groovy:       event("ConfigureAppEnd", [grailsApp, appCtx])
BugReport.groovy:    event("StatusFinal", ["Created bug-report ZIP at ${zipName}"])

何が呼び出されているのかがわかれば、それに対応するリスナーを scripts/Events.groovy 内に作成し、ビルド環境をさらに詳細にカスタマイズすることができます。


カスタム・イベントをスローする方法

イベントがどのような動作をするのかが理解できれば、後は自由に独自のイベントを追加して構いません。しかしカスタム・イベントをスローするための作業を行うにあたって、$GRAILS_HOME/scripts に置かれたスクリプトをどうしてもカスタマイズしなければならないというのであれば、スクリプトをプロジェクト内の scripts ディレクトリーにコピーすることを強くお勧めします。これはつまり、カスタム・スクリプトを他のものと同様にソース管理にチェックインすることを意味します。そうすれば、Grails がスクリプトのどのバージョン ($GRAILS_HOME 内にあるスクリプト、またはローカル scripts ディレクトリー内にあるスクリプト) を実行するかを確認してきます。

$GRAILS_HOME/scripts/Clean.groovy をローカル scripts ディレクトリーにコピーして、CleanEnd イベントの後に以下のイベントを追加します。

event("TestEvent", [new Date(), "Some Custom Value"])

最初の引数はイベントの名前です。2 番目の引数はどの項目を返すかを指定するリストです。この例では現行の日付スタンプとカスタム・メッセージを返すように指定しています。

scripts/Events.groovy に、リスト 8 のクロージャーを追加してください。

リスト 8. カスタム・イベントを受け取る処理
eventTestEvent = {timestamp, msg ->
  println "### ${msg} occurred at ${timestamp}"  
}

grails clean と入力してローカル・バージョンのスクリプトを選択すると、以下の内容が出力されます。

### Some Custom Value occurred at Wed Jul 09 08:27:04 MDT 2008

.


ブートストラップ

ビルド・イベントに加え、アプリケーション・イベントを利用することもできます。grails-app/conf/BootStrap.groovy は、Grails の起動時と停止時に常に実行されるファイルです。この BootStrap.groovy をテキスト・エディターで開いてください。起動時には init クロージャーが呼び出され、アプリケーションがシャットダウンすると destroy クロージャーが呼び出されるということがわかります。

まずは、この 2 つのクロージャーに単純なテキストを追加します (リスト 9 を参照)。

リスト 9. BootStrap.groovyでの最初の作業
def init = {
  println "### Starting up"
}

def destroy = {
  println "### Shutting down"
}

grails run-app と入力してアプリケーションを起動してください。プロセスの終わり近くになると、### Starting Up というメッセージが表示されます。

ここで CTRL+C を押すと、### Shutting Down メッセージが表示されると期待するかもしれませんが、このメッセージは表示されません。なぜなら CTRL+C は、destroy クロージャーを呼び出さずに唐突にサーバーを終了させるからです。それ以外の方法でアプリケーション・サーバーをシャットダウンすれば、このクロージャーが確実に呼び出されることになります。しかし、destroy イベントを確認するために grails war と入力して Tomcat または IBM®WebSphere® に WAR をロードする必要はありません。

init イベントと destroy イベントの両方が発生することを確認するには、grails interactive と入力して Grails を対話モードで起動します。これで run-app と入力すればアプリケーションが起動され、exit と入力すればサーバーがシャットダウンします。対話モードで実行すると、JVM が実行中のままになり、ウォームアップされることになるため、開発プロセスが大幅にスピードアップします。さらに、CTRL+C でアプリケーションを強制的にシャットダウンするのではなく、グレースフル・シャットダウンを行えるという特典もあります。

ブートストラップ中にレコードをデータベースに追加する

BootStrap.groovy スクリプトを単純なコンソール出力の他に利用する方法として一般的なのは、これらのフックを利用してレコードをデータベースに挿入することです。

まず、先ほど作成した Hotel クラスに name フィールドを追加してください (リスト 10 を参照)。

リスト 10. Hotel クラスへのフィールドの追加
class Hotel{
  String name
}

次に、HotelController の scaffold を作成します (リスト 11 を参照)。

リスト 11. ホテル・コントローラーの作成
class HotelController {
  def scaffold = Hotel
}

: 「Grails とレガシー・データベース」の説明に従って grails-app/conf/DataSource.groovy 内の dbCreate 変数を無効にしてある場合、この例のために変数をもう一度有効にして値を update に設定してください。もちろん、Hotel テーブルに Hotel クラスに対する変更を手作業で反映させるという選択肢もあります。

BootStrap.groovy にリスト 12 のコードを追加します。

リスト 12. BootStrap.groovy 内でのレコードの保存と削除
def init = { servletContext ->  
  new Hotel(name:"Marriott").save()
  new Hotel(name:"Sheraton").save()  
}

def destroy = {
  Hotel.findByName("Marriott").delete()
  Hotel.findByName("Sheraton").delete()  
}

この後に説明する例のために、MySQL コンソールを開いたままにしてデータベースを監視する必要があります。mysql --user=grails -p --database=trip と入力してログインした後 (パスワードは server です)、次のステップを実行してください。

  1. Grails を起動します (Grails がまだ実行中になっていない場合)。
  2. show tables; と入力して Hotel テーブルが作成されていることを確認します。
  3. desc hotel; と入力して列とデータ型を調べます。
  4. select * from hotel; と入力してレコードが挿入済みであることを確認します。
  5. delete from hotel; と入力してすべてのレコードを削除します。

BootStrap.groovy でのフェイルセーフなデータベースの挿入および削除

BootStrap.groovy でデータベースの挿入と削除を行うときには、もう少しフェイルセーフな方法が必要になります。レコードを挿入する前に、そのレコードの有無を確認していないと、データベース内のレコードが重複してしまう結果になりかねないからです。また、存在しないレコードを削除しようとすると、面倒な例外がコンソールにスローされることになります。フェイルセーフな挿入および削除を行う方法は、リスト 13 に示すとおりです。

リスト 13. フェイルセーフな挿入と削除
def init = { servletContext ->  
  def hotel = Hotel.findByName("Marriott")    
  if(!hotel){
    new Hotel(name:"Marriott").save()
  }
  
  hotel = Hotel.findByName("Sheraton")
  if(!hotel){
    new Hotel(name:"Sheraton").save()
  }
}

def destroy = {
  def hotel = Hotel.findByName("Marriott")
  if(hotel){
    Hotel.findByName("Marriott").delete()
  }
  
  hotel = Hotel.findByName("Sheraton")
  if(hotel){
    Hotel.findByName("Sheraton").delete()
  }
}

Hotel.findByName("Marriott") を呼び出すと、その Hotel がテーブル内に存在しなければ null オブジェクトが返されます。次の行にある if(!hotel) は、値が null ではない場合にだけ true に評価されます。これにより、新しい Hotel を保存できるのは、既存のものがない場合だけとなります。destroy クロージャーでも同じテストを実行して、存在しないレコードを削除しようとすることがないようになっています。

BootStrap.groovy で環境固有のアクションを実行する

特定のモードで実行しているときにだけ特定の動作が実行されるようにするには、GrailsUtil クラスが役に立ちます。grails.util.GrailsUtil はファイルの先頭にインポートします。静的 GrailsUtil.getEnvironment() メソッド (Groovy の簡潔明瞭なゲッター構文のおかげで、簡潔に GrailsUtil.environment と省略されています) を使用すれば、現在どのモードで実行しているのかを調べることができます。この知識と switch 文を組み合わせることで (リスト 14 を参照)、Grails の起動時に環境固有の振る舞いを実現することができます。

Groovy の強固な switch

Groovy の switch 文は Java の switch 文よりも柔軟な使い方ができることに注目してください。Java コードでは整数値しか切り替えることができませんが、Groovy では String 値でも切り替えられます。

リスト 14. BootStrap.groovy での環境固有のアクション
import grails.util.GrailsUtil

class BootStrap {

     def init = { servletContext ->
       switch(GrailsUtil.environment){
         case "development":
           println "#### Development Mode (Start Up)"
           break
         case "test":
           println "#### Test Mode (Start Up)"
           break
         case "production":
           println "#### Production Mode (Start Up)"
           break
       }
     }

     def destroy = {
       switch(GrailsUtil.environment){
         case "development":
           println "#### Development Mode (Shut Down)"
           break
         case "test":
           println "#### Test Mode (Shut Down)"
           break
         case "production":
           println "#### Production Mode (Shut Down)"
           break
       }
     }
}

上記から、テスト・モードの場合にだけレコードを挿入するには何が必要かわかったはずです。しかし、これで終わりにしないでください。私はよく、XML ファイルにテスト・データを外部化します。ここで学んだ内容を「Grails とレガシー・データベース」で説明した XML のバックアップ・スクリプトとリストア・スクリプトと組み合わせれば、強力なテスト・ベッドを実現できます。

BootStrap.groovy は受動構成ファイルではなく実行可能スクリプトなので、Groovy で可能なことは文字通り何でも実行することができます。例えば起動時に Web サービスを呼び出して、中央サーバーにインスタンスが稼働していることを宣言するというもの一案です。また、ローカル側にあるルックアップ・テーブルを共通ソースから同期させることもできます。可能性はまさに無限です。


マイクロ・レベルのイベント

マクロ・レベルのイベントをいくつか説明したところで、今度はマイクロ・レベルのイベントを取り上げます。

ドメイン・クラスのタイムスタンプを取得する

具体的な名前付きフィールドをいくつか設定すると、GORM は自動的にクラスのタイムスタンプを取ります (リスト 15 を参照)。

リスト 15. タイムスタンプ・フィールド
class Hotel{
  String name
  Date dateCreated 
  Date lastUpdated 
}

名前からわかるように、dateCreated はデータがデータベースに初めて挿入されたときに入力されるフィールドで、lastUpdated はその後データベース・レコードが更新される度に入力されるフィールドです。

この 2 つのフィールドが裏で入力されていることを確認するには、もう 1 つの作業として Create ビューと Edit ビューでこれらのフィールドを無効にする必要があります。それには grails generate-views Hotel と入力して、create.gsp ファイルと edit.gsp ファイルでこれらのフィールドを削除するという方法がありますが、scaffold によって生成されたビューの場合には、もう少し動的な方法があります。「Groovy Server Pages によるビューの変更」では grails install-templates と入力して、scaffold によって生成されたビューを調整できるようにしてあるはずです。scripts/templates/scaffolding で create.gsp と edit.gsp を探して、2 つのタイムスタンプ・フィールドをテンプレート内の excludedProps リストに追加してください (リスト 16)。

リスト 16. デフォルト scaffold からのタイムスタンプ・フィールドの除外
excludedProps = ['dateCreated','lastUpdated',
                 'version',
                 'id',
                   Events.ONLOAD_EVENT,
                   Events.BEFORE_DELETE_EVENT,
                   Events.BEFORE_INSERT_EVENT,
                   Events.BEFORE_UPDATE_EVENT]

上記のコードによって、Create ビューと Edit ビューではフィールドが作成されない一方、List ビューと Show ビューにはフィールドがそのまま残されることになります。Hotel を 1 つか 2 つ作成して、フィールドが自動的に更新されることを確認してください。

アプリケーションでこれらのフィールド名をすでに使用している場合、リスト 17 の設定によって、この機能を簡単に無効にすることができます。

リスト 17. タイムスタンプの無効化
static mapping = { 
  autoTimestamp false 
}

Grails とレガシー・データベース」で説明したように、オプティミスティック・ロックのために使用する version フィールドの自動作成および更新についても、version false を指定することで無効にできます。

イベント・ハンドラーをドメイン・クラスに追加する

ドメイン・クラスのタイムスタンプを取得するだけでなく、beforeInsertbefortUpdatebeforeDelete、そして onLoad という 4 つのイベント・フックも利用することができます。

これらのクロージャーの内容はそれぞれの名前から明らかです。beforeInsert クロージャーは save() メソッドの前に呼び出されます。beforeUpdate クロージャーは update() メソッドの前に呼び出され、beforeDelete クロージャーは delete() メソッドの前に呼び出されます。そして最後の onLoad は、クラスがデータベースからロードされる際に呼び出されるクロージャーです。

例えば、皆さんの会社ではデータベース・レコードのタイムスタンプについて既存のポリシーがあり、タイムスタンプ・フィールドの名前は cr_time および up_time として標準化されているとします。この企業ポリシーに Grails を準拠させる方法としては、いくつかの選択肢があります。その 1 つは、「Grails とレガシー・データベース」で説明した静的マッピングの手法で、Grails でのデフォルト・フィールド名を会社でのデフォルト列名にマッピングするという方法です (リスト 18 を参照)。

リスト 18. タイムスタンプ・フィールドのマッピング
class Hotel{
  Date dateCreated
  Date lastUpdated
  
  static mapping = {
    columns {
      dateCreated column: "cr_time"
      lastUpdated column: "up_time"
    }
  }
}

別の選択肢としてはリスト 19 に示すように、ドメイン・クラスのフィールドに会社の列名と一致する名前を付け、これらのフィールドに値を入力する beforeInsert および beforeUpdate クロージャーを作成することです (新しいフィールドは必ず nullable に設定してください。そうでないと、save() メソッドが BootStrap.groovy 内で何の通知もなく失敗することになります)。

リスト 19. beforeInsert および beforeUpdate クロージャーの追加
class Hotel{
  static constraints = {
    name()
    crTime(nullable:true)
    upTime(nullable:true)
  }

  String name
  Date crTime
  Date upTime

  def beforeInsert = {
    crTime = new Date()
  }

  def beforeUpdate = {
    upTime = new Date()
  }  
}

アプリケーションの起動と停止を何度か繰り返して、新しいフィールドが期待通りに入力されることを確認してください。

これまで説明してきた他のすべてのイベントと同じく、これらのイベントによってどのようなアクションを行うかは、何の制約もなく自由に選べます。例えば「Grails サービスと Google Maps」では、空港をマップ上に表示できるように、空港の住所を緯度と経度による地点に変換するジオコーディング・サービスを作成しました。その記事のなかでは、AirportController 内の save および update クロージャーでこのサービスを呼び出させるようにしましたが、サービス呼び出しを Airport クラスの beforeInsertbeforeUpdate に移せば、気づかれないところで自動的にサービスが呼び出されることになっていたでしょう。

この振る舞いをすべてのクラスで共有できるようにするには、これらのフィールドとクロージャーを、src/templates に配置されているデフォルト DomainClassテンプレートに追加します。こうすることで、新しく作成されるドメイン・クラスのフィールドとイベント・クロージャーが、あらかじめ用意されることになります。


まとめ

Grails 全体でのイベントは、さらにきめ細かくアプリケーションの振る舞いをカスタマイズするのに役立ちます。scripts ディレクトリー内に Events.groovy ファイルを作成することで、標準 Grails スクリプトを変更しなくてもビルド・プロセスを拡張することができます。起動とシャットダウンのプロセスをカスタマイズするには、BootStrap.groovy ファイルに含まれる init および destroy クロージャーに独自のコードを追加します。さらに、beforeInsertbeforeUpdate などのクロージャーをドメイン・クラスに追加することによって、タイムスタンプの取得やジオコーディングを実行するといった振る舞いも追加することができます。

次回の記事では、Grails を使用して、データの REST (Representational State Transfer) をベースに Web サービスを作成するというアイデアを紹介します。次世代の RESTful な Web サービスをサポートするために必要な HTTP の GETPUTPOST、および DELETE アクションを、Grails では簡単にサポートできることを理解できるはずです。次回の記事まで、Grails を楽しみながらマスターしてください。

参考文献

学ぶために

  • 連載「Grails をマスターする」: この連載の他の記事を読んで、Grails とこのフレームワークを使って実現可能なすべての内容をよく理解してください。
  • Grails: Grails の Web サイトにアクセスしてください。
  • Grails Framework Reference Documentation: Grails のバイブルとなります。
  • Groovy Recipes』: Scott Davis の最新の著作で Groovy と Grails の詳細を学んでください。
  • 連載「実用的な Groovy」: developerWorks のこの連載記事では、実用的な Groovy の使用方法を探り、それぞれの方法をいつ、どんな場合に適用するかを解説しています。
  • Groovy: Groovy の Web サイトで、このプロジェクトの詳細を学んでください。
  • AboutGroovy.com: Groovy に関する最新のニュースと記事へのリンクが記載されています。
  • Build software with Gant」(Andrew Glover 著、developerWorks、2008年5月): このチュートリアルを読んで、Groovy と Apache Ant との組み合わせが柔軟性の高いビルドを容易にする仕組みを学んでください
  • technology bookstore: この記事で紹介した技術やその他の技術に関する本を参照してください。
  • developerWorks Java technology ゾーン: Java プログラミングのあらゆる側面を網羅した記事が豊富に用意されています。

議論するために

  • Grails: Grails の最新リリースをダウンロードしてください。

コメント

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=339724
ArticleTitle=Grails をマスターする: Grails のイベント・モデル
publish-date=08122008