org.apache.myfaces.application.jsp
Class JspViewHandlerImpl

java.lang.Object
  extended by javax.faces.application.ViewHandler
      extended by org.apache.myfaces.application.jsp.JspViewHandlerImpl

public class JspViewHandlerImpl
extends ViewHandler

Implementation of the ViewHandler interface that knows how to use JSP pages as the view templating mechanism, and either javax.servlet or javax.portlet API as the request/response framework.

This implementation works tightly together with the various JSP TagHandler classes to implement the behaviour mandated by the ViewHandler specification.

Rendering of a view is done simply by invoking the servlet generated from the jsp file that is named by the viewId of the view being rendered. Such servlets generate all their output in one pass, writing text and invoking JSP taghandlers in the order they are present in the jsp file.

On the first visit to a view, components are created when their taghandler is invoked They must then be rendered immediately in order for their output to be generated in the correct location relative to non-JSF text (and other non-jsf tags) within the same jsp file. This means that components which are defined via tags later in the page do not yet exist. This is particularly problematic for:

On later visits to the same view, the component tree already exists (has been restored). Components can therefore reference others later in the page. When the JSP-generated servlet invokes a taghandler, it "locates" the appropriate existing component in the tree rather than creating a new one, and then invokes the appropriate rendering methods on it.

Version:
$Revision: 608647 $ $Date: 2008-01-03 16:57:10 -0500 (Thu, 03 Jan 2008) $
Author:
Thomas Spiegl (latest modification by $Author: skitching $)

Field Summary
static String FORM_STATE_MARKER
           
static int FORM_STATE_MARKER_LEN
           
 
Fields inherited from class javax.faces.application.ViewHandler
CHARACTER_ENCODING_KEY, DEFAULT_SUFFIX, DEFAULT_SUFFIX_PARAM_NAME
 
Constructor Summary
JspViewHandlerImpl()
           
 
Method Summary
 Locale calculateLocale(FacesContext facesContext)
          Get the locales specified as acceptable by the original request, compare them to the locales supported by this Application and return the best match.
 String calculateRenderKitId(FacesContext facesContext)
           
 UIViewRoot createView(FacesContext facesContext, String viewId)
          Create a UIViewRoot object and return it; the returned object has no children.
 String getActionURL(FacesContext facesContext, String viewId)
           
 String getResourceURL(FacesContext facesContext, String path)
           
protected  String getViewIdPath(FacesContext facescontext, String viewId)
           
 void renderView(FacesContext facesContext, UIViewRoot viewToRender)
          Simply invoke the appropriate jsp-generated servlet.
 UIViewRoot restoreView(FacesContext facesContext, String viewId)
          Just invoke StateManager.restoreView.
 void writeState(FacesContext facesContext)
          Writes a state marker that is replaced later by one or more hidden form inputs.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

FORM_STATE_MARKER

public static final String FORM_STATE_MARKER
See Also:
Constant Field Values

FORM_STATE_MARKER_LEN

public static final int FORM_STATE_MARKER_LEN
Constructor Detail

JspViewHandlerImpl

public JspViewHandlerImpl()
Method Detail

calculateLocale

public Locale calculateLocale(FacesContext facesContext)
Get the locales specified as acceptable by the original request, compare them to the locales supported by this Application and return the best match.

Specified by:
calculateLocale in class ViewHandler

calculateRenderKitId

public String calculateRenderKitId(FacesContext facesContext)
Specified by:
calculateRenderKitId in class ViewHandler

createView

public UIViewRoot createView(FacesContext facesContext,
                             String viewId)
Create a UIViewRoot object and return it; the returned object has no children.

As required by the spec, the returned object inherits locale and renderkit settings from the viewRoot currently configured for the facesContext (if any). This means that on navigation from one view to another these settings are "inherited".

Specified by:
createView in class ViewHandler

getActionURL

public String getActionURL(FacesContext facesContext,
                           String viewId)
Specified by:
getActionURL in class ViewHandler

getResourceURL

public String getResourceURL(FacesContext facesContext,
                             String path)
Specified by:
getResourceURL in class ViewHandler

renderView

public void renderView(FacesContext facesContext,
                       UIViewRoot viewToRender)
                throws IOException,
                       FacesException
Simply invoke the appropriate jsp-generated servlet.

Specified by:
renderView in class ViewHandler
Throws:
IOException
FacesException

restoreView

public UIViewRoot restoreView(FacesContext facesContext,
                              String viewId)
Just invoke StateManager.restoreView.

Specified by:
restoreView in class ViewHandler

writeState

public void writeState(FacesContext facesContext)
                throws IOException
Writes a state marker that is replaced later by one or more hidden form inputs.

The problem with html is that the only place to encode client-side state is in a hidden html input field. However when a form is submitted, only the fields within a particular form are sent; fields in other forms are not sent. Therefore the view tree state must be written into every form in the page. This method is therefore invoked at the end of every form.

And the problem with JSP2.0 as a templating system is that as described at the top of this file the component tree is not built before rendering starts. It is created only as jsf tags are encountered while the page is being rendered.

But when the end of a form (h:form tag) is encountered, not all of the component tree exists yet, so it is impossible to write the tree state out at that time.

The solution used here is to buffer the entire page being generated, and simply output a "marker" string. After the rendering pass is complete the component tree state can be computed. The generated page is then post-processed to replace all the "marker" strings with the complete tree state.

Note that this is only a problem with client-side state saving. For server-side state it should be possible to write the appropriate "key" out even though the data will not be stored under that key until the end of the rendering. This is not yet implemented however. TODO: optimise server-side state saving by not writing markers.

See ViewTag.doAfterBody() for the call that triggers the replacement of marker strings.

Specified by:
writeState in class ViewHandler
Parameters:
facesContext -
Throws:
IOException

getViewIdPath

protected String getViewIdPath(FacesContext facescontext,
                               String viewId)


Copyright © 2012 The Apache Software Foundation. All Rights Reserved.