Java Server Faces在验证阶段失败后继续显示旧值(忽略actionListeners设置)



我想请一些人帮助理解JSF在验证阶段显示的特定行为失败。

我正在使用:

  • Tomcat 7.0.2
  • JSF 1.2_12
  • RichFaces 3.3.3

问题描述。

我写了一个有4个输入字段的表单:一个inputText和3个selectOneMenu。inputText是必需的而selectOneMenus不需要任何验证。附加到第一个selectOneMenu(第32行),是一个a4j:support标记,因此每当触发更改事件时以及第三个selectOneMenu(行44和58)被正确填充。特别是在加载之后在两个项目列表中,该方法强制第二个和第三个的值选择OneMenu设置为null。在我提交表格而不填写输入之前,这种机制似乎运行良好text:不出所料,JSF验证失败,但当我更改第一个selectOneMenu的值时,页面持续显示JSF验证第二次失败之前指定的值第三个选择OneMenu(注意actionListener仍然被调用,第二个和第三个selectOneMenu仍然被强制为null)。

由于我使用的是一个简单的PhaseListener,我注意到了以下内容:在JSF验证失败之前,每次我更改第一个selectOneMenu的值时,JSF生命在渲染期间,cycle总是为第二个和第三个selectOneMenu调用get方法响应阶段。通过这种方式,JSF能够"看到"在调用应用程序阶段。验证失败后,当我更改第一个getter的值时,JSF停止调用这些getter选择OneMenu。

这是我的看法

<?xml version='1.0' encoding='UTF-8' ?> 
<!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:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:rich="http://richfaces.org/rich">
<head>
  <title>Prove Rich</title>
</head>
<body>
  <h2>Prove Rich</h2>
  <f:view>
  <a4j:outputPanel ajaxRendered="true">
    <h:messages style="color:red" />
  </a4j:outputPanel>
  <h:form>
  <p>
    Input required: <h:inputText value="#{provaProbReplyBean.inputRequired}" required="true" />
  </p>
  <p>
    <h:outputText value="Scegli il canale:" />
    <h:selectOneMenu value="#{provaProbReplyBean.canale}">
       <f:selectItem itemLabel="--" itemValue="" />
       <f:selectItem itemLabel="Profamily" itemValue="Profamily" />
       <f:selectItem itemLabel="Captive" itemValue="Captive" />
       <a4j:support event="onchange" action="#{provaProbReplyBean.caricaProcBanche}" ajaxSingle="true" reRender="procedure, banche" />
    </h:selectOneMenu>
  </p>
  <p>
    <h:outputText value="Scegli la procedura:" />
    <h:selectOneMenu id="procedure" value="#{provaProbReplyBean.procedura}">
       <f:selectItem itemLabel="--" itemValue="" />
       <f:selectItems value="#{provaProbReplyBean.procedureList}" />
       <!-- immediately save the current value -->
       <a4j:support event="onchange" ajaxSingle="true" />
    </h:selectOneMenu>
  </p>
  <p>
    <h:outputText value="Scegli la banca:" />
    <h:selectOneMenu id="banche" value="#{provaProbReplyBean.banca}">
       <f:selectItem itemLabel="--" itemValue="" />
       <f:selectItems value="#{provaProbReplyBean.bancheList}" />
       <!-- immediately save the current value -->
       <a4j:support event="onchange" ajaxSingle="true" />
    </h:selectOneMenu>
  </p>
  <p><h:commandButton value="Submit" /></p>
  </h:form>
  </f:view>
</body>
</html>

这是我的模型:

public class ProvaProbReply {
    private String inputRequired;
    private String canale;
    private String procedura;
    private String banca;
    private Map<String, List<SelectItem>> canaliProc = new HashMap<String, List<SelectItem>>();
    private Map<String, List<SelectItem>> canaliBanche = new HashMap<String, List<SelectItem>>();
    private List<SelectItem> procedureList = new ArrayList<SelectItem>();
    private List<SelectItem> bancheList = new ArrayList<SelectItem>();
    public ProvaProbReply() {
        List<SelectItem> l = new ArrayList<SelectItem>();
        l.add(new SelectItem("Cessione del quinto"));
        l.add(new SelectItem("Credito al consumo"));
        l.add(new SelectItem("Mutui"));
        canaliProc.put("Profamily", l);
        l = new ArrayList<SelectItem>();
        l.add(new SelectItem("Credito al consumo"));
        canaliProc.put("Captive", l);
        l = new ArrayList<SelectItem>();
        canaliBanche.put("Profamily", l);
        l = new ArrayList<SelectItem>();
        l.add(new SelectItem("BDL"));
        l.add(new SelectItem("BM"));
        l.add(new SelectItem("BPM"));
        l.add(new SelectItem("CRA"));
        canaliBanche.put("Captive", l);
    }
    public String getInputRequired() {
        return inputRequired;
    }
    public void setInputRequired(String ir) {
        inputRequired = ir;
    }
    public String getCanale() {
        return canale;
    }
    public void setCanale(String c) {
        canale = c;
    }
    public String getProcedura() {
        System.out.println("ngetProcedura calledn");
        return procedura;
    }
    public void setProcedura(String p) {
        procedura = p;
    }
    public String getBanca() {
        System.out.println("ngetBanca calledn");
        return banca;
    }
    public void setBanca(String b) {
        banca = b;
    }
    public List<SelectItem> getProcedureList() {
        return procedureList;
    }
    public List<SelectItem> getBancheList() {
        return bancheList;
    }
    public String caricaProcBanche() {
        System.out.println("nListener calledn");
        procedureList.clear();
        bancheList.clear();
        if(canale != null && !canale.equals("")) {
            procedureList.addAll(canaliProc.get(canale));
            bancheList.addAll(canaliBanche.get(canale));
        }
        System.out.println("BEFORE setting:n");
        System.out.println("nProcedura: "+procedura+"n");
        System.out.println("Banca: "+banca+"n");
        procedura = null;
        banca = null;
        System.out.println("nnnAFTER setting:n");
        System.out.println("nProcedura: "+procedura+"n");
        System.out.println("Banca: "+banca+"n");
        return "";
    }
}

听起来您正在观察EditableValueHolder类型的预期行为。

如果类型的验证或转换失败,表单将以提交时的状态重新提交。这在应用请求值阶段(JSF 2规范)的文档中有所暗示:

在此阶段结束时,组件树中的所有EditableValueHolder组件都将使用此请求中包含的新提交值进行更新(或者,如果存在转换错误,则将存储足够的数据来再现不正确的输入)

如果转换或验证失败,更新模型值阶段将不会运行(不会在bean上调用任何setter。)如果用户刚刚提交了一个复杂的表单,他们不会因为其中一个错误而期望擦除所有字段。渲染器发出用户提交的值,而不调用getter(请参见isValid()getSubmittedValue())。

相关内容

  • 没有找到相关文章

最新更新