JSF2で、バリデーションエラーが起きると、inputHiddenの値が失なわれる。
こちらは回避策を見つけたけど、やはり結構困る問題。
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@RequestScoped
@Named
public class Bug2 {
long seed;
String value;
String value2;
public String getValue() {return value;}
public void setValue(String value) {this.value = value;}
public String getValue2() {return value2;}
public void setValue2(String value2) {this.value2 = value2;}
public long getSeed() {return seed;}
public void setSeed(long seed) {this.seed = seed;}
public void perform() {
seed = System.currentTimeMillis();
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:form>
<h:inputHidden value="#{bug2.seed}"/>
<h:panelGrid columns="3">
<h:outputLabel value="seed"/>
<h:outputText id="seed" value="#{bug2.seed}"/>
<h:message for="seed"/>
<h:outputLabel value="Value"/>
<h:inputText id="value" value="#{bug2.value}" required="true"/>
<h:message for="value"/>
<h:outputLabel value="Value2"/>
<h:inputText id="value2" value="#{bug2.value2}" required="true"/>
<h:message for="value2"/>
</h:panelGrid>
<h:commandButton value="Submit" action="#{bug2.perform}"/>
</h:form>
</html>
こんな風に操作する。
- Value, Value2に適当な値'1', '2'とかを入れて、Submitをclick。
- seedのところに、値が生成される。
- Valueのところを空にして、Submitをclick。
- required="true"なので、バリデーションエラーになるが、Value2の内容は残っているのに、なぜかseedの方(これはinputHiddenで保持)が消えてしまって0になる。
JSF2では、bookmarkable urlが簡単に作れるので、この手のread-onlyパラメータは、リクエストパラメータとして持たせておけば、回避できるんだけど、ちょっと面倒なんで、バグ報告してみた。
P.S. これ、もうちょっと調べてみたら、hiddenが消えているのではなくて、出力コンポーネントの値が失なわれているということが分かった。エラーがあってページを再表示する時に、出力コンポーネントから、モデルのオブジェクトを見に行くと、エラーになっているから存在していなくて、何も表示できないってことみたいだ。入力コンポーネント系なら、submitted valueを書き戻せるけど、出力コンポーネントはダメってことらしい。入力コンポーネントをreadonlyにしても、やっぱり消えちゃうようだ。とりあえずJavaScriptで、hiddenの値をコピーしてやるくらいしか方法は無さそう。





