struts の validwhen では、小数付きの数値比較が正しく行われない。
ソースを追ってみたところ、ValidWhenParser クラスで比較処理をしていたのだけど、これが int 型で比較できる場合は数値として比較、それ以外はすべて String で比較するという処理になっていた。えー、整数だけですか。全然かゆいところに手が届いていない!
これのタチ悪いところは、小数値であっても比較処理自体は行われる点。そう、文字列として比較して、その結果たまに正しい結果を返してしまう。厄介だ。
例えば、start と end という数値入力するフィールドがあって、その大小関係が逆転しないように入力チェックをするとき、
((start == null) or (*this* <= end))
と validwhen 式を書いて、
private String start = "9.5"; private String end = "11";
とすると、文字列での比較となり、1より9の方が後になるってんで、大小関係が正しいにも関わらずエラーとして検証に引っかかってしまう。
private String start = "2.5"; private String end = "5";
という場合は、小数があっても正しい検証結果を返すので、問題なし。こんな感じで一見すると正しく動いているようにみえるので、むーって感じ。ハマリました。
そんなわけで、validwhen は整数の比較と、文字列の比較のときのみ使用するようにしなくちゃいけないです。いや、もう文字列に限定して使用するものだと捉えた方が良いかもしれない。そして数値比較用には、自前で検証メソッドを作成してしまった方が、間違いがなくて良さそう。(または ValidWhenParser の処理そのものを小数対応に直しちゃうのもアリ)
BigDecimal で比較、いやせめて Double で比較してくれれば良かったのに...。