In einem "neuen Benutzer erstellen" jsf Seite, ich habe ein SelectOneMenu mit einem benutzerdefinierten Konverter und eine noSelectionOption selectItem wie folgt: (irrelevant Code weggelassen)
NeuerBenutzer.xhtml
<h:form>
<h:selectOneMenu value="#{newUserController.user.department}"
required="true" converter="departmentConverter">
<f:selectItem itemLabel="Select a department" noSelectionOption="true"/>
<f:selectItems value="#{newUserController.departments}"
var="dep" itemLabel="#{dep.name}" itemValue="#{dep}"/>
</h:selectOneMenu>
<p:commandButton action="#{newUserController.saveUser}"
value="#{bundle.Save}"
ajax="false"/>
</h:form>
NewUserController.java
@ManagedBean
@ViewScoped
public class NewUserController implements Serializable {
private static final long serialVersionUID = 10L;
@EJB private UserBean userBean;
private List<Department> departments;
private User user;
public NewUserController () {
}
@PostConstruct
public void init(){
user = new User();
departments = userBean.findAllDepartments();
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Department> getDepartments(){
return departments;
}
public String saveUser() {
// Business logic
}
}
AbteilungKonverter.java
@FacesConverter(value="departmentConverter")
public class DepartmentConverter extends EntityConverter {
public DepartmentConverter(){
super(Department.class);
}
}
Super-Konverter für alle Einheiten
public class EntityConverter<E> implements Converter{
protected Class<E> entityClass;
public EntityConverter(Class<E> type) {
entityClass = type;
}
@Override
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
try {
InitialContext ic = new InitialContext();
UserBean ub = (UserBean)ic.lookup("java:global/CompetenceRegister/UserBean");
return ub.find(entityClass, getKey(value));
} catch (NamingException e) {
return null;
}
}
Long getKey(String value) {
Long key;
key = Long.valueOf(value);
return key;
}
String getStringKey(Long value) {
StringBuilder sb = new StringBuilder();
sb.append(value);
return sb.toString();
}
@Override
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof AbstractEntity) {
AbstractEntity e = (AbstractEntity) object;
return getStringKey(e.getId());
}
else
throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + entityClass.getName());
}
}
Wenn ich das Formular jedoch mit der Option "Wählen Sie eine Abteilung" versende, wird die Etikett an getAsObject im Konverter anstelle von null, was dazu führt, dass der Konverter eine Ausnahme bei getKey auslöst (versucht, einen String, der eine id enthält, in einen Long zu konvertieren). Das Attribut itemValue des selectItem auf null zu setzen, hat keine Auswirkungen. Die Elemente aus der Sammlung funktionieren ansonsten perfekt mit dem Konverter. Hat jemand eine Idee, was die Ursache dafür ist?
Update Eine interessante Sache, die ich vergessen habe zu erwähnen; wenn ich das Konverter-Attribut aus dem SelectOneMenu entferne, funktioniert das noSelectionAttribute, wie es sollte, aber da der Standardkonverter nicht weiß, wie man meine Objekte konvertiert, schlägt der Beitrag bei der Auswahl einer echten Abteilung stattdessen fehl. Kann dies bedeuten, dass die noSelectionOption=true SUPPOSED stattdessen sein Etikett zu senden, und der Konverter soll dies irgendwie handhaben?