A simple way to Inject Guice into JSF (Mojarra)

Previously I have been using GuiceSF to inject the JSF managed beans which extends the Mojarra's implementation of ELResolver (ManagedBeanELResolver). This was bit of a hack but it was relatively simple to implement.
In upgrading to newer version of JSF, I had to manually tweak it to keep it in line with the new features in the spec which took a fair amount of debug stepping. So when JSF 2 came out I looked around for a way to do it which still used the implementation's bean creation and handling but also injected it with Guice.

After digging around in the injection code in Mojarra, I saw how simple it would be to extend the provided Tomcat injection (which injects stuff for the @Resource and @EJB etc annotations).

This solution first requires the injection provider be specified in web.xml:
<context-param>
   <description>JSF Injection provider</description>
   <param-name>com.sun.faces.injectionProvider</param-name>
   <param-value>net.devgrok.jsf.Tomcat6GuiceInjectionProvider</param-value>
</context-param>

Next extend the Tomcat injector:
package net.devgrok.jsf;

import javax.faces.FacesException;
import javax.servlet.ServletContext;

import org.apache.AnnotationProcessor;

import com.google.inject.Injector;
import com.sun.faces.spi.InjectionProviderException;
import com.sun.faces.vendor.Tomcat6InjectionProvider;

/**
 * Based on {@link com.sun.faces.vendor.Tomcat6InjectionProvider}. Injects using Guice for JSF.
 * 
 * @author Chris Watts
 */
public class Tomcat6GuiceInjectionProvider extends Tomcat6InjectionProvider
{

 private ServletContext servletContext;

 public Tomcat6GuiceInjectionProvider(ServletContext servletContext)
 {
  super(servletContext);
  this.servletContext = servletContext;
 }

 public void inject(Object managedBean) throws InjectionProviderException
 {
  try
  {
   getProcessor().processAnnotations(managedBean);
   getInjector().injectMembers(managedBean);
  }
  catch (Exception e)
  {
   throw new InjectionProviderException(e);
  }
 }

 private AnnotationProcessor getProcessor()
 {
  return ((AnnotationProcessor) servletContext.getAttribute(AnnotationProcessor.class.getName()));
 }
 
 protected Injector getInjector()
 {
  Injector injector = (Injector) servletContext.getAttribute(Injector.class.getName());
  if (injector == null)
   throw new FacesException("Guice injector not found, verify your web.xml file for mapping GuiceContextListener");
  return injector;
 }
}

Comments