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.
|