1

This is in relation to the workaround for the known issue of JSF FacesConverter not being an eligible @Inject target for CDI. I followed the workaround at CDI Injection into a FacesConverter. However, in my FacesConverter, I had been utilizing the feature of having the Class of the object passed into a constructor.

From the javadoc - "If a converter has a single argument constructor that takes a Class instance and the Class of the data to be converted is known at converter instantiation time, this constructor must be used to instantiate the converter instead of the zero-argument version." This is in direct conflict with the CDI requirement for "normal scope" beans where a no-arg or @Inject annotated constructor is all that's allowed.

So in summary, I want to use a Converter that can take CDI Injections, and has access to the Class of the object being converted at runtime.

I am using Mojarra 2.2.4 on Glassfish 4 with Weld 2.0.4.

Community
  • 1
  • 1
jdessey
  • 690
  • 6
  • 14
  • Have you read the "Update" section of the answer you found yourself? – BalusC Oct 10 '13 at 19:58
  • I have. I was hoping for something that didn't involve introducing more libraries. But overall this may be cleaner than the hacks I was beginning to consider. Thanks Bauke – jdessey Oct 10 '13 at 22:00
  • OmniFaces is not "just" a library :) There's quite some stuff in there that can greatly help in reducing/simplifying your JSF code. – BalusC Oct 10 '13 at 22:06
  • Actually the OmniFaces home page says it's a "utility library". – Adrian Mitev Oct 11 '13 at 06:42
  • I will check out Omnifaces but keeping additional dependencies to a minimum is a priority. The alternative I may go with is keeping the FacesConverter declaration, but using an explicit lookup via CDI BeanManager to replace the non-functional Inject annotations. If only the issue could just be resolved in JSF. It's been out there a while... – jdessey Oct 11 '13 at 14:39

1 Answers1

3

For those who might be interested in this alternative, I was able to replace the Inject annotations with programmatic lookup via BeanManager in the constructor. The condensed code is below. I've not performance tested, and suspect that may be a downside. If time permits I'll compare to the Omnifaces solution.

EDIT: The cost of the BeanManager lookup turned out to be minimal. The constructor takes on average <1ms.

@FacesConverter(forClass = AbstractEntity.class)
public class EntityConverter implements Converter {

    private LocationService locationService;
    private Class entityClass;

    //Special parameterized constructor for @FacesConverter described in the original question
    public EntityConverter(Class entityClass) throws NamingException {
            this.entityClass = entityClass;
            this.locationService = loadManagedBean(LocationService.class, "locationService");
        }

    //Generic lookup method for @Named managed beans
    protected <T> T loadManagedBean(Class<T> clazz, String beanName) throws NamingException {
            InitialContext initialContext = new InitialContext();
            BeanManager bm = (BeanManager) initialContext.lookup("java:comp/BeanManager");

            Bean<T> bean = (Bean<T>) bm.getBeans(beanName).iterator().next();
            CreationalContext<T> cc = bm.createCreationalContext(bean);
            T beanInstance = (T) bm.getReference(bean, clazz, cc);
            return beanInstance;
    }
}
jdessey
  • 690
  • 6
  • 14