0

Using JSF2 (MyFaces 2.1) and CDI (Weld) I use a selectOneMenu filled with an enum to conditionally render a second selectOneMenu (doublemenu in the code). There are several other fields in the form which are validated using bean validation.

The problem:

If there are validation errors after clicking on the commandButton and error messages are shown, the doublemenu will not reappear. It appears that bean.type =='double' is not true. But why? The selectOneMenu itself shows the option double as the selected item.

@javax.inject.Named
@javax.enterprise.context.RequestScoped
public class Bean {

private enum MyEnum {
    Single, Double
}

private MyEnum type;

public MyEnum getType() {
    return type;
}

public void setType(MyEnum type) {
    this.type = type;
}

public MyEnum [] getTypes() {
    return MyEnum.values();
}


<h:form>
<h:selectOneMenu value="#{bean.type}">
  <f:selectItems value="#{bean.types}" />
  <f:ajax render="doublemenu" />
</h:selectOneMenu>

<h:panelGroup id="doublemenu">
  <h:panelGroup rendered="#{bean.type == 'double'}">
    <h:selectOneMenu ...>
    </h:selectOneMenu>
  </h:panelGroup>
</h:panelGroup>
<h:inputText id="VALIDATED"/>
<h:commandButtonaction="#{bean.save}"
</h:form>

BTW: bean.save is not executed

Ginkgochris
  • 455
  • 4
  • 25

1 Answers1

4

It's because your bean is request scoped. Request scoped beans are garbaged by end of every request and newly created on begin of every request. This also applies to individual ajax requests on the same view.

The rendered attribute is also evaluated during collecting submitted values (the apply request values phase). However, at the point the submitted values are to be collected, the #{bean.type} is obviously not been set yet (it has still to be set based on the collected submitted value during update model values phase). As your bean is request scoped, it would return the default value, not the submitted value from a previous request.

There are basically 2 ways to fix this.

  1. Put the bean in a bit broader scope. JSF offers the @ViewScoped for exactly this purpose. This is in the current JSF 2.1 version only not compatible with CDI. If switching to JSF @ManagedBean is not an option, then you'd need MyFaces CODI to bridge the JSF @ViewScoped transparently to CDI, or to wait for JSF 2.2 to get a CDI compatible @ViewScoped out the box.

  2. Check a request parameter instead of a bean property.

    <h:selectOneMenu binding="#{type}" ...>
        ...
    </h:selectOneMenu>
    
    <h:panelGroup rendered="#{param[type.clientId] == 'Double'}">
    

Please note that this all is completely unrelated to enums. You'd have had exactly the same problem when using e.g. a String. Also please note that I fixed a typo in your code example, an enum value of Double is definitely not the same as double.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks, the request parameter solution works for me. But I still wonder why texts in inputboxes stay in the form after validation but the enum value is set to default. – Ginkgochris Feb 13 '13 at 09:25