I came across a scenario were a set of radio buttons gets reset to a none-selected state whenever the view returns from an immediate action, although the actual value is processed correctly. Refreshing the view also displays the correct value. Weirdly enough, the behavior does only occur when the component uses an converter and is not inside a ui:repeat
I narrowed it down to the following example:
JSF Page
<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>
Backing Bean
@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(){
}
}
Converter
@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";
}
}
So we have:
- a group of radio buttons built from a backing bean list of
SelectItem(String, String)
, saved to a String. No converter needed. - a group of radio buttons built from a backing bean list of
SelectItem(boolean, String)
, saved to a boolean. A converter is provided to map the boolean to some words ("real"/"unreal") - just to replace the standard converter ("true"/"false") - A submit button + output to test if values get set correctly.
- A button with some immediate action, which does nothing else but change the JSF lifecycle.
With this, one can play around and observe the following:
- Whenever the page returns from the immediate action, the radios with converter outside
ui:repeat
display no value, meaning: no radio is selected - However, the value is actually set correctly during submit. Refreshing the page will results in correctly set radios.
- the same radio group inside
ui:repeat
works just fine, as does the one without the converter
Testing around against better knowledge I checked that the converter-radios put inside a <c:foreach>
instead of ui:repeat
show the same error (which is as I would have expected, as it merely builds the tree and then vanishes) and that attaching some standard converter to the string-radios does not make them break. Regarding BalusC's comment, changing the bean to ViewScoped does not affect the problem - only then, refresh gives you a blank default-initialized page.
Here I am at the end of my knowledge. I don't really see how to reduce this any further or why it behaves like this. So... well... ideas anybody?
Specs I got from the server guy: Mojarra JSF API Implementation 2.0.5-FCS, JSF 2.0 and Facelets, Server is a Weblogic 11g 10.3