Getting a FacesContext from a GWT service

I'm working on a project where we needed to integrate JSF and GWT. To be more specific, we needed to have access to JSF beans in the GWT services.

Because I missed the methods getThreadLocalRequest() and getThreadLocalResponse() in RemoteServiceServlet, I had to search quite a bit before i found an answer to this problem. So to save others some time i post the class i came up with.

Most of the code is taken from an article at ocpsoft.com which also points out how important it is to release the context when you're done with it. The big difference are the lines,
UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, "gwtViewID");
facesContext.setViewRoot(view);
, which sets the view root. If no view root is set you can't use, for instance MessageBundles.

The getBean methods are only convenience methods for retrieving beans by name.

/**
 * A substitute for RemoteServiceServlet that has access to the FacesContext.
  */
@SuppressWarnings("serial")
public class FacesContextAwareRemoteServiceServlet extends RemoteServiceServlet {
 protected  T getBean(final Class type) {
  String name = type.getSimpleName();
  name = name.substring(0, 1).toLowerCase().concat(name.substring(1));
  return getBean(name, type);
 }

 @SuppressWarnings("unchecked")
 protected  T getBean(final String name, final Class type) {
  ELContext el = getFacesContext().getELContext();
  return (T) el.getELResolver().getValue(el, null, name);
 }

 /**
  * Returns the current FacesContext.
  */
 protected FacesContext getFacesContext() {
  return getFacesContext(getThreadLocalRequest(), getThreadLocalResponse());
 }

 /**
  * Should be called when the FacesContext aren't needed any more.
  */
 protected void releaseFacesContext() {
  FacesContext facesContext = FacesContext.getCurrentInstance();
  if (facesContext != null) {
   facesContext.release();
   InnerFacesContext.setFacesContextAsCurrentInstance(null);
  }
 }

 private FacesContext getFacesContext(ServletRequest request, ServletResponse response) {
  FacesContext facesContext = FacesContext.getCurrentInstance();
  if (facesContext != null) {
   return facesContext;
  }

  FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder
    .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
  LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
    .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
  Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);

  ServletContext servletContext = ((HttpServletRequest) request).getSession().getServletContext();
  facesContext = contextFactory.getFacesContext(servletContext, request, response, lifecycle);

  InnerFacesContext.setFacesContextAsCurrentInstance(facesContext);
  
  UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, "gwtViewID");
  facesContext.setViewRoot(view);

  return facesContext;
 }

 private abstract static class InnerFacesContext extends FacesContext {
  protected static void setFacesContextAsCurrentInstance(final FacesContext facesContext) {
   FacesContext.setCurrentInstance(facesContext);
  }
 }
}
Get from github

Comments

Popular posts from this blog

Cubing for charity #4

jQuery floating table header plugin

Seascape - OpenVR adaptation of a 4k intro