1

我遇到了一个场景,即当视图从立即操作返回时,一组单选按钮被重置为未选择状态,尽管实际值被正确处理。刷新视图也会显示正确的值。奇怪的是,该行为仅在组件使用转换器且不在内部时才会发生,ui:repeat其缩小到以下示例:

JSF 页面

<ui:repeat value="#{bean.stringList}" var="item" varStatus="iteration">        
    #{item} 
    <h:selectOneRadio value="#{bean.boolValue}" rendered="#{iteration.last}">
        <f:selectItems value="#{bean.boolItemList}" />
        <f:converter converterId="testConverter" />      
    </h:selectOneRadio><br /><br />
          
</ui:repeat>
<hr /> 
<h:selectOneRadio value="#{bean.stringValue}">
    <f:selectItems value="#{bean.stringItemList}" />                 
</h:selectOneRadio>    

<h:selectOneRadio value="#{bean.boolValue}">
    <f:selectItems value="#{bean.boolItemList}" />
    <f:converter converterId="testConverter" />        
</h:selectOneRadio>

<p>
<h:commandButton value="Submit" type="submit" />
<h:commandButton value="Do nothing, but immediate!" immediate="true" action="#{bean.doNothing}" />
</p>

<p>boolValue is: #{bean.boolValue}</p>

支持豆

@ManagedBean(name = "bean")
@SessionScoped
public class Bean {

private List<String> stringList;
private List<SelectItem> stringItemList;
private List<SelectItem> boolItemList;
private boolean boolValue;    
private String stringValue;    
private int removeParam;

public Bean() {
    stringList = new ArrayList<String>();
    stringList.add("Test Item One");      
    stringList.add("Test Item Two");  
    
    stringItemList = new ArrayList<SelectItem>();
    stringItemList.add(new SelectItem("1", "Option One"));
    stringItemList.add(new SelectItem("2", "Option Two"));      
    
    boolItemList = new ArrayList<SelectItem>();
    boolItemList.add(new SelectItem(Boolean.TRUE, "This is real"));
    boolItemList.add(new SelectItem(Boolean.FALSE, "This is not real"));                                                                    
    }
// + getters and setters

public void doNothing(){
    }
}

转换器

@FacesConverter("testConverter")
public class TestConverter implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value)
{       
    if (value!= null) {
        if (value.equals("real"))
        { 
        return Boolean.TRUE;          
        }
    }
    return Boolean.FALSE;
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    boolean check = (Boolean) value;
    if (check)  return "real";
    else        return "unreal";
    }
}

所以我们有:

  • 一组单选按钮,由 的支持 bean 列表构建SelectItem(String, String),保存到字符串。无需转换器。
  • 一组单选按钮,由 的支持 bean 列表构建SelectItem(boolean, String),保存为布尔值。提供了一个转换器来将布尔值映射到一些单词(“real”/“unreal”) - 只是为了替换标准转换器(“true”/“false”)
  • 提交按钮 + 输出以测试值是否设置正确。
  • 一个带有一些即时操作的按钮,除了改变 JSF 生命周期之外什么都不做。

有了这个,人们可以玩耍并观察以下内容:

  • 每当页面从即时操作返回时,带有转换器的收音机 ui:repeat显示任何值,这意味着:没有选择收音机
  • 但是,该值实际上在提交期间设置正确。刷新页面将导致正确设置收音机。
  • 内部相同的无线电组工作正常,没有转换器的无线电组也可以 ui:repeat

根据更好的知识进行测试,我检查了转换器无线电放在 a<c:foreach>中而不是ui:repeat显示相同的错误(正如我所预料的那样,因为它只是构建树然后消失),并且将一些标准转换器附加到字符串 -收音机不会让它们坏掉。关于 BalusC 的评论,将 bean 更改为 ViewScoped 不会影响问题 - 只有这样,刷新才会为您提供一个空白的默认初始化页面。

在这里,我的知识已经走到了尽头。我真的不知道如何进一步减少这种情况或为什么它会这样。所以...嗯...想法有人吗?

我从服务器人那里得到的规范:Mojarra JSF API Implementation 2.0.5-FCS、JSF 2.0 和 Facelets,服务器是 Weblogic 11g 10.3

4

1 回答 1

0

我仍然没有真正理解它为什么会这样,但我找到了两个解决方案。

1)doNothing()方法不符合规范,要求签名必须匹配java.lang.Object action()

如果我正确添加返回值以返回同一页面(通过文件名“test.xhtml”或通过outcomenavigation-rulefaces-config 中),一切正常。

2)如果我添加f:ajax到按钮来执行和重新渲染页面的一部分,一切都很好。我玩了一会儿,页面的哪一部分被执行/重新渲染似乎并不重要(除了应用值等的正常效果)。

我仍然对最初相当随机的行为(以及 ui:repeat 和转换器如何影响它)感到有些困惑。看来我对 JSF 如何在没有显式导航的情况下返回页面的理解是不完整的。这也适用于通过FacesContext#renderResponse. 任何帮助表示赞赏(如果合适,我也可以打开一个新问题,然后编辑此答案)

于 2012-10-26T15:04:27.453 回答