Search code examples
jsf-2cdimyfaces

CDI Injection into a FacesConverter


From just a few searches, this seems like a problem that has been around for a while. I have written a FacesConverter that looks like the following. The object Category is a JPA entity and CategoryControl is the DAO that fetches it.

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

}

As you probably guessed by now, I never get the injection. I got this workaround from this page, which looks like this.:

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.

However I can't make this work either. My backing bean creates and returns a converter all right, but it doesn't get the object injected into it.

I am using MyFaces CODI 1.0.1. With the current GlassFish/Weld container. Can anyone suggest a solution before I re-code to not use a Converter?


Solution

  • Replace

    @FacesConverter(value = "categoryConverter")
    

    by

    @Named
    

    and use

    <h:inputSomething converter="#{categoryConverter}" />
    

    or

    <f:converter binding="#{categoryConverter}" />
    

    instead of

    <h:inputSomething converter="categoryConverter" />
    

    or

    <f:converter converterId="categoryConverter" />
    

    By the way, similar problem exist for @EJB inside a @FacesConverter. It however offers a way to be grabbed by JNDI manually. See also Communication in JSF 2.0 - Getting an EJB in @FacesConverter and @FacesValidator. This way you can use a @FacesConverter(forClass=Category.class) without manually defining it everytime. Unfortunately I can't tell from top of head how to realize that for CDI beans.


    Update: if you happen to use JSF utility library OmniFaces, since version 1.6 is adds transparent support for using @Inject and @EJB in a @FacesConverter class without any additional configuration or annotations. See also the CDI @FacesConverter showcase example.