ゴミ箱.net

汚物は消毒

またStruts2のバグ踏んだ

ついでにもう1つStruts 2のバグを踏んだ。

[#WW-4184] When a getter of an action calls getText("getterName.something"), method call stack overflow occurs - ASF JIRA

アクションクラスにgetterを用意し、その中でメソッドgetTextを呼び出す。
そのとき、getTextのパラメータとして「getterの名前.○○」を指定する。

public class HogeAction extends ActionSupport {
public String getPiyo(){
return getText("piyo.fuga");
}
}

また、アクションクラスと同名のプロパティファイルを用意し、「getterの名前.○○」をキーとする値が存在しないようにしておく。

このとき、JSPファイルからこのgetterを参照しようとすると無限再帰呼び出しが発生してスタックがオーバーフローする。
しかも<s:debug>タグを入れると例外が発生してデバッグできなくなってしまう。

このバグを踏むのはなかなかのレアケースだと思うが、レアなバグにはまる人間はまれによくいる。ちょうどここに1人。
万が一踏んでしまったらgetterの名前かgetTextの引数のどちらかを変えましょう。

スポンサーサイト

PageTop

Struts2のバグ踏んだ

ウェブアプリケーションフレームワークのStruts 2を使っててバグに出くわしたので報告してみた。

[#WW-4167] Unable to create a custom validator inheriting IntRangeFieldValidator - ASF JIRA

Struts 2には入力値をチェックする仕組みとしてバリデータというものがあり、最初から用意されているもの以外に独自に作成することもできる。
整数値の入力値の最大・最小値をチェックするためのバリデータとしてIntRangeFieldValidatorというのが用意されているが、それを継承して独自のバリデータを作ろうとしたところ、なぜか動作しない。

どうやらIntRangeFieldValidatorの基底クラスでgetter、setterの型が型パラメータで指定されているのが悪いらしい。基底クラスの直接の派生クラスでは問題ないが、間接的に継承している場合にsetterに値がきちんと渡されないようだ。

回避策としては、IntRangeFieldValidatorを継承しないようにするか、継承するときは型パラメータを使ったgetterとsetter(getMin, setMin, getMax, setMan)をオーバーライドしましょう(実装は基底クラスのメソッドを呼び出すだけでおk)。

PageTop

Struts 2でeval関数もどきを実現するウルテク

Struts 2はOGNL を式解析器として利用することで、異様に柔軟なページ作成を可能にしている。

たとえばJSPをビュートして用いる場合、JSPファイルに以下のようなタグを書く。(JSPの先頭で<%@ taglib prefix="s" uri="/struts-tags" %>のようにディレクティブを定義しておいてね。)

<s:property value="hoge * 2" />

このように書くと、ビューを呼び出したアクションのクラスに定義されたメソッドgetHoge()を呼び出してその値を取得し、その値の2倍をタグの箇所に勝手に埋め込んでくれる。getHoge()の戻り値が3ならば、タグの箇所に「6」と記載される。
ここで、計算式そのものはただの文字列であり、事前にコンパイルされたものではないことに注意。OGNLに式の文字列を渡すことで式を実行時に解析して計算してくれているのだ。
この仕組みによって、Struts 2はビューにある程度の処理を組み込むことができるようになっており、本当のロジックに表示のためだけの煩雑な処理をあまり入れなくてすむようになっている。

ただ、この式そのものを実行時に組み立てることは、普通はできない。JSPタグの属性として事前にハードコーディングする必要があるのだ。
アクションのクラスに定義した文字列を返すgetterや、Struts 2のタグ<s:set>などにより、変数として文字列を与えても、与えた文字列がそのまま表示されるだけで文字列を式として評価させることはできない。
EL式を使って逃げようと思っても、Struts 2のタグは普通のJSPライブラリのタグと違い、EL式を一切受け付けません。(${変数名}のようなEL式を含めるとエラーになる。)
JavaScriptのeval関数のように、動的に組み立てた文字列を式として評価することがどうしてもできないのだ。必要なことはあまりないが、まれにこのような処理がどうしても必要なことがあって非常に困る。
これもフレームワークのサガか…

…とここで終わるのが凡人の悲しいサガ。Strutsを極めればこの程度のことなど造作もない。

続きを読む

PageTop

このStruts 2すごいよ~!さすがStruts 1の弟さぁぁぁん!!

Javaでウェブアプリを開発するのにStruts 2を使っているが、異常な柔軟性にワロタ。

対抗馬としてJavaServer Faces(JSF)があり、そっちは標準仕様に取り込まれている。だが、なんかしっくりこないんです

Struts 2は処理を呼び出し、その結果にしたがってページが決まる。きれいにモデルとビューが分かれているのだ。
また、サーバ・クライアントの間の通信も素直だ。HTMLフォームのinput要素に名前を指定してPOSTすると、それがインスタンスの対応する名前の変数に自動的に代入される。

ところがJSFは基本的にページを呼び出してから処理が走る。そこが気に入らない。モデルとビューがごっちゃになっている感じ。
サーバ・クライアント間の通信も、処理を隠蔽しているせいで分かりにくい。画面の裏で自動生成された変数をたくさん持っていて、そのやりとりにユーザがちょっかいをかけることは基本的にできない。

最大の差はネットでぐぐれる情報量。Struts 2についてはぐぐればすぐに日本語で情報を得ることができるのに、JSFは異様に情報が少ない。この差は何なんだろう…

PageTop