vol.2

Magazine

Japan Grails/Groovy User Group個人サポータ制度のお知らせ
JGGUG では , 2011 年度より個人サポータ制度を始めました .
今まで JGGUG の経済的な基盤はすべて法人会員の年会費に依存していました。 しかし、個人会員も金銭面からサポートしたいという声があがり、JGGUG 運営基盤の裾野を拡げるためにも、個人サポータという形で個人会員からの寄付を受け入れることにした次第です。
個人サポータとなっていただいた方には、一年間にわたって JGGUG が発行する G* Magazine（年数回刊。
基本的に電子版として配布予定）に個人サポータとしてお名前を掲載します（掲載を希望しない旨お申し
出いただけば掲載しません）。
個人サポータとなるには、まず supporters@jggug.org にメイルで• お名前• 予定金額• G* Magazine へのご芳名掲載の可否をお知らせください。追って、運営委員より振込先の情報などを返信します。
皆様のサポートをお待ちしております。
日本 Grails/Groovy ユーザーグループ
代表

山田 正樹

Contents
Grails 1.4.0 M1 リリース

緊急企画

検証 ! Grails 1.4.0 の世界……………………… 4
Series 02

Griffon 不定期便

〜第 3 回 バインディング編〜… ……………………… 9Series 03

CodeNarc を利用して GROOVY のコード品質を上げる〜第 2 回 開発ツールと連携〜… ……………………… 13
Series 06

もし新人女子 Java プログラマが『Groovy イン・アクション』を読んだら〜第１章 もかは『Groovy イン・アクション』と出会った〜… … 16
Series 05

Grails Plugin 探訪〜第 3 回 MongoDB GORM プラグイン〜… ………… 21
Information

リリース情報……………………………………… 25
JGGUG ４コマ漫画「ぐるーびーたん」第 2 話… …… 26

G*Magazine vol.2

緊急企

画 Grails 1.4.0 M1 リリース

検証 ! Grails 1.4.0 の世界山本剛（株式会社ニューキャスト）

出版・印刷関連のシステム設計開発等に従事するテクニカル DTP アーキテクト。
日本 Grails/Groovy ユーザーグループ名古屋支部長。2006 年より Grails のドキュメント翻訳、
その後、Grails 公式の Acegi プラグインを開発。書籍『Grails 徹底入門』( 翔泳社発行 ) の 9、10、11 章を執筆。

今回は、「Grails 1.4.0 M1 リリース」緊急企画として、楽しみに

これだけあると、今回の記事だけでは全ての情報を掲載できましてた方には申し訳ないですが、前回の続き「Grails をコントロー

せん。今回は、このマイルストーンで著者が気になった部分の一M1 の追加機能・変更点など一部を紹介します。

限り記事にしていきたいと思っています。では、早速見ていきまルせよ！ Part 2」をお休みして、先日リリースされた、Grails 1.4.0

Grails 1.4.x 系最初のリリース！
去年に発表されたロードマップの情報から、様々な先行情報が見えてきた、Grails 次期バージョン 1.4 系の最初のマイルストー

部を紹介します。今後も、残りの情報・最新情報があればできるしょう。

またしても UI デザインの変更！
これで３回目となる、ベースデザインの変更です。最初の青っンがリリースされました。Grails 1.4.x 系では変更点が多く、内部

ぽいデザインから、次にリニューアルされた Spring カラーの UI、新内容を公式サイトのロードマップから内容を拝借しますと、

HTML5 化です。個人的な意見では、CSS の修正だけでもよかっ

的にはかなり深いところまで改善・向上されています。今回の更• Groovy 1.8, Spring 3.1 M1, Hibernate 3.6,Servlet 3.0, Tomcat 7への更新。

• エージェントベースリロード

そして時代に合わせてか今回は Spring カラーを採用しながらのたのでは？と思っていますが・・・。スクリーンショットを掲載
しておきます。

今回の変更では HTML5 を採用したデザイン内容になっていま• プラグイン使用統計トラッキング

す。中身は Modernizr（http://www.modernizr.com/）が使われて• HTML5 で強化したスカッフォルド UI

見えたりします。iPhone の Safari 用の調整もしてあるので、iOS• AST 変換を使用した GORM API と Java 統合• 静的リソースハンドリングの向上• Mixin ベースの Unit テストサポート• バイナリープラグイン• Prototype から jQuery への変更

• 基本データベースの H2 への変更
• GORM の機能強化

います。大幅に変わりすぎて、いや、違和感がありすぎて別物にでも上手くはまっています。apple-touch-icon も定義してあるので、iOS でのアイコンもバッチリです。

個人的な意見は多々あると思いますが、別テンプレートを作ってしまおうかと。ってのはウソで、がんばって慣れようかと思います。

[iOS アイコン ][ 新デザイン ]4

緊急企画

検証 ! Grails 1.4.0 の世界[iOS 画面 ]G*Magazine vol.2

H2 になっただけでは無くて！データベース
コンソールもつかえる！
1.4.0 からデータベースが、HSQLDB に代わり H2 になりました。

そして、ただ H2 になっただけでは無く、H2 付属のデータベース

ます。本運用で使用する際はセキュリティを考慮して、必ず、
spring-security-core プラグインなどでアクセス制御しましょう。
environments {production {管理コンソールも使用できるようになりました。使用方法は単grails.serverURL = "http://www.changeme.com"

純に、アプリケーションの URL に、/dbconsole と追加するだけ

grails.dbconsole.enabled = trueです。例えば、http://localhost:8080/t140m1/ であれば、http://

grails.dbconsole.urlRoot = '/admin/dbconsole'

localhost:8080/t140m1/dbconsole/ となります。管理コンソール}を参照すると、DB の指定、ドライバー、JDBC URL 等を設定する

development {ログイン画面が現れます。ここまで来たら、後は接続ボタンを押

grails.serverURL =すだけ！と行きたいところですが、状況によっては、JDBC URL"http://localhost:8080/${appName}"

がデフォルトの状態になっている場合があるので設定します。

}
test {JDBC URL・ユーザ名・パスワード等の設定を行って接続する

grails.serverURL =と、SQL の実行を行ったりとデータベースの操作ができる管理コ"http://localhost:8080/${appName}"

ンソールが現れます。これは便利！

デ ー タ ベ ー ス 管 理 コ ン ソ ー ル は、 基 本 的 に は 開 発}}(development) モードでしか動作しません。場合によっては、本
運用環境でも管理コンソールを使用したいケースもあります。そん な 時 は Config.groovy の 環 境 別 設 定 (environments ブ ロ ッ ク )の production 以下に、"grails.dbconsole.enabled = true" と、URLの指定 "grails.dbconsole.urlRoot = '/admin/dbconsole'" を指定し[DB 管理コンソールログイン画面 ][ コンソール画面 ]緊急企画

検証 ! Grails 1.4.0 の世界

5G*Magazine vol.2

Grails 1.4 からの Unit テスト
今回のリリースで、Unit テストが大幅改良されて、今まで可能では無かった部分まで、
Unitテストでテストを書くことができます。

例えば、インテグレーションテストが必要だったコントローラ

関連の、フィルタ−・URL マッピング・ファイルアップロード・
コンテントネゴシエーション・テンプレートビューレンダリング

や、ドメインクラスでは、クライテリアクエリーなども Unit テ
ストでサポートされています。

新 Unit テストの一部を試してみたので紹介します。詳しくは

1.4.x 系のドキュメントを参考にしてください。

■コントローラの Unit テスト% grails generate-all myapp.Book
生成された Unit テストのコード BookControllerTests.groovy は

次のようになります。( 一部抜粋 )生成されたコードの中に TODO: と書かれた部分があるので、その辺りにドメインクラスの内容に沿ったコードを追記します。
( ①の部分 )import org.junit.*
import grails.test.mixin.*@TestFor(BookController)@Mock(Book)

Grails 1.4.x 系の Unit テストでは、従来の GrailsUnitTestCase をclass BookControllerTests {す。代わりに、アノテーション grails.test.mixin.TestFor にテスト

void testIndex() {使用しません。下位互換用にクラスは存在していますが非推奨で@Test

するコントローラクラスを指定します。このアノテーションを指

controller.index()

定する事によって、grails.test.mixin.web.ControllerUnitTestMixin

assert "/book/list" == response.redirectedUrlと関連する API が自動で設定されます。

}..... 中略 .....

import grails.test.mixin.*
import org.junit.*@Test
void testSave() {controller.save()@TestFor(HomeController)class HomeControllerTests {assert model.bookInstance != null

void testSomething() {// ここにテストを書くよ。
}

assert view == '/book/create'}// TODO: Populate valid properties

さらには、今まで、在って当然と思っていた静的スカッフォル

controller.save()// ①ここの部分に追記

ドで生成されたコントローラの Unit テストが、grails generate-all
コマンドで同時に生成されるようになりました。

assert response.redirectedUrl == '/book/show/1'

生成されたコントローラの Unit テストは、完全な形ではなく、

assert controller.ﬂash.message != null

必要な ( 後で変更があるであろう ) ドメインクラスやパラメータ

assert Book.count() == 1の部分は TODO: と記載されており、その部分は実装に応じて自分で記述する必要があります。

例えば myapp.Book といったドメインクラスがあるとします。
package myappclass Book {String title
String author
String isbnLong pricestatic constraints = {title()
author()isbn minSize:9
price()}}
静的スカッフォルドを生成します。

6

緊急企画

検証 ! Grails 1.4.0 の世界｝}

サ ン プ ル コ ー ド 内 ① の 部 分 が 含 ま れ て い る テ ス ト は、

testSave() なので、フォームの内容を投げて保存するといった動作になります。ここの部分に必要なのは、フォームに入るべきパ
ラメータ、アクションでの params になります。なので次のコードように、サンプルコード内①以下に、params マップにフォー
ムに実際に入力する値をセットします。サンプルコード内②のcontroller.save() が実行されることによって、save アクションのテストが行えます。

G*Magazine vol.2@Test
void testSave() {controller.save()assert model.bookInstance != null
assert view == '/book/create'// TODO: Populate valid properties// ①ここの部分に追記
params.title=' 吾輩は猫 'params.author=' 夏目漱石 'params.isbn='0-00000000-000000'
params.price=1000
controller.save()// ②
assert response.redirectedUrl == '/book/show/1'
assert controller.ﬂash.message != null
assert Book.count() == 1

います。それによって、この同一 Unit テスト内では、Book を扱うことができるのです。
import org.junit.*
import grails.test.mixin.*@TestFor(BookController)@Mock(Book)
class BookControllerTests {..... 省略 .....

@Mock の指定は、複数のドメインクラスを指定する事も可能です。その場合は @Mock([Book, Author]) と、配列で定義するだ
けです。

@Mock を 指 定 す る 事 で、 ド メ イ ン ク ラ ス を デ ー

タ ベ ー ス に 繫 ぐ こ と な く GORM の 機 能 を テ ス ト でき る、DomainClassUnitTestMixin が 設 定 さ れ ま す。
DomainClassUnitTestMixin を 使 用 す る と メ モ リ 上 の}ConcurrentHashMap 内で GORM のデータが構築され動作します。

他のアクション、例えば show、edit 等の予めドメインクラス

こ と も 可 能 で す。 こ の 場 合 は、 ド メ イ ン ク ラ ス の モ ッ ク は、@TestMixin で、 直 接 DomainClassUnitTestMixin を 定 義 す るが必要になるコードの場合も似たような追記をします。

アクション show の例を紹介します。今度は、(a) の部分に通常

mockDomain( ドメインクラス名 ) で直接生成します。

行うのと同じように、Book のインスタンスを生成して、それぞ@TestFor(BookController)

ことで、Unit テストで内部的に保存され Book の id が取得できまclass BookControllerTests {れのプロパティを設定します。そして、book.save() を実行する@TestMixin(DomainClassUnitTestMixin)
void testSave() {す。params.id に、Book の id を 設 定 し て、controller.show() を 実

mockDomain(Author)

行することで、show アクションのテストが完成です。
@Test
void testShow() {controller.show()assert ﬂash.message != null
assert response.redirectedUrl == '/book/list'// TODO: populate domain properties (a)def book = new Book()
book.title=' 吾輩は猫 'book.author=' 夏目漱石 'book.isbn='0-00000000-000000'
book.price=1000
assert book.save() != null

mockDomain(Book)}}■ドメインクラスの Unit テスト

ここまででわかるように、コントローラ Unit テストでドメイ

ンクラスの Unit テストも簡単に行えるのがわかります。ただ、やはり制約などは、ドメインクラス用のテストを書きたいと思います。従来通りドメインクラスを create-domain-class コマンドで生成すると、ドメインクラスの Unit テストコードも生成されます。但し内容は以前と同じ何も記述されていない状態です。

先ほどのドメインクラス Book の Unit テストの例を紹介します。※誌面の関係上今回は多く説明しません。今後の参考になればと思います。

params.id = book.id
def model = controller.show()assert model.bookInstance == book}
ここで気になるのは、Book クラスの存在です。先ほど、生成されたコードのアノテーション部分をみると @Mock(Book) と指定してあります。この指定で Book クラスのモックが定義されて緊急企画

検証 ! Grails 1.4.0 の世界

7

G*Magazine vol.2

import grails.test.mixin.*
import org.junit.*@TestFor(Book)
class BookTests {void testSomething() {def book = new Book()
book.title=' 吾輩は猫 'book.author=' 夏目漱石 'book.isbn='123456789'
book.price=1000
assert book.save() != null
assert book.id != null

assert book.title==' 吾輩は猫 '}[ テストレポート ]void testConstraints(){
mockForConstraintsTests Bookdef book = new Book()
assert !book.validate()
assert "nullable" == book.errors["title"]
assert "nullable" == book.errors["author"]book.title=' 吾輩は猫 'book.author=' 夏目漱石 'book.isbn='12345678'
assert !book.validate()
assert "minSize" == book.errors["isbn"]
assert !book.validate()book.isbn='123456789'
book.price=1000
assert book.validate()}}
最後にテストレポートもデザインが変更になったので、スク

リーンショット載せておきます。

8

緊急企画

検証 ! Grails 1.4.0 の世界

今回は、UI・DB・Unit テストを紹介しました。まだ正式版のリリースは時期が 2011 Q3 としかわかっていません。これから
M2,M3? と 1.4 系のマイルストーンリリースラッシュになるのは確かです。速度・機能と共に向上した Grails 1.4 系、とても楽しみですね。

次号からも、時間がある限り、複数の著者で順番に「検証！

Grails 1.4.0 の世界。
」シリーズを掲載していきたいと思います。

G*Magazine vol.2

Griﬀon 不定期便

〜第 3 回 スレッド編 その１〜

series02

奥 清隆（おく きよたか）
仕事でもときどき Groovy と戯れるプログラマ。
日本 Grails/Groovy ユーザーグループ関西支部長。
著書：『Seasar2 による Web アプリケーションスーパーサンプル』

G* なみなさま、こんにちは。今回からスレッド編として 2 回に分けて Griffon アプリケーションでのスレッドの扱い方を紹介していきます。今回は Swing アプリケーションでスレッドを扱うための基本となる Swing のスレッドポリシーと Groovy のSwingBuilder でスレッドを扱う方法を紹介し、次回は Griffon でのスレッドの使い方をサンプルアプリケーションを作りながら紹介したいと思います。

Web アプリケーションの開発がメインで Swing アプリケー

ションにあまり馴染みのない方は、これまでにスレッドを扱う機会が少なかったかと思います。Web アプリケーションでは独自のスレッドを生成して処理するということはあまり必要とされません。しかし、Swing アプリケーションではスレッドの扱いを理解しておくことが大変重要になります。

Swing のスレッドポリシー
Swing アプリケーションで発生するイベントはすべて、イベン

トディスパッチスレッドと呼ばれる 1 つのスレッドで処理されます。

また、基本的に Swing コンポーネントはスレッドセーフでは

static メソッドを利用してイベントディスパッチスレッド上で処理を行うようにスケジュールします。

SwingUtilities
SwingUtilities に用意されているイベントディスパッチスレッ

ド上で処理をするためのメソッドには invokeLater(Runnable)、
invokeAndWait(Runnable) があります。それぞれイベントディス

パッチスレッド上で実行する処理を java.lang.Runnable インターフェースに実装したクラスのインスタンスを引数に取ります。
invokeLater メソッドはイベントディスパッチスレッドにスケジュールします。スケジュールされた処理は、スケジュールされた順番に実行されます。invokeLater メソッドはスケジュールしたあとで呼び出し元に処理が戻りますが、invokeAndWait メソッ
ドはスケジュールした処理が実行されるのを待ってから呼び出し
元に戻ります。次のコードでそれぞれのメソッドの動作を確認できます。

▼invokeLater_sample.groovy
import javax.swing.SwingUtilities

ないため、Swing コンポーネントに対する操作はすべてイベント

import groovy.swing.SwingBuilderと言いましたが、例外もあります。例えば、テキストエリアにテ

println "1 - ${Thread.currentThread().name}"

メソッドはスレッドセーフになっています。どのメソッドがス

new SwingBuilder().edt() {ディスパッチスレッド上で実行する必要があります。「基本的に」キストを追加する javax.swing.JTextArea クラスの append(String)
レッドセーフかどうかは Javadoc に記述されています。例えば

frame(show:true, pack:true) {javax.swing.JTextArea の append(String) メ ソ ッ ド の Javadoc に は

button 'Click', actionPerformed: {以下の注意書きが記述されています。

doOutside {SwingUtilities.invokeLater {このメソッドはスレッドに対して安全ですが、ほとんどの Swing メ
ソッドは違います。

sleep 1000

スレッドセーフなメソッドをイベントディスパッチスレッド内

println "2 - ${Thread.

で呼び出しても問題ありませんが、スレッドセーフではないメ

currentThread().name}"

ソッドをイベントディスパッチスレッド外で呼び出した場合は、}予期しない動作をすることがあるでしょう。スレッドセーフに関

println "3 - ${Thread.

する問題は、再現性がないため慎重に実装する必要があります。

currentThread().name}"}

イベントディスパッチスレッド上で処理を行うにはいくつか}方法があります。まず、各 Swing コンポーネントに登録したイ
ベントリスナの各アクションイベントを受け取るメソッド (java.

}}

awt.event.ActionListener クラスの actionPerformed() メソッドなど ) はイベントディスパッチスレッド上で実行されます。イベン
トディスパッチスレッド外から Swing コンポーネントに対する操作を 行 う 場 合 は javax.swing.SwingUtilities に 用 意 さ れ て い る

Griffon 不定期便 〜第 3 回 スレッド編 その１〜

9

G*Magazine vol.2▼invokeAndWait_sample.groovy

次のようなコードを実行してみましょう。

import javax.swing.SwingUtilities

import groovy.swing.SwingBuilder

import groovy.swing.SwingBuilder
new SwingBuilder().edt {println "1 - ${Thread.currentThread().name}"frame(show:true, pack:true) {gridLayout(cols:1, rows:2)

new SwingBuilder().edt() {label id:'label'button ' 更新 ', id:'button',frame(show:true, pack:true) {button 'Click', actionPerformed: {actionPerformed: {doOutside {sleep 3000

SwingUtilities.invokeAndWait {label.text = new Date().

format('HH 時 mm 分 ss 秒 ')sleep 1000
println "2 - ${Thread.

println 'Clicked!'currentThread().name}"

}

}

}

println "3 - ${Thread.
currentThread().name}"}}}}
更 新 ボ タ ン を ク リ ッ ク す る と、3 秒 後 に 時 刻 が 表 示 され、 標 準 出 力 に「Clicked!」 と 出 力 さ れ ま す。javax.swing.

JLabel#setText(String) メソッドは、スレッドセーフではありませ}んが、ボタンの actionPerformed に設定したクロージャはイベン

両方とも、同じウィンドウが表示されますが、ボタンをクリッ

ションはスレッドセーフです。しかし、更新ボタンをクリックしクしたときの挙動が異なります。それぞれ doOutside() を使用してイベントディスパッチスレッド外から SwingUtilities クラスのメソッドを呼び出すようにしています。（doOutside() メソッドに

トディスパッチスレッド内で実行されるため、このアプリケー

たときにボタンが押下状態のままになり、アプリケーションがフリーズしているように見えます。

ついては後で説明します。）

最初のサンプルコードを実行し、ボタンをクリックすると標準出力に次のように表示されます。
1 - main
3 - Thread-4
2 - AWT-EventQueue-0

invokeLater() メソッドに渡した処理を待たずに 3 番目の printlnが実行されているのがわかります。invokeAndWait を使用するサ
ンプルコードの実行結果は次のようになります。
1 - main
2 - AWT-EventQueue-0
3 - Thread-4
こちらは、invokeAndWait() メソッドに渡した処理が実行されて終わるのを待ってから 3 番目の println が実行されているのがわかります。イベントディスパッチスレッド外から Swing コンポー

ネントを操作する場合は状況に合わせてこの 2 つのメソッドを使用することでスレッドセーフなアプリケーションになります。

すべての処理をイベントディスパッチスレッド上で実行すればスレッドセーフに関する問題はなくなりますが、時間のかかる処理をイベントディスパッチスレッド上で実行するとアプリケー
ションがフリーズしたような状態になります。

10 Griffon 不定期便 〜第 3 回 スレッド編 その１〜押下状態のままボタンをクリックしても動いていないように見えますが、実はクリックしたときに発生するイベントがイベント
ディスパッチ上にスケジュールされています。しばらく押下状態が続いたのち、クリックした回数だけ標準出力に「Clicked!」と表示されます。
もしこれが何かデータを登録する処理だった場合、ユーザがクリックした回数だけデータが登録されてしまいます。
このようにアプリケーションが止まっているような状態になるのを回避するためには、イベントディスパッチスレッドから新しくスレッドを生成して処理する必要があります。この方法については後ほど紹介いたします。

Swing のスレッドポリシーについては Javadoc に記述されていますので、一度読んでおくといいでしょう。

http://java.sun.com/javase/ja/6/docs/ja/api/javax/swing/package-summary.html#threadingG*Magazine vol.2

SwingBuilder でスレッドを扱う
Swing で の ス レ ッ ド の 扱 い 方 を 紹 介 し ま し た が、Groovy のSwingBuilder ではスレッドの扱いが簡単でさらに賢く使えるようになっています。SwingBuilder ではスレッドを扱うメソッドとして、edt()、doOutside()、doLater() の 3 つが用意されています。
それぞれのメソッドは SwingUtilities と以下のように対応します。
• edt()

	SwingUtilities#invokeAndWait() に相当。イベントディ
スパッチスレッド上で呼び出された場合は引数のク
ロージャをそのまま実行。

• doLater()

SwingUtilities#invokeLater() に相当。

• doOutside()	イベントディスパッチスレッド上で呼び出された場合は、新しいスレッドを生成して、引数のクロージャをイベントディスパッチスレッド外で実行。イベントディ
スパッチスレッド外で呼び出された場合はクロージャをそのまま実行。

こ れ ら の メ ソ ッ ド を 使 わ ず に、SwingUtilities を 使 用 す る こと も で き ま す が、SwingBuilder の メ ソ ッ ド を 使 用 す る こ と で処理がどのスレッドで実行しているかが分かりやすくなりま

す。 ま た SwingUtilities#invokeAndWait() メ ソ ッ ド は イ ベ ン ト

ディスパッチスレッド内から呼び出すとエラーが発生しますが、SwingBuilder の edt() メソッドは呼び出されたスレッドがイベン
トディスパッチスレッドかどうかを判断してくれるので使い勝手もよくなります。

SwingBuilder を使用して先ほどのサンプルコードを正しく実装

し直してみましょう。

ボタンをクリックしたときのイベントはイベントディスパッチ

スレッド上で実行されます。処理が終わるまでボタンをクリック

出来ない様に javax.swing.JButton#setEnabled(boolean) メソッドを使用してボタンを無効化しています（①）
。

次に時間のかかる処理をバックグラウンドスレッドで実行する

ように doOutside を使用しています（②）
。doOutside に渡すク
ロージャはイベントディスパッチスレッドとは別の新しいスレッ
ドで実行されます。3 秒待つために、1 秒間スレッドを止める処理を 3 回ループしています。このループの中でラベルのテキストに「.」を追加しています（※）。これはユーザに処理中であることを知らせる簡易的なプログレスバーと考えてください。このとき、処理はバックグラウンドスレッド内で実行されているので、
イベントディスパッチスレッド上でラベルのテキストを変更する必要があります。ラベルのテキストを変更したあとでスレッドを止めるには edt() メソッドを使用します（③）
。doLater() を使用してもイベントディスパッチスレッド上で実行されますが、処理をスケジュールするだけですので後続のスレッド停止処理と並行して実行されることになります。

3 秒スレッドを停止したら、ラベルに時刻を表示して、ボタンを有効化させます（④）。ここでは doLater を使用して処理をス
ケジュールさせます。バックグラウンドスレッドはこれで終了しますが、後でイベントディスパッチスレッド上でラベルに時刻が表示され、ボタンがクリック出来る状態になります。

※ボタンを無効化させるだけでもアプリケーションとしては問題ありませんが、それだけでは待たされる方としてはアプリケーションが動いているのかどうかわかりません。今回は説明をシンプルにするためにラベルのテキストを変更していますが、実際にアプリケーションを作成す

import groovy.swing.SwingBuilder
new SwingBuilder().edt {frame(show:true, pack:true) {gridLayout(cols:1, rows:2)
label id:'label'button ' 更新 ', id:'button',actionPerformed: {// ①button.enabled = false
label.text = ''// ②
doOutside {3.times {// ③
edt { label.text += '.' }sleep 1000}// ④
doLater {label.text = new Date().
format('HH 時 mm 分 ss 秒 ')button.enabled = true
println 'Clicked!'
}
}
}
}
}

る 場 合 は javax.swing.JProgressBar な ど を 使 用 し て 処 理 の進捗状況を知らせるのが良いでしょう。SwingBuilder では

progressBar() メソッドを使用して javax.swing.JProgressBar
コンポーネントを利用できます。

Griffon 不定期便 〜第 3 回 スレッド編 その１〜

11

G*Magazine vol.2

まとめ
イメージとしては、仕事中の自分がイベントディスパッチス

レッドと考えてください。何か作業が発生（イベントが発生）し、その作業を他の誰かに振るのが doOutside() です。作業を他の人に振ったので別の作業に取り掛かれます。作業を振られた人が作業の途中であなたに確認を取らなければいけなくなり、「確認お願いします」と言い、あなたは「そこに置いといて下さい、手が開いたときにやっときます。」というのが edt() です。確認をお願いした方は確認が終わるまで作業を終えることができませんし、他のこともできません（ひどい話ですが例えばの話です）。

また別の作業があって、その作業は誰にも振らず自分でやるとします。自分でやりますが別の作業があって今やれないときは「あとでやる」ことにします。これが doLater() です。

あまり関係ないですが、私は「あとでやる」というのが好きです。

あとでやるというか「明日やる」ことにするのが好きです。そしてギリギリになってやる羽目になり泣きながらやります。この記事を書いている今も少し泣いています。

少 し や や こ し く な り ま し た が、Swing の ス レ ッ ド ポ リ シ ーを理解することでアプリケーションの出来が変わってきます。
SwingBuilder の edt()、doLater()、doOutside() の使い方をマスター
すれば、より簡単にスレッドを扱うことが可能になります。今回は Swing のスレッドポリシーと Groovy で使う方法の紹介で終わってしまいましたが、次回はいよいよ Griffon でスレッドを扱う方法を紹介いたします。それではまた次回。

12 Griffon 不定期便 〜第 3 回 スレッド編 その１〜

G*Magazine vol.2

CodeNarcを利用してGROOVYのコード品質を上げる〜第 2 回 開発ツールと連携〜
series03

荒井健太郎

某 IT ベンダーのセキュリティコンサルタント、ソフトウエアをよりセキュアにするために日々精進しています。
テスト系スクリプトは、G* を利用して書いています。

はじめに
前回は CodeNarc の基本操作を解説した。

今回は開発の現場でより実践的に利用できるようにするために方法として次の項目を解説する。
• IntelliJ IDEA との統合

• Grails プラグインの利用
最終回の第 3 回は解析ルールのカスタマイズ方法を解説する。
本稿は次の環境を前提で話を進める。

• Groovy1.7 がインストールされていること• JDK1.6 がインストールされていること[ 図 1]■解析の実行Inspections は有効にすると即座にコードに反映される。問題を検知した行はエディタの右側に黄色で表示され、該当行はうすIntelliJ IDEA との統合

いオレンジ色で反転される。反転されている場所にカーソルを合わせるとライトのマークが左に表示されクリックすると適用され■IntelliJ IDEA のインストール

IntelliJ IDEA は、チェコの JetBrains 社により開発されている統ているルールや変更適用などの項目などが表示される ( 図 2)。

合開発環境である。Java の開発は有償版でないと実施できないが Groovy の開発は Community 版で可能である。機能の詳細等はWeb 等の記事を参考にして頂きたい。

Community 版 は、http://www.jetbrains.com/idea/download/

index.html からダウンロード可能である。インストールはインス

トーラーの指示に従って簡単にインストールすることができるので各自でインストールして頂きたい。

■CodeNarc プラグインの組込みIntelliJ IDEA を起動し、_File_ → Settings の順番にクリックし左側ペインで Plugins を選択する。右側ペインで Available タブをク

[ 図 2]

リックし CodeNarc を選択し右クリックし Download and Installをクリックする。ダウンロード及びインストールが実行された後に OK をクリックすると再起動をうながすポップアップがあがる
ので再起動する。

再 起 動 後、File → Settings を ク リ ッ ク し 右 側 ペ イ ン でInspections をクリックすると右側ペインに CodeNarc が表示されているのでチェックをいれる ( 図 1)。

CodeNarc を利用して GROOVY のコード品質を上げる〜第 2 回

開発ツールと連携〜

13

G*Magazine vol.2

Grails プラグインの利用
Grails の CodeNarc プラグインを利用すると、Grails で作成されcodenarc.reports = {それぞれのレポートに対して以下の設定を実施する :た Web アプリケーションに対して容易に CodeNarc の解析を実行

REPORT-NAME( レポート形式 ) {することができる。

プロパティ名 = プロパティ値

本稿は Grails を利用して作成したアプリケーションが既にある

プロパティ名 = プロパティ値

前提で話を進める。Grails の詳細については、G*Magazine 準備号の「Grails - JavaEE 開発をライトにするフルスタックフレームワーク」等の記事を参照して頂きたい。

■Grails プラグインの導入

Grails プロジェクトディレクトリに移動し次のコマンドを実行

する。

}
}
レ ポ ー ト 形 式 は、_html_, _xml_, _text_, CodeNarc のReportWriter を継承したクラス名を指定できる。

次 は、XML 形 式 で フ ァ イ ル 名 が CodeNarc-Report.xml、 タ イ

トルが Sample Report のレポートと HTML 形式でファイル名がgrails install-plugin codenarc

CodeNarc-Report.html、タイトルが Sample Report のレポートを

Grails のスクリプトが実行されプラグインが導入される。

すると、設定した値でレポートが作成されることが確認できる。

■Grails プラグインの実行

Grails プロジェクトディレクトリに移動し次のコマンドを実行する。

出力する例である。プロパティを編集し Grails プラグインを実行

codenarc.reports = {MyXmlReport('xml') {// The report name "MyXmlReport" is user-deﬁned;
Report type is 'xml'
outputFile = 'CodeNarc-Report.xml'

grails install-plugin codenarc
CodeNarc の 解 析 が Grails プ ロ ジ ェ ク ト に 対 し て 実 行 さ れ、

CodeNarcReport.html がプロジェクトディレクトリに作成される。

// Set the 'outputFile' property of the (XML)
Reporttitle = 'Sample Report'// Set the 'title' property of the (XML) Report}■Grails プラグインの設定●標準の設定MyHtmlReport('html') {// Report type is 'html'
outputFile = 'CodeNarc-Report.html'

Grails プ ラ グ イ ン は 標 準 の 設 定 で Grails プ ロ ジ ェ ク ト のtitle = 'Sample Report'

次 の デ ィ レ ク ト リ に 対 し て 解 析 を 実 行 し、HTML 形 式 のCodeNarcReport.html レポートを生成する。
• src/groovy• grails-app/controllers• grails-app/domain• grails-app/services}}●ルールのカスタマイズ

利用するルールのカスタマイズは次の書式で変更する。

• grails-app/taglib

codenarc.ruleSetFiles="ﬁle: 利用するルールファイル "• test/unit

次は、カスタムルール ( 次回に解説予定 )MyRuleSet.groovy を• grails-app/utils• test/integration

また、解析に利用されるルールは、rulesets/basic.xml,rulesets/

exceptions.xml, rulesets/imports.xml,rulesets/grails.xml, rulesets/
unused.xml である。

設 定 は、_grails-app/conf/config.groovy_ に _codenarc.XXX_を追加し変更できる。代表的なものを次節以降で紹介する。
●レポートのカスタマイズ

出力レポートのカスタマイズは次の書式で変更する。

利用する例である。

codenarc.ruleSetFiles="ﬁle:grails-app/conf/MyRuleSet.groovy"●解析対象ファイルのカスタマイズ• codenarc.processSrcGroovy - src/groovy を 解 析 対 象 と す るか。 ( 標準は true)• codenarc.processControllers - grails-app/controllers を解析対象とするかを指定。 ( 標準は true)• codenarc.processDomain - grails-app/domain を解析対象とするかを指定。 ( 標準は true)

14 CodeNarc を利用して GROOVY のコード品質を上げる〜第 2 回 開発ツールと連携〜

G*Magazine vol.2• codenarc.processServices - grails-app/services を解析対象とするかを指定。 ( 標準は true)• codenarc.processTaglib - grails-app/taglib を解析対象とするかを指定。 ( 標準は true)• codenarc.processTestUnit - test/unit を解析対象とするかを指定 ( 標準は true)• codenarc.processTestIntegration - test/integration を 解 析 対象とするかを指定 ( 標準は true)• codenarc.processViews - grails-app/views 以下の GSP を解析対象とするかを指定 ( 標準は false)• codenarc.extraIncludeDirs - 上記以外のソースを解析対象とする場合に指定

次は、'grails-app/jobs/*.groovy' を解析対象とする場合の例である。

codenarc.extraIncludeDirs=['grails-app/jobs']■まとめ

今回は、CodeNarc を IntelliJ IDEA と統合する方法及び Grails プ

ラグインを利用して静的解析する方法を解説した。これによって、
CodeNarc がより現場で利用されるようになればと考えている。

今回紹介した以外にもさまざまなフレームワーク、ツールと連携することが可能である。詳細は、http://codenarc.sourceforge.

net/codenarc-other-tools-frameworks.html を参照して頂きたい。
次回はプロジェクト固有のルールを作成する方法を解説し最終回とする予定である。

CodeNarc を利用して GROOVY のコード品質を上げる〜第 2 回

開発ツールと連携〜

15

G*Magazine vol.2

もし新人女子 Java プログラマが『Groovy イン・アクション』を読んだら 〜第１章〜
series

06

吉田

健太郎

仕事では Java、趣味でライフワークの如く Groovy と戯れるプログラマ。
日本 Grails/Groovy ユーザーグループ運営委員参画予定。
ブログ：『No Programming, No Life』http://d.hatena.ne.jp/fumokmm/

第１章 も かは『Groovy イン・アクション』と出会った■新人女子 Java プログラマ4 月、それは新社会人にとって新たな幕開けの季節だ。もかにとってもそれはそうだった。七海 萌香 ( ななみ もか )、はソフトハウスとしては中堅どころのジェイガ株式会社へとプログラマ志
望で入社した新入社員の一人だった。

新人教育でビジネスマナーやら簡単な手続きを済ませた後は、早速プログラミング講習が待っていた。言語は Java だった。
もかはこれまで簡単なホームページを HTML や CSS、それから

Web1.0 時代の JavaScript で書いたことがあるくらいだったので、もか「なるほどね、こなつは勉強熱心だよね、感心しちゃうよ」

こなつ「いえいえ、そんなことないです ... 私、出来が悪いし ... みんなについていくのに必死なんです」

それを聞いていたもかは目を閉じてしばし無言になった。しば

らく何か考えている様子だったが、ゆっくりと目を開いてからこう言った。

もか「私も一緒について行っていい？」

こなつ「え、あ、はい ... いいですよ」

きょとんとしているこなつを尻目に、もかは嬉しそうににんま

これが本格的なプログラミング言語との出会いだった。

りと笑顔を見せた。

人女子社員は一ノ瀬 小夏 ( いちのせ こなつ ) という名前の女の子がないらしく苦労しているようである。会社でも Java の講義に開発に憧れて情報系に進んだらしいのだが、現実の厳しさなどを少しでも追いつこうとして、参考書を購入しようというわけだ。

たらしい。どうあれ、新人女子社員は二人だけということもあり、もか「本屋さんって近くにあるの？私、どうも本って苦手で今年の新人は男性が８名、女性が２名であった。もう一人の新だった。こなつは情報系専門学校を卒業しており、当初はゲーム目の当たりにし、それから色々あってジェイガに入ることに決めもかとこなつはすぐに打ち解けることができた。

追いついていくのがやっとといったところのようである。だから

さぁ ... 一人では本屋さんなんてあまり行かないから」
こなつ「え、そ ... そうなんですか？ごめんなさい、私誘ちゃっ
たみたいで ...」

■ある日の定時後もか「あー今日も終わった終わった〜！お疲れちゃ〜ん！」

こなつ「はい ... お、お疲れ様です」

もか「へへーん、頑張ったわ私！

こなつは勉強熱心なのだが、どうやらプログラミングには自信さてっと ... ねぇねぇ、こなつぅ！ちょっといい？」
私と違ってこなつはちっちゃくて目もクリっとしててかわいいんだよね、ついつい誘いたくなっちゃう。

もか「え？ううん、今日は私がついて行きたいって言い出した
んだし、こなつは全然悪くないよ！むしろ謝らなきゃい
けないのは私の方だよね」
こなつ「ううん、一緒に来てくれるの嬉しいですよ、一緒に選んでもらえるとすごく助かります」
こなつはえへっと笑顔を見せた。

こなつ「え、あ、はい ... 何ですか？」もか「今日ってさ、このあと時間ある？ どこかにパーッと遊びに行きたいなぁって思ってるんだけど」

こなつ「え、あ、はい ... でも私ちょっと寄りたいところが ...」
こなつは困った表情をしている。
もか「あ〜そうなんだ ...。ふーん、じゃあ仕方ないかぁ」

こなつ「私、Java の講義について行けてなくて ... 会社からもらった参考資料だけじゃだめだなーって思うんです。だからちょっと本屋さんに寄って、Java の本を買いたい
なって思ってるんです！」

16 もし新人女子 Java プログラマが『Groovy イン・アクション』を読んだら 〜第１章〜

G*Magazine vol.2■書店にてパラパラとページをめくってみた。

もか「さーて、着いたわね。こなつはもうどれを買うか決めてるの？」

こなつ「え、えーと ... か、簡単そうなのがいいなぁと思って ... 講
義 の 内 容 が ち ょ っ と 難 し く て。 ほ ら、 こ の あ い だ、class の話になったあたりから急に難しくなったでしょう？だから分かりやすく丁寧に書かれている参考書が欲

もかはふと P63 のコードに目が止まった。そのページのタイト

ルは「3.4.3 Java から Groovy へ」となっていた。
System.out.println("Hello Groovy!");うんうん、これは Java のコードよね、一番初歩的はハローワー

ルドだわ。そしてすぐ下はこう続いていた。

しいなって思ってるんです」
それを聞いたもかは、ある本を指差しながらこう言った。
もか「ふーん、なるほどね。じゃあさ、これなんてどう？『たのしい Java』っていうタイトルからしていかにもって感じじゃない？」System.out.println('Hello Groovy!');ダブルクォーテーションがシングルクォーテーションになったのね、JavaScript みたいなものかしら。

もかはそこまで気に留めず、例をさらに読み進めた。
print('Hello Groovy!');もかはその本を取って渡してあげた。
こなつ「わぁ〜いいかもです。ちょっと見て見ますね」
こなつがその本を見ている間、もかは Java の本が並ぶ棚の他の本を眺めて回っていた。

もかは Java こそ今回の研修で初めてやったとはいえ、プログ

ラミングというものにはずっと興味を抱いていたし、JavaScript

で簡単なアルゴリズムだったり、クラスだったりの概念は理解しているつもりである。今日まで行われた講義も分からなくなるところは全然なかった。

いっぱい本あるなぁ ... と、そんなことを思いながら何気なく本を眺めていると、もかの視界にとある本が飛び込んできた。その本のタイトルは、

すごいすっきりしてきたわ。Java だと System.out.println ってドットでつないで長く書いていかないといダメけど、Groovy だと System.out が要らないんだ。
print 'Hello Groovy!'
わぁ、括弧までなくなっちゃった。すごくスッキリした感じ。

もかはさらに読み進めた。

greeting = 'Hello Groovy!'
assert greeting.startsWith('Hello')
assert greeting.getAt(0) == 'H'
assert greeting[0]『Groovy イン・アクション』
んっ？ぐるーびー？何だろうこれ。なんで Java のコーナーに？
他の本は Java という名前がつく本ばかりであるのに。気になったのでちょっと手に取ってみた。ずっしりと重みを感じる。それ== 'H'

assert greeting.indexOf('Groovy') >= 0
assert greeting.contains('Groovy')
assert greeting[6..11] == 'Groovy'

もそのはず、600 ページ近くもあってかなり分厚い。表紙にはな

assert 'Hi' + greeting - 'Hello' == 'Hi Groovy!'あった。

assert greeting.count('o') == 3にやら日本人形のような踊り子さんが描かれている。帯にはこう● Groovy とはassert 'x'.padLeft(3) == 'x'Java プラットフォームのためのアジャイルで動的な言語です。

assert 'x'.padRight(3,'_') == 'x__'

入れ、Java 開発者が Java 風の構文を使ってこれらを利用でき

assert 'x' * 3 == 'xxx'

Python や Ruby、Smalltalk などの言語から多くの機能を取りるようになっています。スクリプト言語として言及されることも多いのですが、その枠にとどまるものではありません。

assert 'x'.center(3) == ' x 'え？ ほ ん と ?こ ん な 記 述 で い い の？ assert っ て あ れ？ こ なJava 実行環境上で動作するため、Java バイトコードにコンパいだの講義でやった JUnit ってやつにも出て来たやつだよね、を備えています。

ドなんだわ！（後にもかは P28, P29 ページの assert の解説を読んイルすることも可能であるなど、非常に強い「Java との親和性」

assertEquals とかってやつ。ってことはこれはつまり、
テストコー
で assertEquals よりも Groovy の assert がもっと軽量に使えて便利

ふーん ... ？なんだかすごそうね。Python とか Ruby とかは聞いた事はあるけど、Groovy ってどんな言語なんだろう？すもーるとーくっていうのは知らないけど ...。ちょっと興味がわいたのでだということを知ることになる）

え？うそうそ！？文字列に対してマイナスが使えるの？？あと [6..11] で切り出したりできるの？すごい！それから、最後のもし新人女子 Java プログラマが『Groovy イン・アクション』を読んだら 〜第１章〜

17

G*Magazine vol.2
padLeft, padRight, center っていうので文字を空白埋めしたり、
アンダーバーで埋めたりできちゃうんだ！それからそれから、文字のかけ算も？

もかはすごく興奮しだしている自分を感じていたが、頭の中で、これは Java じゃないんだから今の私とは関係ないないんだ！と言い聞かせるようにしていた。

そうこうしているうちに、こなつがニコニコしながらもかの側に寄って来た。手には先ほどの『たのしい Java』を持っている。
こなつ「もかちゃん！私この本にするね」

もか「そうだね、その本なら Java に限らずプログラミングの基本的なところも勉強できるしいい本だと思うわ」

こなつ「私、この本読んで頑張る！みんなについて行けるように」もか「うんうん、頑張って勉強して一緒にかっこいいプログラマになろうねっ！」
こなつ「ありがとう、もかちゃん。あれ？ところでもかちゃんも何か本を買うの？」
こなつはもかが持っている『Groovy イン・アクション』に目がいった。

もか「あー、えっと、なんかこれね、Java とは違うプログラ
ミング言語の本なんだけど、ちょっと面白そうなのよ。
まだちょっと立ち読みしてただけだから、あまりわからないんだけど Java との親和性が高いんだって」
こなつ「えーー？すごいね、やっぱりもかちゃんは ... 私なんてJava だけで精一杯なのにもかちゃんは違うプログラミ
ング言語も勉強してるの？私どんどん置いて行かれちゃう ...」
もか「ちがうちがう、私も Java は今回の講義で始めたばっ
かりだし、良くわかってないところが多いし ... まずは
Java をマスターしなきゃ！」そう言いながら、もかは『Groovy イン・アクション』を棚に

戻した。

■自室にて

その日の夜。自室のベッドに入って寝る前にもかは今日本屋さんで見た『Groovy イン・アクション』のことを思い出していた。
なんとなく興奮が止まらない。プロブラミングは好きだけど、こんなにドキドキしたことって今までなかったな。もしかしたらこれって運命の出会い？とか言っちゃって。なにそれ ... 素敵な男の子じゃなくてプログラミング言語との出会いなんて。もかはそんなことを考えながら苦笑する。もう ... こんなこと考えてるから私ってモテないのかなぁ、女子力っていうの？全くない！こなつがうらやましいなぁ ... ちっちゃくて、かわいくて。ああいう子は絶対にモテるんだよなぁ ...。

とりとめのないことを考えながら、いつのまにかもかは眠りについていた。

■Java の演習

次の日、出社したもかたちは Java の講義を受けているところだ。今日も恒例の課題が出題されるようだ。

「さーて、みんなそろそろ Java に慣れてきたところだろう、次はこんな問題だ。周りと相談しないで自分だけで解くように」
正の整数 n が与えられたときに、高さ n のピラミッドを出力するプログラムを作ってください。
n=4 の時の出力は下のようになります。
*
***
*****
*******

もかはピンときた。なるほどね、これは単純な文字列操作の例

ね。よーし、作るぞぉ！もかは意気込んでこの課題に取り組んだ。
数十分後、Java のコードが出来上がった。

public class Pyramid {/*** ピラミッドを出力するプログラム♪
* @author 七海 萌花* @param args 何段にするか*/
public static void main(String[] args) {int dan = Integer.parseInt(args[0]);for (int i = 0; i < dan; i++) {String hidari = "";String migi = "";for (int j = 0; j < dan - (i + 1); j++) {hidari += " ";migi += " ";}String moji = "";int mojisuu = 1 + (2 * i);for (int j = 0; j < mojisuu; j++) {moji += "*";}
System.out.println(hidari + moji + migi);}}}
ふぅ〜、なんとかできた。こんなもんだよね？他の人はできた

18 もし新人女子 Java プログラマが『Groovy イン・アクション』を読んだら 〜第１章〜

G*Magazine vol.2
ら数十秒固まったあとになんとか納得してくれたようで、こなつはまた苦渋の表情を浮かべながらソースコードとにらめっこを始めたのだった。

■もし Groovy だったら自分の席に戻ったもかは課題をちょっとだけ早く終わったことで空いた時間、昨日のことを思い出していた。そういえばこの問

題、もしかしたら Groovy で書いたらもっと簡単に書けるんじゃないのかな？ええと確か、そうそう、center っていうのがあった
わよね。たとえば、1 段目なんて、"*".center(7) とかすればできのかなぁ〜、ちょっと遊びに行ってみようかな。もかはこなつの席に近寄ってみた。すると苦悶の表情を浮かべているこなつがそるんじゃないかしら？わくわくしてきて、もかはそのあとずっと
Groovy のことを考えていた。

こにいた。

もか「こ ... こなつ？大丈夫？苦しそうだけど ...」

こなつ「え、あ、はい ... ちょっと考え過ぎちゃって頭がぐるぐ
るなんです ...」
もか「そっかそっか ... まだ時間はゆっくりあるし、頑張って考えてみるといいよ」
こなつ「はい ... もかちゃんはもう出来たの？」

もか「うん、まぁね。あれであってるかどうかは分からないけど」

こなつ「やっぱりもかちゃんすごいね！他の誰よりも早いもの ... すごいです！」
こなつが突然大きな声を出すので、みんなの視線が二人の方に集まった。

その日の研修が終わり定時になると、もかは誰とも話をせずにもか「（小声で）こ、コラー（笑）恥ずかしいじゃん」

こなつ「（小声で）ごめんなさい（笑）」

書店に走っていた。目的はもちろん一つ、『Groovy イン・アクション』を手に入れることだった。書店に到着したもかはさっそく、昨日『Groovy イン・アクション』を見つけた棚へと走った。

途中でこなつのコードをちらっと見せてもらったのだが、こな「はぁ ... はぁ ...、あ、あったわ！」

String hoshi4_1 = "*";String hoshi4_2 = " *** ";String hoshi4_3 = " ***** ";String hoshi4_4 = "*******";
String hoshi5_1 = "*";String hoshi5_2 = "***";String hoshi5_3 = " ***** ";String hoshi5_4 = " ******* ";String hoshi5_5 = "*********";
if (args[0].equals("4")) {System.out.println(hoshi4_1);
System.out.println(hoshi4_2);
System.out.println(hoshi4_3);
System.out.println(hoshi4_4);} else if (args[0].equals("5")) {.
.
.
}本がそこにあったことで安堵した。
あらためて本を手に取るもか、つは各段を全部打ち込んでしまっているようで ...

そんなに焦らなくてもよかったのかもしれないけれど、もかは踊り子さんも微笑んでくれている。よーし買うぞぉ！もかは値段を確認してみた。本の裏表紙には ¥5,800 + 税と書かれていた。

「うわっ ... ちょっと高い ... けど！これはきっと運命なんだわ！」
興奮していたので、ちょっとだけ声が漏れてしまったようだ。

周りの人に白い目で見られたが、もかはそんなことを気にはしていなかった。

のような感じになってしまっていた。これだともっといろんな段数のパターン全部作るわけにはいかないよね？と教えてあげたもし新人女子 Java プログラマが『Groovy イン・アクション』を読んだら 〜第１章〜

19

G*Magazine vol.2■自室にて

早 速 買 っ て 来 た『Groovy イ ン・ ア ク シ ョ ン 』 を 片 手 に ま

それにしてもすごいわ ... たった 5 行で出来ちゃった。それに、すごく見やすいし、分かりやすい！

ず は Groovy の イ ン ス ト ー ル 作 業 を 行 っ た。 こ れ は P536 を 見

な が ら も か に も 簡 単 に で き た。 そ の 後、P15 に 書 か れ て い た

groovyConsole というもので、簡単にコード片を動かして試せることが分かったので、もかは今日の講義中に考えていた Groovyのコードを早速書いて実行させてみた。
int dan = 4
for (int i = 0; i < dan; i++) {String moji = "*" * (1 + i * 2)println(moji.center(dan * 2 - 1))}
出来上がったコードはこれ。動かしてみたもかは感動した。
「わぁ〜！ちゃんとピラミッドが出て来た！やった〜！」

こうして、『Groovy イン・アクション』ともかは出会ったのであった。

その日、遅くまでもかの部屋の明かりは消えることが無かった。
（続く）

イラスト・けんや

20

もし新人女子 Java プログラマが『Groovy イン・アクション』を読んだら 〜第１章〜

G*Magazine vol.2

Grails Plugin 探訪
第3回~ MongoDB GORM プラグイン ~URL: http://grails.org/plugin/mongodb
プラグインのバージョン : 1.0-M5

対応する Grails のバージョン : 1.3.5 以上

杉浦孝博
最近は Grails を使用したシステムの保守をしている自称プログラマ。
日本 Grails/Groovy ユーザーグループ事務局長。

共著『Grails 徹底入門』、共訳『Groovy イン・アクション』

はじめに

grails {今回紹介する Grails プラグインは、MongoDB GORM プラグイ

mongo {

ンです。

host = "localhost"て Grails から MongoDB にアクセスできるようになります。

username = "jggug"

このプラグインをインストールすることで、GORM API を使っ

port = 27107

今回は、以下のバージョンの Grails、MongoDB で試しました。

password = "jggugpass"• Grails : 1.3.7• MongoDB : 1.8.0• OS : MacOS X 10.6

MongoDB とは
MongoDB は、C++ で開発されたドキュメント指向のデータベースです。BSON とよばれる JSON ライクなバイナリドキュメ
ントを管理します。

• 詳細は、MongoDB の公式サイト http://www.mongodb.org/
を参照してください。

MongoDB GORM プラグインのインストール

最初に、Grails アプリケーションのプロジェクトに MongoDB

GORM プラグインをインストールします。
$grails install-plugin mongodb

設定
何の設定もしない場合、MongoDB が 27017 ポートで動作しているとみなし、Grails アプリケーションは動作します。

MongoDB の 設 定 を し た い 場 合、grails-app/config/Config.

groovy を編集します。

databaseName = "jggugdb"}}
DB 名は、指定しない場合、Grails アプリケーション名となります。

RDBMS と MongoDB を両方使いたい場合
Hibernate プ ラ グ イ ン を ア ン イ ン ス ト ー ル せ ず、MongoDB

GORM プラグインと両方のプラグインがインストールされている

場合、grails-app/domain ディレクトリ配下のドメインクラスは、
Hibernate 経由で RDBMS に永続化されます。

特定のドメインクラスを MongoDB に永続化したい場合、ドメ

インクラスに mapWith プロパティで指定する必要があります。
static mapWith = "mongo"

あるいは、Hibernate のエンティティに追加された "mongo" というスコープを使用します。

// Hibernate 経由で RDBMS からインスタンスを取得
def hibernateBook = Book.get(1)// RDBMS からインスタンスを MongoDB に保存
hibernateBook.mongo.save()// MongoDB からインスタンスを取得
def mongoBook = Book.mongo.get(1)Grails Plugin 探訪

第 3 回〜 MongoDB GORM プラグイン〜

21

G*Magazine vol.2

MongoDB だけ使う場合やメインの DB として使う場合
MongoDB だけ使う場合やメインの DB として使う場合、デフォ

ルトでインストールされている Hibernate プラグインをアンイン
ストールします。

■ドメインクラスの作成

ドメインクラスを作成します。本をあらわす Book ドメインク

ラスと、出版社をあらわす Publisher ドメインクラスを作成します。

$ grails create-domain-class Book

$ grails uninstall-plugin hibernate
こうすることで、grails-app/domain ディレクトリ配下のドメ$ grails create-domain-class Publisher
Book ドメインクラスの内容は次のとおりです。

インクラスは、MongoDB に永続化されるようになります。

package pluginmongodb

API を使う場合、NullPointerException が発生することがあるか

class Book {ただし、Hibernate プラグインをアンインストールし GORM

もしれません。

String title

そのような場合は、ドメインクラスに mapWith プロパティをInteger price

設定し明示的に MongoDB を使うことを宣言してください。

Publisher publisher

高度な設定

static constraints = {

設定は Config.groovy で行いますが、先程紹介した以外にも設}

options ブロックで、MongoDB との接続設定を変更できます。

static mapWith = "mongo"

grails {String toString() {定できる項目があります。

mongo {

title

options {}autoConnectRetry = true
connectTimeout = 300}}}
Publisher ドメインクラスの内容は次のとおりです。
package pluginmongodb}
また、本番環境ではマスター / スレーブ、レプリケーションとclass Publisher {いった形式、複数の MongoDB サーバーを動作させることがある

String nameと思います。

そのような設定も、Config.groovy で行います。

static constraints = {}grails {mongo {

static mapWith = "mongo"

replicaSet = [ "localhost:27017","localhost:27018"]

String toString() {

}

name

}

簡単なサンプル
ここでは、MongoDB を使った簡単なサンプルを作ってみます。

■Grails アプリケーションの作成

Grails ア プ リ ケ ー シ ョ ン を 作 成 し ま す。 こ こ で は、

pluginmongodb という名前とします。

$ grails create-app pluginmongodb$ cd pluginmongodb

22 Grails Plugin 探訪 第 3 回〜 MongoDB GORM プラグイン〜}}■コントローラとビューのスカフォールド

generate-all コマンドで、コントローラとビューをスカフォー

ルドします。

$ grails generate-all pluginmongodb.Book$ grails generate-all pluginmongodb.Publisher
スカフォールドされるコントローラおよびビューは、GORM

API(list, count, save など ) が使われた通常のファイルとなります。

G*Magazine vol.2■アプリケーションの実行

ア プ リ ケ ー シ ョ ン を 実 行 し ま す。 ア プ リ ケ ー シ ョ ン は、MongoDB に対しドメインクラスのインスタンスの CRUD を行い対して操作を行います。
class BookService {def mongoます。

def addBook(params) {def db = mongo.getDB("jggugdb")
db.books.insert([title:params.title,
price:params.price, publisher:params.publisher])}}Config.groovy の grails.mongo.databaseName で定義した DB 名に "DB" を追加した名前の、DB を参照する Bean も定義されます。
また、insert() メソッドの代わりに、左シフト演算子が使用できます。

上記の例は、以下のようになります。
class BookService {[ 一覧画面 ]def jggugdbDB
def addBook(params) {jggugdbDB.books << [title:params.title,
price:params.price, publisher:params.publisher]}}

トランザクションについて
MongoDB は直接トランザクションをサポートしていません

が、MongoDB GORM プラグインを使用することで、トランザク
ション処理を行うことができます。

トランザクションの指定は、次のとおりです。

1. サービスクラスにトランザクション指定をする
2. withTransaction() メソッドを使う■サービスクラスにトランザクション指定をする[ 詳細画面 ]低水準な API

サービスクラスの transactional プロパティに 'mongo' という値を設定することで、トランザクション処理が行われます。
class BookService {static transactional = 'mongo'

MongoDB GORM プラグインは、GORM API だけでなく、低水

準な API も提供しています。

Gmongo と呼ばれる Mongo Java Driver の Groovy ラッパーが...
}あり、コレクションに簡単にアクセスできるように拡張されています。

「mongo」という名前で Bean が定義されていますので、コン

トローラやサービスにインジェクションできます。
class BookService {def mongo....
}

getDB() メソッドで DB の参照を取得し、その後コレクションにGrails Plugin 探訪

第 3 回〜 MongoDB GORM プラグイン〜

23

G*Magazine vol.2■withTransaction() メソッドを使う

ドメインクラスの withTransaction() メソッドを使うことでも、トランザクション処理が行われます。部分的なトランザクション
処理やコントローラでのトランザクション処理などに使用できます。

Book.withTransaction { status ->new Book(title:'Groovy in Action',
price:5000).save()throw new RuntimeException("bad")
new Book(title:'Grails in Action',
price:5500).save()}

おわりにいろいろな NoSQL DB があり、その一つとして MongoDB が注目されています。Grails アプリケーションから MongoDB にアクセスする場合、MongoDB GORM プラグインを使ってみてはいかがでしょうか。

24 Grails Plugin 探訪 第 3 回〜 MongoDB GORM プラグイン〜

G*Magazine vol.2

リリース情報 2011.05.20
GrailsGrails は、Groovy や Hibernate などをベースとしたフルスタックの Web アプリケーションフレームワークです。
URL: http://grails.org/
バージョン : 1.2.5, 1.3.7■更新情報• 1.3.7 では、Groovy が 1.7.8 に更新されたり、スタックトレー
スログに出力されるリクエストパラメータの値をマスキング
したり、といった改良が行われています。
• 1.3.7 リリースノート :http://www.grails.org/1.3.7+Release+Notes

GroovyGroovy は、JavaVM 上で動作する動的言語です。
URL: http://groovy.codehaus.org/
バージョン : 1.7.10, 1.8.0■更新情報• 1.7.10 では、Groovydoc の子クラスで package-templates、
doc-templates、class-templates がオーバーライド可能になったり、いくつかのバグフィックスが行われています。
• 1.7.10 リリースノート : http://jira.codehaus.org/secure/
ReleaseNote.jspa?projectId=10242&version=17229• 1.8.0 では、Groovy の動的な表現力の向上や、JSON をネイティ
ブサポート、GPars ライブラリのバンドルなどが行われています。
• 1.8.0 リリースノート : http://docs.codehaus.org/display/
GROOVY/Groovy+1.8+release+notes

Griffon
Griffon は、デスクトップアプリケーションを開発するためのア
プリケーションフレームワークです。
URL: http://griffon.codehaus.org/
バージョン : 0.9.3-beata-1■更新情報• 0.9.3-beata-1 では、新しい archetype が追加されたり、依存する Groovy のバージョンが 1.8.0 に、Gant のバージョンが1.9.5 にバージョンアップされたり、いくつか改良されています。
• 0.9.3-beata-1 リリースノート : http://griffon.codehaus.org/
Griffon+0.9.3-beta-1

Gant
Gant は、XML の代わりに Groovy で Ant タスクを記述し実行する
ビルド管理ツールです。
URL: http://gant.codehaus.org/
バージョン : 1.9.5■更新情報• 1.9.5 の変更箇所は不明です。
• 1.9.5 リリースコメント : http://groovy.329449.n5.nabble.
com/Gant-1-9-5-released-2011-05-03T09-30-01-00td4366728.html

GradleGradle は、Groovy でビルドスクリプトを記述し実行するビルド管理ツールです。
URL: http://www.gradle.org/
バージョン : 0.9.2, 1.0-milestone-3■更新情報• 1.0-milestone-3 では、Ivy リポジトリの定義が簡単になった
り、新しい API が追加されたり、いくつかのバグフィックスが行われています。
• 1.0-milestone-3 リリースノート : http://wiki.gradle.org/
display/GRADLE/Gradle+1.0-milestone-3+Release+Notes

GaelykGaelyk は、Groovy で記述する Google App Engine for Java 用のライトウェイトなフレームワークです。
URL: http://gaelyk.appspot.com/
バージョン : 0.7■更新情報• 0.7 では、Groovy が 1.8.0 に、GAE SDK が 1.5 にアップグレー
ドされたり、File サービスがサポートされるようになりました。
• 0.7 リリースノート : http://gaelyk.appspot.com/download

Google App Engine SDK for Java
Google App Engine SDK for Java は、Java で Google App Engine
用の Web アプリケーションを開発するための SDK です。
URL: http://code.google.com/intl/ja/appengine/バージョン : 1.5.0■更新情報• 1.5.0 では、Backend がサポートされたり、Task キューの pull
モードがサポートされたり、いくつかのバグフィックスが行
われています。
• 1.5.0 リリースノート : http://code.google.com/p/
googleappengine/wiki/SdkForJavaReleaseNotes

GPars
GPars は、Groovy に直感的で安全な並行処理を提供するシステム
です。
URL: http://gpars.codehaus.org/
バージョン : 0.11GA、0.12-beta-1■更新情報• 0.12-beta-1 では、構成可能な非同期機能や、Active Objectが追加されました。

Groovy++Groovy++ は、Groovy 言語に対して静的な機能を拡張します。
URL: http://code.google.com/p/groovypptest/
バージョン : 0.4.243■更新情報• 0.4.243 での変更点は不明です。
• 0.4.243 リリースメッセージ : http://groups.google.com/
group/groovyplusplus/browse_thread/thread/52a7fb1dca4
3783d/632913b0785b02f8?show_docid=632913b0785b02f8

Spock
Spock は、Java や Groovy 用のテストと仕様のためのフレームワー
クです。
URL: http://code.google.com/p/spock/バージョン : 0.5

GroovyServ
GroovyServ は、Groovy 処理系をサーバとして動作させることでgroovy コマンドの起動を見た目上高速化するものです。
URL: http://kobo.github.com/groovyserv/
バージョン : 0.7

リリース情報25

G*Magazine vol.2■更新情報• 0.7 では、groovyserver の起動時に CLASSPATH 情報を表示したり (MacOS X, Linux のみ )、-server オプションを使用するようにしたり、バグフィックスがいくつか行われています。
• 0.7 チェンジログ : http://kobo.github.com/groovyserv/
changelog.html#0.7

Geb
Geb は、Groovy を使用した Web ブラウザを自動化する仕組みです。
URL: http://geb.codehaus.org/
バージョン : 0.5.1

Easyb
Easyb は、 ビ ヘ イ ビ ア 駆 動 開 発 (Behavior Driven
Development:BDD) 用のフレームワークです。
URL: http://www.easyb.org/
バージョン : 0.9.8

Gmock
Gmock は、Groovy 用のモック・フレームワークです。
URL: http://code.google.com/p/gmock/バージョン : 0.8.1

HTTPBuilder
HTTPBuilder は、HTTP ベースのリソースに簡単にアクセスするための方法です。
URL: http://groovy.codehaus.org/modules/http-builder/バージョン : 0.5.1

CodeNarc
CodeNarc は、Groovy 向けの静的コード解析ツールです。
URL: http://codenarc.sourceforge.net/
バージョン : 0.13

GMetrics
GMetrics は、Groovy ソースコードのサイズや複雑さを計算したり報告するためのツールです。
URL: http://gmetrics.sourceforge.net/
バージョン : 0.3

GContracts
GContracts は、Groovy で契約プログラミングを行うためのフレームワークです。
URL: https://github.com/andresteingress/gcontracts
バージョン : 1.2.3▼ぐるーびーたん

第１話のあらすじ

2011 年春、熊本からプログラマを目指して上京してきたぐるーびーたん。就職先のソフトウェア開発会
社（㈱ジーアスターソフト）の扉を勢いよく開けて初出社！しかし、そこには寝袋にくるまった怪しい人影が。
。
。

※この作品は、たいがいフィクションです。
実在の人物、
団体とは関係ありません。

26 リリース情報

G* Magazine vol.2 2011.05
http://www.jggug.org

発行人：日本 Grails/Groovy ユーザーグループ
編集長：川原正隆
編集：G* Magazine 編集委員（杉浦孝博、奥清隆）
デザイン：㈱ニューキャスト
表紙：川原正隆
編集協力：JGGUG 運営委員会
Mail：info@jggug.org© 2011 JGGUG 本誌に掲載されている写真、イラストレーション、および記事の無断転載、使用を禁止します。

Reproduction of any materials appearing
in this magazine is forbidden without priorwritten consent of the publisher.

Publisher：Japan Grails/Groovy User Group
Editor in Chief：Masataka Kawahara
Editors：G* Magazine Editors Team
(Takahiro Sugiura, Kiyotaka Oku)
Design：NEWCAST inc.
CoverDesign：Masataka Kawahara
Cooperation：JGGUG Steering Committee
Mail：info@jggug.org