На странице jsf «Создать нового пользователя» у меня есть SelectOneMenu с пользовательским конвертером и элемент selectOtem выбора 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 в конвертере вместо нуля, в результате чего конвертер генерирует исключение в getKey (пытается преобразовать строку, содержащуюИдем в длинную).Установка атрибута itemValue элемента selectItem в значение null не имеет никакого эффекта.Предметы из коллекции отлично работают с конвертером.Кто-нибудь имеет представление о том, что вызывает это?
Обновление Интересная вещь, которую я забыл упомянуть;если я удалю атрибут преобразователя из SelectOneMenu, noSelectionAttribute будет работать как надо, но, поскольку конвертер по умолчанию не знает, как преобразовать мои объекты, в публикации не будет выбран правильный отдел.Может ли это означать, что noSelectionOption = true равен SUPPOSED для отправки своей метки, а конвертер каким-то образом должен обрабатывать ее?