2007年6月10日日曜日

delete won't work for test env.

ありゃりゃ. 困ったもんだな.

test 環境だとどうもドメイン・オブジェクトの delete() がまったく効いていない模様...



MacOSX 10.4.9 / Java 1.5.0_07 / Grails 0.5



WicketBuilder

さて, いよいよ Wicket Builder を作らねばならぬか, と腰を上げかけて, もしやと思い直して探してみると, あ~るじゃありませんか, Wicket Builder.



http://wicketstuff.org/confluence/display/STUFFWIKI/WicketBuilder

http://bigheadco.blogspot.com/2007/03/wicket-and-groovy.html



しかし, SourceForge を見に行っても, 肝心の wicket-1.3 というブランチは存在しない模様... orz.



しばらく待ちますか...



2007年5月30日水曜日

grail-0.5 bookmarks

杉浦さん@それなりの日記の記事に付け加えて...



grails-0.5 の例題として付いてくる bookmarks を動かすには, 以下のプラグイン



  • http://grails.org/XFire+Plugin


  • http://sky.geocities.jp/acegiongrails/

をインストールする必要があるみたい (acegi は grails-0.5+ 対応版). それぞれのプラグイン (.zip) をダウンロードしたら,



% cd .../bookmarks

% grails install-plugin .../grails-xfire-0.5.zip

% grails install-plugin .../grails-Acegi-0.1.zip



すると, run-app できるようになる (それでもなんだか例外を吐いているようだけど:-)



grails-0.5 では 今までの domain-class と同じように hibernate annotation を処理できるようだ (実際ちゃんと永続化されているように見える). ただしそのためには, Java でアノテーション付きのコードを書かないといけない (.../src/java/org/grails/*.java). もっともアノテーションの処理は hibernate に任せているようで, grails のコードにはない.

SS2007

えーと, 告知です...



6 月 27日 (水) から 29日 (金) の三日間にわたって, 新潟市朱鷺メッセで「ソフトウェア・シンポジウム 2007」が開かれます.



初日 27 日に不肖山田が, 2 時間程度のチュートリアル「日常会話的モデル駆動開発 (Groovy/Grails を使ってみる) 」をやることになっています.



中日 28 日は各ワークショップに分かれて一日中議論を行います. 山田はモデリング・ワークショップに参加します.



参加受付は http://www.sea.jp/Events/symposium/ss2007/ss2007cfp.html, 詳細は SS2007 Portal をご覧ください.



日々の業務の中で何か納得のいかないものを抱えている方, このまま行ったらこの業界先はないぞと考えている方, あんまり大きな声では言えないこんな面白い話があるんだけどさという方, どなた様も参加をお待ちしています.



2007年5月29日火曜日

GrailsPlugin のプロパティ

GrailsPlugin のプロパティを GrailsPlugin.java からまとめておく. ただしドキュメントとは幾分異なっている. 5.5 辺りで実装される予定らしい.




doWithDynamicMethods


実行時にメソッドを inject するために呼ばれるクロージャ.


watchedResources


このプラグインが変化を監視するリソース.


evict


このプラグインが立ち退かせるプラグインのリスト. 立ち退きは PluginManager がロードするときに行われる.


status


このプラグインの状態. "enabled" (ロードされる), "disabled" (ロードされない)


influences


このプラグインが影響を与えるプラグインのリスト. 監視しているリソースが変化すると, 影響を及ぼすプラグインは refresh() される.


onChange


監視しているリソースが変化したときに呼ばれるクロージャ.


doWithWebDescriptor


web.xml の作成時に呼ばれるクロージャ.


version


このプラグインのバージョン.


doWithSpring


Spring の実行時コンフィギュレーションが行われるときに呼ばれるクロージャ.


doWithApplicationContext


初期化が終わり, アプリケーション・コンテキストが確立したときに呼ばれるクロージャ.


dependsOn


このプラグインが依存している他のプラグイン.


artefacts


このプラグインがサポートする ArtefactHandler のリスト.

このほかにも予定されているが, grails-0.5 では実装されていないプロパティがかなりあるようだ.

grails-wicket plugin を読む (3)

さて, メタオブジェクトの迷宮からようやく戻ってきた. 残りは wicket を動かすための手続きを grails のコードとして書いているだけだ. WicketGrailsPlugin.groovy に戻ろう.



def doWithSpring = {

def applicationClass = application.allClasses.find { Application.class.isAssignableFrom(it) }



if(applicationClass) {

applicationBean(applicationClass)

}

}




applicationGrailsApplication だということが分かった. そうするとここには「この Grails アプリケーションが持つ (ロードした) すべてのクラスの中で wicket.Application クラスと (ほぼ) 同じクラスがあれば, それを applicationBean としてインスタンス化する (ここで Spring Bean Builder を使っている)」と書いてあることになる. その「wicket.Application クラスと (ほぼ) 同じクラス」というのが, grails-app/controllers/WebApplication.groovy なわけだ.



def doWithWebDescriptor = { xml ->

def servlets = xml.servlet[0]

servlets + {

servlet {

'servlet-name'('wicket')

'servlet-class'('wicket.protocol.http.WicketServlet')

'init-param' {

'param-name'('applicationFactoryClassName')

'param-value'('wicket.spring.SpringWebApplicationFactory')

}

'load-on-startup'(1)

}

}



def mappings = xml.'servlet-mapping'[0]

mappings + {

'servlet-mapping' {

'servlet-name'('wicket')

'url-pattern'('/app/*')

}

}

}




doWithWebDescriptor は (アプリケーション起動時に Grails によって動的に作られる) web-app/WEB-INF/web.xml に関するクロージャ. web.xml の作成時に呼び出され, web.xml に以下を付け加える.



<servlet>

<servlet-name>wicket</servlet-name>

<servlet-class>wicket.protocol.http.WicketServlet</servlet-class>

<init-param>

<param-name>applicationFactoryClassName</param-name>

<param-value>wicket.spring.SpringWebApplicationFactory</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>



<servlet-mapping>

<servlet-name>wicket</servlet-name>

<url-pattern>/app/*</url-pattern>

</servlet-mapping>


こんなくそ XML を書かずに済んでいるのは Groovy の Markup Builder のおかげだ.



で, この plugin がやっているのはこれだけ. つまり普通の J2EE アプリケーションで Wicket を使うときにやる設定の手続きを WicketGrailsPlugin.groovy に書いているのだ. 後は grails の枠組み (特に GORM) がすべてそのまま使えている.



よくできました.



grails-wicket plugin を読む (2)

2回目. ここでは実は "Convention over Configuration" の実態が実は, grails がインタプリタ (メタオブジェクト) の集合になっていることだというのが分かる. ではいってみよう...



プラグイン定義クラスの規約を決めているやつは, 実はここにいる.



org.codehaus.groovy.grails.plugins.GrailsPlugin



Java インタフェースだが, スーパーインタフェースは Spring Framework の中にある ApplicationContextAware. ApplicationContextAware を実装するクラスは Spring Framework の恩恵を得ることができる, ととりあえずは思っておく.



GrailsPlugin には「規約」に相当する (≒ Java Interface に相当する), つまりプラグイン定義クラスで def すべきプロパティが文字列として定義されている. 例えば



String DO_WITH_DYNAMIC_METHODS = doWithDynamicMethods;

String WATCHED_RESOURCES = watchedResources;

String EVICT = evict;

// ......




また実装クラスはそれらプロパティへのアクセッサを定義しなさい, となっている. 例えば



void doWithWebDescriptor(GPathResult webXml);

String getName();

String getVersion();

// .......




つまり GrailsPlugin の実装クラスは, プラグイン定義クラスのインタプリタなのだ!



GrailsPlugin を実装しているのは



org.codehaus.groovy.grails.plugins.AbstractGrailsPlugin



で, つまりプラグイン定義クラスのインタプリタのひな形というわけ. これはさらに AbstractGrailsClass のサブクラスになっている. AbstractGrailsClass は Grails 全体で使われる汎用インタプリタのひな形だ. AbstractGrailsClass のサブクラスには他に DefaultGrailsDomainClass などがあるが, これはドメイン・クラス定義クラスのインタプリタということになる.



org.codehaus.groovy.grails.plugins.DefaultGrailsPlugin



AbstractGrailsPlugin を具体化したもの, つまりデフォルトのプラグイン定義クラス・インタプリタと言える. この中身を見てみると, new するときには対象となるプラグイン定義クラス (例えば WicketGrailsPlugin) が渡される. これがつまりインタプリタに与えられるプログラムということになる. このプログラムのシンタックスは前述の GrailsPlugin が決めているわけだ.



だから, プラグイン定義クラスに定義されていない変数 application が出現したとしても, それをどうするかはインタプリタの都合次第ということになる. インタプリタの中を見てみると application という変数には GrailsApplication が入っている (doWithRuntimeConfiguration() メソッド内). 他にもこのクロージャの中では manager, plugin, parentCtx, resolver という変数が使えることが分かる.



GrailsApplication は多分 Grails アプリケーションのファサードだろうと想像がつく. けど, これが実際にどんな変数とメソッドを持っているかは, GrailsApplication の JavaDoc のようなドキュメントかソース・コードを見ないと分からない. そこが Grails の弱点だとは思う. つまりインタプリタの世界 (Java) とプログラムの世界 (Groovy/Grails) が分離している. だから何かしようと思うと二つの世界を行ったり来たりしなければならないことになる. Lisp や Smalltalk だとこの二つの世界は同じ言語で記述され, かつ優秀な開発/デバグ環境が存在するのだが...



ちなみにここで「インタプリタ」と呼んでいるものは「メタオブジェクト」と呼び変えてもよい. オブジェクトの挙動を決めているオブジェクトだから.



続く...