JSF:为什么在请求范围内的POST REDIRECT GET下的表单提交期间在应用请求值阶段期间调用渲染中的空测试

时间:2012-04-01 09:14:57

标签: jsf jsf-2 phase rendered-attribute

这个问题是从JSF2: why does empty test in rendered of panelGroup in composite prevent action from being called?

的部分答案中产生的

在下面,Element是一个名称和ID的@Entity。一个view.xhtml JSF页面将id作为viewParam,并使用@ManagedBean @RequestScoped ElementController的setID(Long id)触发从数据库中加载相应的Element(在问题中不再起作用),并且发现元素被设置为'当前'元素可用(由于历史原因,名称略有不同)作为元素getSelected()。

view.xhtml页面执行渲染属性测试#{not empty elementController.selected},并且有啊:commandButton with action执行faces-redirect,以及id作为查询参数,返回view.xhtml页。

由于某种原因,我不完全理解,在表单提交时,在应用请求阶段和进程验证阶段都调用了测试(因此getSelected),之后可以设置viewParam id(因此在当前/之前)可以在更新模型值阶段找到并设置所选元素。

极大缩写的view.xhtml页面是:

<f:view>
 <f:metadata>
    <f:viewParam name="id" value="#{elementController.id}"/>
 </f:metadata>
</f:view>
<h:body>   
 <h:form>
   <h:panelGroup rendered="#{not empty elementController.selected}">
       <h:outputText value="#{elementController.selected.name}"/>
   </h:panelGroup>

   <h:commandButton value="Apply" action="#{elementController.action}" />

 </h:form>
</h:body>

(表单提交的意义在上面丢失,但对于这个问题并不重要。)

ElementController扩展了RequestController:

public void setId(Long id) {
log_debug("setId","id",id);
if (id != null) {
    this.id = id;
    T found = (T) getAbstractFacade().find(id);
    if (found == null) {
        String $error = "No object with id(" + id + ") found for class " + getManagedClass().getSimpleName();
        log_error($error);
    }
    setCurrent(found);
 }
}

public T getSelected() {
  log_debug("getSelected","current",current);        
  if (current == null) {
    log_warn("getSelected","null current Element");
   }
 return current;
}

public Object action() {
    String $i = "action";
    log_debug($i);
    if (current==null) {
        log_warn($i, "can't generate action outcome for null current element");
        return null;
    }
    return "/view?faces-redirect=true&id="+current.getId();
 }

现在在表单提交时,getSelected()恰好被调用两次,当current == null时,一次在apply请求值阶段,一次在进程验证阶段,由于测试#{not empty elementController.selected因为view.xhtml中的viewParam,可以在设置id之前(因此加载Element实体)。

问题是,为什么在应用请求阶段和流程验证阶段都会调用render =#{not empty elementController.selected}?

在执行带有id参数的view.xhtml的初始GET加载时,不会在这些阶段调用它,仅在表单提交POST和后续重定向和GET期间。

1 个答案:

答案 0 :(得分:4)

在回发后查询rendered属性两次或更多次的原因是因为JSF遍历每个阶段的组件树。

名称'rendered'可能不是最好的名字,因为它不仅仅是渲染它应用条件的组件,而是实际上处理它。

首先咨询“应用请求值”,以查看是否应该处理该组件及其子组件以将这些请求值应用于它们。它在“过程验证”中再次被咨询,因为它的价值可能在不同阶段之间发生了变化。

在我执行初始GET加载的那些阶段中没有调用它,因为当你执行GET时,组件树不会在这些阶段中遍历(只处理元数据,这就是视图参数被放置的原因)在一个特殊的元数据部分)。

为了在回发后使操作方法中的GET请求中提供的id可用,您最好使用视图范围(@ViewScoped)作为辅助bean。