Previous Section  < Day Day Up >  Next Section

9.3 Returning a JSF View Response to a Non-JSF Request

A less common scenario is that a request is first processed by a regular servlet, but a JSF view is used to generate the response. One example of where this approach is needed is for an application framework that needs to process the request before passing it on to a JSF view.

To let a JSF view generate a response to a non-JSF request, the servlet must create a FacesContext instance, configure it with the view, and ask JSF to render the response. Here's the code for doing this:

import javax.faces.FactoryFinder;

import javax.faces.application.Application;

import javax.faces.application.ViewHandler;

import javax.faces.component.UIViewRoot;

import javax.faces.context.FacesContext;

import javax.faces.context.FacesContextFactory;

import javax.faces.lifecycle.LifecycleFactory;

import javax.faces.lifecycle.Lifecycle;

...

public class MyServet extends HttpServlet {

    public void doPost(HttpServletRequest request, 

        HttpServletResponse response) throws IOException {

        // Whatever processing is needed

        ...

        LifecycleFactory lFactory = (LifecycleFactory)

        FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);

        Lifecycle lifecycle =

            lFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);



       FacesContextFactory fcFactory = (FacesContextFactory)

       FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);

       FacesContext context =

           fcFactory.getFacesContext(context, request, response, lifecycle);



       Application application = context.getApplication( );

       ViewHandler viewHandler = application.getViewHandler( );

       UIViewRoot view = viewHandler.createView(facesContext, "/myView.jsp");

       facesContext.setViewRoot(view);



       lifecycle.render( );

    }

A number of JSF factories and other internal classes are needed to make this work. The internal class that controls the request processing is called javax.faces.lifecycle.Lifecycle, and because an application or a tool can plug in its own, customized version, a factory named javax.faces.lifecycle.LifecycleFactory is responsible for creating instances of the Lifecycle class. FacesContext instances are also created by a factory—for example, in order to provide different implementations of FacesContext for a servlet and a portlet environment. Both of these factories are managed by yet another factory, called the javax.faces.FactoryFinder.

The factories are used to create a Lifecycle instance, which is then used to construct a FacesContext instance, along with the objects that represent the Servlet context, request and response. Next, a ViewHandler is retrieved from the Application class that you've seen earlier. The ViewHandler is also a pluggable class that can be replaced for an application if you prefer to use a different presentation technology than JSP. The ViewHandler is asked to create a UIViewRoot for the JSF view, and the returned instance is installed on the new FacesContext object. Finally, the Lifecycle is asked to render the view.

As you've seen in this chapter, the most common navigation needs are satisfied by the <h:outputLink> action and the combination of the <h:commandButton>, action methods, and navigation rules defined in the faces-config.xml file. For special cases, such as the ones described in the last section, you can drop down to the API level to do whatever is needed.

    Previous Section  < Day Day Up >  Next Section