2

I'm implementing a webapp using Jsf 2.0 and Primefaces 3.2. I've noticed this unexpected behavoiur: I have a selectOneMenu and a commandButton, as below

<p:selectOneMenu id="selsel" value="#{bean.myObj}">
  <f:selectItems value="#{bean.myObjList}" />
</p:selectOneMenu>
<p:commandButton id="btnid" value="Ok" actionListener="#{bean.updateSelectValues()}" />

What happens is that if myObj is not a String, the updateSelectValues method is not called. I can't see any exception or error at all, it's just not called. Here's the backing bean:

private List<MyObj> myObjList;
private MyObj myObj;
// getters and setters

public void updateSelectValues() {
  System.out.println(this.myObj);
}

The code for myObj:

public class MyObj implements Serializable {

  private static final long serialVersionUID = 1L;

  private String param1;
  private int param2;

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("MyObj [param1=");
    builder.append(this.param1);
    builder.append(", param2=");
    builder.append(this.param2);
    builder.append("]");
    return builder.toString();
  }

}
loscuropresagio
  • 1,922
  • 15
  • 26

1 Answers1

8

That's because HTML and HTTP does not understand Java objects. All Java objects are converted to String when HTML is to be produced by JSF. All HTTP request parameters which are String are supposed to be converted back to Java object when the submitted form data is to be processed by JSF.

As to your concrete problem, if you have added a <h:message>, <h:messages> or the PrimeFaces equivalent to the form (and also updated it on ajax submits), then you should have noticed a conversion error for "null converter". Also, if you have paid attention to the server log, you should also have seen a warning about an unhandled message.

You need to create a custom Converter which converts between MyObj and its unique String representation. For example:

@FacesConverter(forClass=MyObj.class)
public class MyObjConverter implements Converter {

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object valueToRender) {
        // Convert MyObj to its unique String representation.
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
        // Convert String to MyObj.
    }

}

Usually those objects are already stored in some database or mapping by their ID. You then use exactly that ID as unique String representation.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555