Tuesday, January 10, 2012

how to access faces context and backing beans in a servlet filter

No updates for awhile, sorry. I've actually been busy coding, but let's get to the business of blogging now. So the thing is that for some reason or the other you would like to populate values in your Javaserver Faces backing beans in a servlet filter. Ur big fat mama in this case is Craig McClanaghan (much kudos to him btw for all the work he has done for Struts and JSF). Craig happily explains how to get a reference to your bean from the faces context, but then bluntly states that sorry, because a filter is running before a Faces servlet the context hasn't been set up for this request, so you cannot access it in a filter. Stupid as I am, I didn't believe that.

JSF people probably forgot the whole filter spec, which is SOO useful for all handly things, such as authorization and for supporting stupid devices that only know how to generate GET requests. Anyway, the code to set up a faces context in a filter:


// You need an inner class to be able to call FacesContext.setCurrentInstance
// since it's a protected method
private abstract static class InnerFacesContext extends FacesContext
{
protected static void setFacesContextAsCurrentInstance(FacesContext facesContext) {
FacesContext.setCurrentInstance(facesContext);
}
}

private FacesContext getFacesContext(ServletRequest request, ServletResponse response) {
// Try to get it first
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);

// Either set a private member servletContext = filterConfig.getServletContext();
// in you filter init() method or set it here like this:
// ServletContext servletContext = ((HttpServletRequest)request).getSession().getServletContext();
// Note that the above line would fail if you are using any other protocol than http

// Doesn't set this instance as the current instance of FacesContext.getCurrentInstance
facesContext = contextFactory.getFacesContext(servletContext, request, response, lifecycle);

// Set using our inner class
InnerFacesContext.setFacesContextAsCurrentInstance(facesContext);

// set a new viewRoot, otherwise context.getViewRoot returns null
UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, "yourOwnID");
facesContext.setViewRoot(view);

return facesContext;
}

// You can even use a NavigationHandler
NavigationHandler navigationHandler = facesContext.getApplication().getNavigationHandler();

navigationHandler.handleNavigation(facesContext,"getrequest", "works");

// you could just render the page here but since we are still in filter, it might be
// a better idea to forward to the actual page
// facesContext.getApplication().getViewHandler().renderView(facesContext, facesContext.getViewRoot() );

request.getRequestDispatcher(facesContext.getViewRoot().getViewId() ).forward(request, response);

Neat, huh?

Posted by thoughts at June 23, 2004 05:25 PM | TrackBack
Comments

How is using a Filter compared with using a PhaseListener?

Implementing a PhaseListener requires implementing 3 methods:
- public void beforePhase (PhaseEvent event)
- public void beforePhase (PhaseEvent event)
- public PhaseId getPhaseId () //the choice of Faces phase to handle

The 1st 2 methods allow a use of the PhaseEvent parameter, which is very useful to get a FacesContext (FacesContext context = event.getFacesContext();).

Could you please comment on the differences between using a Filter and using a PhaseListener?

Posted by: Ophir Radnitz at August 16, 2004 03:07 AM

Thanks for comments Ophir. Check out my response, a new post on filters and PhaseListeners. You can click on "posted by" to get there.

Posted by: Alphageek at August 19, 2004 12:33 AM

On URL http://www.thoughtsabout.net/blog/archives/000033.html

Reference was made to the "servletContext" in Statement:

facesContext = contextFactory.getFacesContext(servletContext, request, response, lifecycle);
but it was never instaniated in the method???

I'm trying to obtain the "ActionEvent" from the Request via a Filter.. I believe this is possible based on your comments???? How could this be accomplished