2009年7月1日水曜日

simple groovy code reading - import

Javaではjava.langだけはimportしなくても使えることになっています (デフォルト・パッケージ) が, それ以外はいっぱいimportしなければなりません. 特定の機能を実現するパッケージをimportで指定するのはいいとして, java.utilのような基本的な機能までいちいちimportしなければならないのは, 納得がいきませんよね.


Groovyでは



  • java.util.*


  • java.io.*


  • java.net.*


  • groovy.lang.*


  • groovy.util.*


  • BigInteger


  • BigDecimal


がデフォルトでimportされます. これはもちろんスクリプト言語として, 普通に使うものはimportせずに済むようになっているわけです.


では, simple groovy code readingの一発目として, どこでこれらがimportされているのか調べてみると...


パッケージに関しては, org.codehaus.groovy.control.ResolveVisitorにDEFAULT_IMPORTSとして定義されています. さらにこれがどこで使われているかを見ると, 同じクラスのresolveFromDefaultImports()で, 具体的なクラス・ノードがどのデフォルト・パッケージに含まれているかを調べています. BigInteger, BigDecimalについてもここで扱っています.


DEFAULT_IMPORTSはpublicなので外から見ることができます. ただしfinalなので, デフォルト・パッケージを勝手に追加することは, 残念ながらできません:-)



2009年6月23日火曜日

WebFlowTestCaseが変わったらしい

どうやらgrails-1.1からWebFlowTestCaseが変わったらしい. なので「Grails徹底入門」のWebFlowのテストはもう古い.


でも grails.orgの記述もアップデートされてない! 1.1.1のオンラインのuser guideのみ, こそこそ消してあるぜ:-)


新しいWebFlowTestCaseは次のようになっています.


startFlow()


対象flowの最初の状態をトリガする. 前はこれでViewSelectionが戻っていたけど, 今はvoid.


signalEvent(String)


対象flowにイベントを送る. startFlowと同様, 今やViewSelectionは返されない (ExternalContextを返す).


getFlowDefinition()


対象flowの定義を得る.


setCurrentState(String)


新しいflowを開始し, 指定した状態に遷移する.


getFlowScope()


現在のflow scopeを得る.


getConversationScope()


現在のconversation scopeを得る.


ViewSelectionを直接扱う代わりに, assertXXXの中に隠蔽されています.


assertCurrentStateEquals(String)


flowが実行中で, 現在の状態の名前が引数に等しい.


assertFlowExecutionActive()


flowが実行中 (まだ end 状態に達していない).


assertFlowExecutionEnded()


flowが終了 (既に end 状態に達している).


assertFlowExecutionOutcomeEquals(String)


flowが終了しており, その end 状態の名前が引数に等しい.


新しいWebFlowTestCase APIに関しては, Grails in Actionの9.4が詳しい.



2008年12月3日水曜日

Groovy Magazine 2008 年 12 月号 (通巻 2 号)

今号は 36 ページ $5. ご注文はこちらから.


素の PDF にコード例が付いてきます.



  1. Grails で iUI という AJAX ライブラリを使って, iPhone 用 Web アプリを作る (Grails プロジェクト付き)


  2. Groovy でリッチな Swing アプリを作る パートII


  3. GORM の解説記事


  4. contentsieve.com, addsieve.com というサイトを運営しているMetaSieveの人へのインタビュ


  5. Plugin Corner の話題は Grails Testing Plugin


  6. コミュニティ・ニューズ



2008年11月4日火曜日

Groovy Magazine創刊

(groovy と grails 開発者のための) Groovy Magazine が創刊されました.

http://www.groovymag.com/

有料 ($5.00) のオンライン・マガジンです. 英語ですけど. 登録したメイル・アドレスがテキストとして各ページの片隅に埋め込まれます. 記事中のサンプル・コードなどはテキスト・ファイルとして同梱されています.


創刊 11 月号 (31ページ) の目次はこんなんです.



  1. コミュニティ・ニューズ (2 ページ)


  2. Grails ってなんだろう (10 ページ) 入門記事


  3. Groovy でリッチな Swing アプリを作る パートI (8 ページ) 入門記事


  4. Groovy ユーザーズ・グループ一覧


  5. Java の未来は Groovy にあり (6 ページ) コラム/解説


  6. プラグイン・コーナー (2 ページ) Searchable Plugin について


  7. 野生の Groovy (2 ページ) インタビュー, minggl.com の人

2008年5月30日金曜日

惜しいリスト

Groovy は関数型言語のようにリストを扱えるようにはなっている. しかし惜しい...

例えば, [1,2,3] と [4,5,6] という二つのリストをマージして, [[1,4] ,[2,5] ,[3,6]] というようなリストを作りたいとする (変態なマージだけど).

普通に考えるとこんな感じになる.

def merge = { x, y, r = [] -> x == [] ? r : merge(x-x[0], y-y[0], r+[[x[0] , y[0]]]) }

まぁ記法がいいかどうかは別として, 意味は分かると思う. ところが Groovy1.5 でこれは動かないのだ. merge の定義中に再帰的に現れる merge を理解できないのだ. そこで次のようにすれば動く.

def merge; merge = { x, y, r = [] -> x == [] ? r : merge(x-x[0], y-y[0], r+[[x[0], y[0]]]) }

馬鹿でしょ. ま, いいけど.

メモ代わりに残しておく.

2008年5月13日火曜日

プラグインをテストする

Grails ではプラグインは強力な仕組みだけど, テストが難しい (場合がある). 特にアーティファクトのダイナミック・プロパティに依存するようなものはテストしにくい.

ここではごく簡単に, Controller に定義された特定のプロパティの値で振る舞いを変えるようなプラグインを考えてみる.

このようなプラグインをテストする最も簡単な方法は, テスト用のコントローラを定義して, ./grails-app/controllers/ の下に置き, integration test を実行することだ. でも, この方法だとテスト用のコントローラがプラグインのインストールを通してアプリケーションに入り込んでしまう. package-plugin 時に注意深くテスト用のコントローラを取り除くという手もなくはないけど, これは避けたい.

またテスト本来の目的からするとテスト用のコントローラがテストの外にファイルの形で存在するのは本当は嬉しくない. じゃあ, テストの中に定義してしまえということになる.

def gcl = new groovy.lang.GroovyClassLoader()

void setUp() {

    gcl.parseClass(

'''

class TestController {

    def action1 = { render "action1 called" }

}

'''

    )

}

このようにすると, テスト用のコントローラの定義もテスト・コード中に入れることが出来る. が, 残念なことにこのままでは TestController はコントローラ・アーティファクトとして認識されないので, 例えば render などというダイナミック・プロパティは注入されない.

そこで次の手は, こうやって書いたコントローラも正しいコントローラ・アーティファクトとして無理矢理認識させる方法だ. 実際, grails 本体のテスト・コードを見ると, このようなテストのための GroovyTestCase として, org.codehaus.groovy.grails.web.servlet.mvc.AbstractGrailsContollerTests がある. ただし, AbstractGrailsControllerTests は Test モジュールに入っているので, 普通の grails アプリケーションやプラグインからはアクセスできない.

じゃあ, このクラスをファイルごと自分のプロジェクトにコピーしてしまえ! (grails-1.0.2/test/groovy/org/codehaus/groovy/grails/web/servlet/mvc/AbstractGrailsControllerTests.groovy) 実はもう一つのクラス, MockGrailsPluginManager も必要になる. これも同じようにコピーしてくる (grails-1.0.2/test/commons/org/codehaus/groovy/grails/plugins/MockGrailsPluginManager.java). 置き場所は例えば test/integration 辺りでよい (パッケージに合わせてディレクトリを掘らなくてもよい). ただし, AbstractGrailsControllerTests の最初の import 文 (import org.codehaus.groovy.grails.commons.test.*) はエラーを起こすのでコメントアウトしておく必要がある.

で, さっきのようなテスト・クラスは

  • GroovyTestCase の直接のサブクラスではなく, 上記 AbstractGrailsControllerTests のサブクラスとする
  • 今まで setUp に書いていたようなことは onSetUp に書くようにする
  • 自分自身 (テスト対象のプラグイン) を AbstractGrailsControllerTests の setUp 中の dependantPluginClasses に追加しておく (例えば dependantPluginClasses <<>

すると, 上記 TestController はちゃんとコントローラ・アーティファクトとして認識されるようになる. つまり, render などが使えるようになる.

でもまだまだ残念なのだ. この Mock 環境では例えば Filter などはちゃんと (つまり run-app するのと同じようには) セットアップされないようなのである. つまり Filter にも何か追加しているようなプラグインのテストはやっぱり出来ない... (これは最初の方法でやっても結局同じ).

結局 webtest でもするしかないのである. この結論を得るためにどれだけ回り道をしたことか.

注:

最初の手法 (テストの外でコントローラを定義する) でもう少しマシなやり方もある. テスト・コントローラを正式な contollers ディレクトリではなく, test/integration/controllers 辺りに置くのである. その代わり, GrailsPlugin 定義の中で, watchedResources と onChange にも手を入れなければならないけど. このままプラグインをパッケージしても, まぁ許されるんじゃないか...?

2008年3月1日土曜日

grailsとspringframework

Grails はある意味では, (巨大で複雑な) springframework (今やlightweightとは言いにくいよなぁ) の wrapper という側面がある. Grails をある程度突っ込んでいくと, springframework に触れざるを得ない. とは言え, springframework をまるごと学習するのは大変だ.


ということで, (本を書く都合もあって:-) Grails が springframework のどの部分を使っているか, Grails を使うに当たって springframework のどの部分が分かっていればいいか, ざっと調べてみた.


例えばspring のリファレンス・マニュアル (2.5.1) でいうと,


3. The IoC Container の特に 3.8 まで


4. Resources の全体


5. Validation , Data-binding, the BeanWrapper, and PropertyEditors の全体


9. Transaction management の 9.4 までと, 9.6


12. Object Relational Mapping (ORM) data access の 12.2, 7


13. Web MVC framework の 13.9, 12, 13 以外


Grails で使われている Spring の機能はざっとこんなところだと思う. 細かく言うと, ユーティリティ的なものとかもあるし, 見落としているのもあるかもしれないし, もしかしたら以下も見ておくといいかもしれないが,


7. Spring AOP API の一部


11. Data access using JDBC の一部


ま, こんなもんだろう. とは言え, 600 ページ近いリファレンスの 1/4 くらいに相当するかな? もちろん普通に使っている分には, これ全部知っている必要はないのだが.


# ここには別パッケージになっている WebFlow や, プラグインになっている Acegi Security, Quartz などに関連する部分は含んでいない