ラベル grails の投稿を表示しています。 すべての投稿を表示
ラベル grails の投稿を表示しています。 すべての投稿を表示

2010年9月13日月曜日

Acegiプラグインでprincipalをリフレッシュする方法

久々にブログに書くネタが出来たので、備忘録的にメモ。

GrailsのAcegiプラグインを使って認証処理を行ったとき、ログイン中に更新されたユーザ情報はSecurityContextのprincipalとかには更新されなかったりする。
恐らくセッション上に抱えてるユーザ情報はそのままキャッシュに残ってるので、どうにかしてこの情報を更新したいんだけれども、やり方がわからない。
で、google先生に教えを乞うて海外サイトを色々探した結果、こんな記事を発見。

http://blog.lourish.com/2010/03/10/updating-the-logged-in-user-with-acegispring-security-in-grails/

「Refresh the Authentication Token」…おおっ、これだこれ。

方法としては、ようするに認証済みのAuthenticationTokenを作ってSecurityContextにぶち込んでるらしい。…いいのか、これ?
自分の環境でも試してみたけど、とりあえずは動いてる。いい…のか?

まあ、他の方法としてはSecurityConfig.groovyのcacheUsersをfalseにするとかというのもあるらしい。
…まあ、キャッシュ切ればそりゃ勝手に更新されるわな。

2010年6月19日土曜日

Grailsのprojection項目にaliasを設定する

GrailsのCriteria使ってて、「あれ、これ集計項目に対してソートかけたい場合とかどうすんだ?」という問題にひっかかった。
とりあえず調べてみたところ、Hibernateにaliasという属性があって、それを設定するとソートとか出来るようになるらしい。SQLでいうところのMAX(foo) as varみたいなもんか。
じゃあ、そいつをGrailsでやるのはどうするのか? あーでもない、こうでもないと試行錯誤した結果、結論してはどうってことない、こんだけでおkだった。

projection {
max("foo", "bar")
}


ようするにメソッドの最後の引数にエイリアス名指定してやればよかっただけという。
maxでしか試してないけど、多分他のも同じ要領で設定できると思われる。
ドキュメントにもGrails徹底入門にも載ってないから微妙に焦った。…載ってないよね?
まあ、どっかしらで使う機能だし、きっと常識なんだろうけど一応備忘録として残しておく。

2010年5月25日火曜日

flowアクション内でflushスコープの変数にアクセスするとき

flowのアクション中でメッセージを埋め込もうとして、

flash.message = "hogehoge"

とやっておいて、結果のgspで

${flash.message}

とやったところ、何故かメッセージが表示されないという問題にハマる。
小一時間ほど頭を抱えたところ、どうやらセットするときにこうするといけるらしい。

this.flash.message = "hogehoge"

…わかるかい、そんなもん!!

2010年4月4日日曜日

日本語コメントを入れると何故か(ry、再び。

しばらく鳴りを潜めていた例のエラーがまた出始めた。
ソースファイルのエンコードについては確認済。UTF-8でBOMはなし。
今度はpackage-plugin。テストとかrun-appでは動くくせに、package-pluginしようとするとエラーを吐く。
今回出たエラーはこんな感じ(長いので途中で省略)。

Running script C:\grails-1.2.1\scripts\PackagePlugin_.groovy
Environment set to development
[echo] Compiling plugin descriptor...
startup failed, D:\work\grails\es-common-mail\EsCommonMailGrailsPlugin.groovy: 193: unexpected token: } @ line 193, column 1.
}
^

1 error

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed,
D:\work\flack\grails\es-common-mail\EsCommonMailGrailsPlugin.groovy: 193: unexpected token: } @ line 193, column 1.
}
^

1 error

at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:296)
at org.codehaus.groovy.control.ErrorCollector.addFatalError(ErrorCollector.java:143)
at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:113)
at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:125)
at org.codehaus.groovy.control.SourceUnit.addError(SourceUnit.java:353)
at org.codehaus.groovy.antlr.AntlrParserPlugin.transformCSTIntoAST(AntlrParserPlugin.java:96)
at org.codehaus.groovy.antlr.AntlrParserPlugin.parseCST(AntlrParserPlugin.java:63)
at org.codehaus.groovy.control.SourceUnit.parse(SourceUnit.java:249)
at org.codehaus.groovy.control.CompilationUnit$1.call(CompilationUnit.java:163)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:820)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:513)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:489)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:466)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:279)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:250)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:189)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

 :
 :
 :

Error executing script PackagePlugin: : Cannot instantiate plugin file
gant.TargetExecutionException: : Cannot instantiate plugin file
at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:331)
at gant.Gant$_dispatch_closure6.doCall(Gant.groovy:334)
at gant.Gant$_dispatch_closure6.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:344)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:334)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.processTargets(Gant.groovy:495)
at gant.Gant.processTargets(Gant.groovy:480)
Caused by: : Cannot instantiate plugin file
at org.apache.tools.ant.taskdefs.Exit.execute(Exit.java:142)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at _PluginDependencies_groovy$_run_closure7.doCall(_PluginDependencies_groovy:472)
at _PluginDependencies_groovy$_run_closure7.call(_PluginDependencies_groovy)
at _GrailsPluginDev_groovy$_run_closure1.doCall(_GrailsPluginDev_groovy:78)
at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:324)
... 10 more
Error executing script PackagePlugin: : Cannot instantiate plugin file


unexpected tokenとあるけど、かっこの閉じ忘れとかではない。
今回も日本語のコメント末尾に半角スペースとか入れると再現しなくなる。
対処法としては、コメント末尾に必ず半角スペースを入れる、コメントを//で書かずに/* */で書く(両端に半角SP入れる)、そもそも日本語でコメント書かないといったところか。…うわ、何そのバッドノウハウ。

これ、どうもスクリプト実行周り(自作スクリプトとか、package-pluginとか)でコンパイルやったときにのみ再現してるっぽいんだよなぁ…やっぱバグ?
でも、他でこの現象発生したって話は聞いたことないんだよなぁ…割と致命的な現象っぽいから、本当にバグなら話題に昇っててもおかしくなさげなんだけれども。
そう考えると、バグではなくこっちの設定不備という可能性も。…でも、そんな変なことやってないはずなんだけどなぁ…。

Config.groovyとか

ConfigSlurper使ってる系統のConfigファイルに日本語混じってるとコケるくさい。
n2aせよと…? や、まあ確かに納得はするんだが。
メッセージリソースは横着してConfigに埋めるんじゃなく、messageで持てってことかなぁ…。

2010年4月1日木曜日

grails scriptに日本語のコメントを入れると落ちる件

プラグイン作成に手を出してたりします。
あんな機能やこんな機能を分離できたりして楽しげ。後々他でも使えそうな機能はプラグイン化しとくと役に立つかも…などと思い、色々試してるところ。
そんな中で起きたトラブル。自作のコマンドを作るためにスクリプトをいじってたところ、何故かエラー。何もないのにエラー。
Error executing script CreateMail: No such property: name for class: CreateMail
gant.TargetMissingPropertyException: No such property: name for class: CreateMa
l
at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:329)
at gant.Gant$_dispatch_closure6.doCall(Gant.groovy:334)
at gant.Gant$_dispatch_closure6.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:344)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:334)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.processTargets(Gant.groovy:495)
at gant.Gant.processTargets(Gant.groovy:480)
Caused by: groovy.lang.MissingPropertyException: No such property: name for cla
s: CreateMail
at CreateMail$_run_closure1.doCall(CreateMail:15)
at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:324)
... 10 more
Error executing script CreateMail: No such property: name for class: CreateMail

一体全体何が起きてるんだ? と、試行錯誤すること1時間強。出た結論としては、どうやらスクリプト中に入力していたコメントが問題だったらしい。
//コメでコメント末尾が全角だとエラーになるらしい。バグなのかな、これ…。
※/* */でも再現。どうやらコメント末尾が全角だとスクリプトの翻訳でコケてるくさい。

こんな感じ。
×:// そんなに日本語が嫌いか!!
※末尾に半角スペースくっつけてやると通るっぽい?
○:// そんなに日本語が嫌いか!!a
×:/*そんなに日本語が嫌いか!!*/

2010年3月26日金曜日

datePickerでありえない日付を入力すると…

日付が繰り上がるのね。
内部でGregorianCalendar使ってるからかな…ヤな動きするなぁ。

message.propertiesでカスタムエラーメッセージを設定するとき

not null制約のエラーメッセージをカスタマイズしようとしたところ、上手くいかない。
ぐぬぬ、何故に…と思いきや、こういうことだったらしい。

registerInputクラスのaddressでnullable制約がひっかかったとき:
×registerInput.address.null=住所を選択してください。
○registerInput.address.nullable=住所を選択してください。

デフォルトのメッセージキーがdefault.null.messageだったから、てっきりnullかと思ってたよ…。
制約名がキーになるのね、納得した。
こんなしょうもないことで1時間以上も費やした罠…。

2010年3月18日木曜日

scaffoldのレイアウトをいじる際の注意

scaffoldの生成する動的なgspをいじるべなーってことで、「grails install-templates」して、gspにスタイルシートを仕込もうとしたところ、何故か404に。
はてな…と思い、コンソールを見ると、何故かException吐いてる。

2010-03-18 22:54:25,910 [http-8080-1] ERROR view.ScaffoldingViewResolver - Erro
r generating scaffolded view [/sex/create]: No signature of method: SimpleTempla
teScript5.resource() is applicable for argument types: (java.util.LinkedHashMap)
values: [[dir:css/all, file:scaffold.css]]
groovy.lang.MissingMethodException: No signature of method: SimpleTemplateScript
5.resource() is applicable for argument types: (java.util.LinkedHashMap) values:
[[dir:css/all, file:scaffold.css]]
at SimpleTemplateScript5.run(SimpleTemplateScript5.groovy:13)
at java.lang.Thread.run(Thread.java:619)


何か、css読ませるためにresource読んだらそこでコケたらしい。
色々調べてみたところ、こんな記事を発見。

Change scaffolding templates in Grails - Messages from mrhaki
http://mrhaki.blogspot.com/2009/07/change-scaffolding-templates-in-grails.html
何でも、scaffold用のgspを生成しているテンプレートエンジン内で、$を記号として使っているらしく、$を使うときは\でエスケープしてやる必要があるそうな。
そらわからんわ…。

てか、struts2のときもそうだったけど、この手の問題を解決しようとすると、どうしても英語のサイトに頼らざるを得なくなるなぁ…。

2010年3月17日水曜日

gspで現在のコントローラを取得したい場合

${webRequest.controllerName}で取得できた。…これでいいのかしらん?

しかし、gspのtaglib生成簡単すぎる…調子に乗って作りすぎる罠にでもハマりそうな勢いだ。
これ知ると他のフレームワークに戻れそうにないなぁ…。

2010年3月14日日曜日

Grails1.2.1でwebflowが使えない?

webflowを使ったcontrollerを作ってみようとして、試しに動かしてみたところ、何故か「そんなアクション定義されてねーよ」と404エラーで怒られる。
何か設定がマズいんだろうかと思って色々試してみるもNG。

それならば…と思い、参考にしているGrails徹底入門のサンプルソースを読み込ませてみると、それもNG。

サンプルで使っているGrailsのバージョンは1.0.3で、自分が使っているバージョンは1.2.1。
その間に何かしら仕様でも変わったんだろうかと思い、色々調べてみたところ、こんな記事を発見(というか、公式ページだけど)。

Grails - WebFlow
http://www.grails.org/WebFlow

Since of Grails 1.2 the WebFlow plugin is not installed by default (see GRAILS-5185).
Use 'grails install-plugin webflow' to install the plugin and enable this feature.


どうやら、現バージョンのGrailsではwebflowが最初からインストールされていないので、使いたければ自分で入れてねってことらしい。
プラグイン自体はインストールしたディレクトリにあるので、「grails install-plugin webflow」してやると無事動作。
現状で出てる解説書(自分が持ってるのはGrails徹底入門とはじめてのGrailsって本)だと書いてないので、微妙にハマりどころな気が…。

2010年3月12日金曜日

UnitTestでダイナミックメソッドを使う

DomainClassdでValidationのテストをやろうと思ったら、「んなメソッドねーよ」って怒られた。本じゃやってるのに! …と思ってよくよく見たら、UTじゃなくてITだった。
UTだとDomainClassでメソッドがInjectionされないらしい。うむむ、どうしたもんか。
…と思ったら、mockForConstraintsTestsというGrailsUnitTestCaseのメソッドで、そこら片のメソッドをInjectionしてくれるらしい。
ソースは↓。

Grails をマスターする: Grails によるモック・テスト
http://www.ibm.com/developerworks/jp/java/library/j-grails10209/

2010年3月11日木曜日

DomainClassで書き込みさせたくない項目を設定するには?

Grails をマスターする: Grails サービスと Google Maps
http://www.ibm.com/developerworks/jp/java/library/j-grails05208/

上の記事を見てて疑問に思ったこと。
AirportDomainClassの作成をページ上で行わせる際、iataとcity以外は触らせたくないため、gspをいじって編集できないようにしている。
「def airport = new Airport(params + results)」とあるので、params(POSTされたプロパティ)とresult(サーバ側で作られたプロパティ)をかけ合わせてbeanを作ってると思われる。
…ん? でもそれって、意図的に変なデータをPOSTすると(POSTパラメータ上でname指定したり)、結局値が上書きされちゃうんじゃ? それ、色々とヤバくね?

とか思って、しげしげとソースを眺めてみること数分。
あーこれ、足した順番で結果変わったりするのか? と思い立ったので、実験。

・Fooドメインクラスを作成、フィールドにbarを設定。
・grails generate-allでControllerとViewを作る。
・Controllerのsaveクロージャでsaveする前に以下の記述を追加。

def prop = [bar:"overwrite!"]

fooInstance.properties = params + prop

・上記の場合、保存時のbarは"overwrite!"になる(POST時のパラメータは無効)。

・↑の記述を以下に変更。

def prop = [bar:"overwrite!"]

fooInstance.properties = prop + params

・上記の場合は、保存時のbarはPOSTした値になる。

ようするに、addした順番でmapの内容が上書きされていってると判断。まあ、map.put("bar", "overwrite!")とか順番にやってると考えれば当然のことか。納得した。

grails始めました。

とりあえず、flex部分の作成が一区切り付いたので、アプリケーションのメイン部分をStruts2からgrailsへ移行すべく、色々調べながら始めてみることに。
とりあえずは本とかネットの記事とか見て、色々試してるところ。
確かにコードの記述量は減るけど、いかんせん慣れてないせいでどう進めていいものやらさっぱり。ひとまずは一画面分機能作ってみないことには何ともならんなぁ。