En una página "Crear nuevo usuario" JSF, tengo una SelectOneMenu con un convertidor de medida y un selectItem noSelectionOption como esto: (código irrelevante omite,)JSF SelectOneMenu with noSelectionOption usando la etiqueta como valor?
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);
}
}
Súper convertidor para todas las entidades
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());
}
}
Sin embargo, cuando puedo enviar el formulario con la opción "Seleccionar un departamento" elegido, envía la etiquetaa getAsObject en el convertidor en lugar de null , lo que provoca que el convertidor genere una excepción en getKey (intenta convertir una cadena que contiene una identificación en una larga). Establecer el atributo itemValue del selectItem en nulo no tiene ningún efecto. Los elementos de la colección funcionan a la perfección con el convertidor. ¿Alguien tiene alguna idea de lo que está causando esto?
Actualización Una cosa interesante que olvidé mencionar; si elimino el atributo del convertidor de SelectOneMenu, noSelectionAttribute funciona como debería, pero dado que el convertidor predeterminado no sabe cómo convertir mis objetos, la publicación falla al seleccionar un departamento verdadero en su lugar. ¿Esto puede significar que noSelectionOption = true es SUPPOSED para enviar su etiqueta en su lugar y se espera que el convertidor lo maneje de alguna manera?
¿Esto es jsf1 o jsf2? –
Usando Jsf 2. Lo siento por no aclarar. –
@Shervin: 'f: selectItem noSelectionOption' y' f: selectItems var' indica JSF2. – BalusC