JSF SelectOneMenu с noSelectionOption с использованием метки в качестве значения?

На странице jsf «создать нового пользователя» у меня есть SelectOneMenu с настраиваемым преобразователем и selectItem noSelectionOption, например: (нерелевантный код опущен)

NewUser.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
}
}

DepartmentConverter.java

@FacesConverter(value="departmentConverter")
public class DepartmentConverter extends EntityConverter {
    public DepartmentConverter(){
        super(Department.class);
    }
}

Суперконвертер для всех сущностей

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());
}

}

Однако, когда я отправляю форму с выбранной опцией «Выбрать отдел», он отправляет метку в getAsObject в конвертере вместо null, что заставляет конвертер генерировать исключение в getKey (пытается преобразовать String, содержащую id, в Long). Установка для атрибута itemValue элемента selectItem значения null не имеет никакого эффекта. В остальном предметы из коллекции отлично работают с конвертером. Кто-нибудь знает, что вызывает это?

Обновление Интересная вещь, которую я забыл упомянуть; если я удалю атрибут преобразователя из SelectOneMenu, атрибут noSelectionAttribute будет работать так, как должен, но, поскольку преобразователь по умолчанию не знает, как преобразовать мои объекты, сообщение не сможет выбрать истинный отдел. Может ли это означать, что noSelectionOption = true ПРЕДПОЛАГАЕТСЯ для отправки своей метки вместо этого, и конвертер должен каким-то образом обрабатывать ее?

6
задан Rasmus Franke 5 January 2011 в 08:17
поделиться