На 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>
Ньюусерконтроллер.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 (пытается преобразовать строку, содержащую идентификатор, в тип Long). Установка для атрибута itemValue объекта selectItem значения null не имеет никакого эффекта. В противном случае элементы из коллекции прекрасно работают с конвертером. Кто-нибудь знает, что вызывает это?
Обновление Интересная вещь, которую я забыл упомянуть; если я удалю атрибут конвертера из SelectOneMenu, атрибут noSelectionAttribute будет работать как надо, но, поскольку преобразователь по умолчанию не знает, как преобразовать мои объекты, сообщение не будет выполнено при выборе истинного отдела. Может ли это означать, что параметру noSelectionOption=true ПРЕДПОЛАГАЕТСЯ вместо этого отправлять свою метку, и ожидается, что преобразователь каким-то образом обработает ее?
f:selectItem noSelectionOption
иf:selectItems var
указывают на JSF2. - person BalusC   schedule 04.01.2011