问题
For my project i want to implement a combobox with h:selectOneMenu. I read many posts about how to handle the selectOneMenu properly and how to implement a custom converter. The combobox shall store the ID (Long) from a different DB Table (named fk_ID) for which a constrain is in place. So far everything seems to function as planned. Now to my problem:
The column fk_ID is optional, so the first option in the combobox is a f:selectItem with no value labeled "choose ...". When I save the form and change the value everything is OK, except if I set it back to "choose ...". The error I get is a constraint integrity violation.
I found the problem too: The converter returns null as intended but the bean receives the Long 0.
The XHTML:
<h:selectOneMenu value="#{userBean.selectedModel.fk_id}"
id="combobox">
<f:selectItem itemLabel="choose ..." />
<f:selectItems
value="#{userBean.items}"
var="item"
itemLabel="#{item.value}"
itemValue="#{item.id}"
/>
<f:converter converterId="userConverter" />
</h:selectOneMenu>
The custom converter:
@FacesConverter(value = "userConverter")
public class UserConverter implements Converter {
@Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
if (arg2 != null && !arg2.equals("null"))
return Long.valueOf(arg2);
return null;
}
@Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
return String.valueOf(arg2);
}
}
The bean (very short version):
@Named(value = "userBean")
public class UserController implements Serializable {
@Getter
@Setter
private UserModel selectedModel;
@Getter
@Setter
private List<UserModel> items;
public void saveModel() {
selectedModel = userService.saveModel(selectedModel);
}
}
The problem is that the fk_id is Long 0, but should be null. I can solve the problem by writing
if (selectedModel.getFk_id() == 0)
selectedModel.setFk_id(null);
, but thats not a solution I am comfortable with.
My Question: Why is the value null, which the converter returns, the Long 0 inside the saveModel() method?
回答1:
This converter is unnecessary and makes no sense (I'd expect an UserConverter
to convert between User
and String
, not between Long
and String
). Remove it.
Now, you need to tell JSF to interpret empty string submitted values as null
. Add the following to your web.xml
:
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
This should solve the problem on most containers. But if you're using Tomcat or a fork/clone of it (JBoss AS, WebSphere AS, etc) and/or the container uses the Apache EL parser implementation, then you also need to add the following argument to its VM startup arguments:
-Dorg.apache.el.parser.COERCE_TO_ZERO=false
This will prevent the Apache EL parser from coercing the submitted value to the primitive's default, even though you're using a primitive wrapper type as property.
See also:
- Communication in JSF 2.0
Unrelated to the concrete problem, you don't have a combobox there. That's just a simple dropdownlist. A combobox is an editable dropdownlist. Get your terms right ;)
来源:https://stackoverflow.com/questions/8093932/jsf-2-0-selectonemenu-defaults-to-0-when-empty