jsf 2 - getasstring - Inyección de CDI en un FacesConverter
h selectonemenu converter (4)
La anotación @Inject
solo funciona en instancias administradas por CDI. Si desea usar funciones de CDI dentro de una instancia administrada que no es CDI (como un Validador de JSF o un Convertidor de JSF), puede programar contra la API de CDI.
Esto funciona solo en al menos el servidor Java EE 7 + CDI 1.1.
@FacesValidator("userNameValidator")
public class UserNameValidator implements Validator {
private UserService userService;
public UserNameValidator(){
this.userService = CDI.current().select(UserService.class).get();
}
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
....
}
}
https://docs.oracle.com/javaee/7/api/javax/enterprise/inject/spi/CDI.html
Con todo el AnnotationHell en Java EE, la gente olvida cómo codificar.
De solo algunas búsquedas, esto parece ser un problema que ha existido por un tiempo. He escrito un FacesConverter que se parece a lo siguiente. El objeto Category es una entidad JPA y CategoryControl es el DAO que lo recupera.
@FacesConverter(value = "categoryConverter")
public class CategoryConverter implements Converter {
@Inject private CategoryControl cc;
public CategoryConverter() { }
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (cc != null) return cc.getByName(value);
System.out.println("CategoryConverter().getAsObject(): no injection!");
return null;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (!(value instanceof Category)) return null;
return ((Category) value).getName();
}
}
Como probablemente ya habrás adivinado, nunca recibo la inyección. Obtuve esta solución de esta página , que se ve así:
Workaround for this problem: create this method in your localeController:
public Converter getConverter()
{
return FacesContext.getCurrentInstance().getApplication().createConverter("localeConverter");
}
and use converter="#{localeController.converter}" in your h:selectOneMenu.
Sin embargo, tampoco puedo hacer que esto funcione. Mi bean de respaldo crea y devuelve un convertidor bien, pero no obtiene el objeto inyectado en él.
Estoy usando MyFaces CODI 1.0.1. Con el contenedor GlassFish / Weld actual. ¿Alguien puede sugerir una solución antes de volver a codificar para no usar un convertidor?
Reemplazar
@FacesConverter(value = "categoryConverter")
por
@Named
y use
<h:inputSomething converter="#{categoryConverter}" />
o
<f:converter binding="#{categoryConverter}" />
en lugar de
<h:inputSomething converter="categoryConverter" />
o
<f:converter converterId="categoryConverter" />
Por cierto, existe un problema similar para @EJB
dentro de @FacesConverter
. Sin embargo, ofrece una forma de ser agarrado por JNDI manualmente. Consulte también Comunicación en JSF 2.0 - Obtención de un EJB en @FacesConverter y @FacesValidator . De esta forma puede usar @FacesConverter(forClass=Category.class)
sin definirlo manualmente cada vez. Desafortunadamente no puedo decir desde lo alto de la cabeza cómo darse cuenta de que para los frijoles CDI.
Actualización : si usa la biblioteca de utilidades JSF OmniFaces , la versión 1.6 agrega soporte transparente para usar @Inject
y @EJB
en una clase @FacesConverter
sin ninguna configuración adicional o anotaciones. Ver también el ejemplo de presentación de CDI @FacesConverter
.
Según la respuesta de BalusC here , decidí agregar frijoles administrados JSF (requestscoped) que solo contenían @FacesConverter y Converter para resolver este problema en mi aplicación, ya que estoy migrando de beans gestionados de JSF a beans administrados por CDI.
Probé CODI @Advanced contra @FacesConverter, pero no inyecta el bean en absoluto.
Simplemente use @Advanced of CODI para su @FacesConverter vea la Wiki .
Tan pronto como un convertidor o un validador se anota con @Advanced, es posible utilizar @Inject.