From 47418094e4e2b86853e4f611cb293ec69a9eb88f Mon Sep 17 00:00:00 2001 From: Erwin Vervaet Date: Thu, 5 Jun 2008 07:13:27 +0000 Subject: [PATCH] Statics on FlowFacesUtils are now public: they're supposed to be well known names. JavaDoc polishing. --- spring-webflow/changelog.txt | 6 ++++- ...AbstractFlowExecutionPropertyResolver.java | 7 ++++-- .../jsf/DelegatingFlowVariableResolver.java | 4 ++-- .../executor/jsf/FlowExecutionHolder.java | 13 +++++++---- .../jsf/FlowExecutionHolderUtils.java | 18 +++++++-------- .../jsf/FlowExecutionPropertyResolver.java | 2 ++ .../jsf/FlowExecutionVariableResolver.java | 6 ++--- .../webflow/executor/jsf/FlowFacesUtils.java | 23 +++++++++++-------- .../executor/jsf/FlowPhaseListener.java | 4 ++-- .../executor/jsf/FlowPropertyResolver.java | 10 ++++---- .../executor/jsf/FlowSystemCleanupFilter.java | 6 ++--- .../executor/jsf/FlowVariableResolver.java | 4 ++-- .../executor/jsf/JsfExternalContext.java | 14 ++++++----- .../jsf/JsfFlowConfigurationException.java | 6 +++++ .../webflow/executor/jsf/ViewIdMapper.java | 2 +- 15 files changed, 76 insertions(+), 49 deletions(-) diff --git a/spring-webflow/changelog.txt b/spring-webflow/changelog.txt index ba037964..7cb92207 100644 --- a/spring-webflow/changelog.txt +++ b/spring-webflow/changelog.txt @@ -8,7 +8,11 @@ Changes in version 1.0.6 () General * JavaDoc polishing. -* Static CURRENT_FORM_OBJECT_ATTRIBUTE on FormObjectAccessor is now public (it's supposed to be a well known name). +Package org.springframework.webflow.action +* Static CURRENT_FORM_OBJECT_ATTRIBUTE on FormObjectAccessor is now public: it's supposed to be a well known name. + +Package org.springframework.webflow.executor.jsf +* Statics on FlowFacesUtils are now public: they're supposed to be well known names. Changes in version 1.0.5 (03.10.2007) ------------------------------------- diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/AbstractFlowExecutionPropertyResolver.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/AbstractFlowExecutionPropertyResolver.java index 08b5e38c..de5a3212 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/AbstractFlowExecutionPropertyResolver.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/AbstractFlowExecutionPropertyResolver.java @@ -24,6 +24,9 @@ import org.springframework.webflow.execution.FlowExecution; /** * Base class for property resolvers that get and set flow execution attributes. + *

+ * Subclasses have to implemented the defined template methods: {@link #doGetAttributeType(FlowExecution, String)}, + * {@link #doGetAttribute(FlowExecution, String)} and {@link #doSetAttribute(FlowExecution, String, Object)}. * * @author Keith Donald */ @@ -61,7 +64,7 @@ public abstract class AbstractFlowExecutionPropertyResolver extends PropertyReso public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException { if (base instanceof FlowExecution) { - // cannot access flow execution by index so we cannot determine type. Return null per JSF spec + // cannot access flow execution by index so we cannot determine type; return null per JSF spec return null; } else { return resolverDelegate.getType(base, index); @@ -104,7 +107,7 @@ public abstract class AbstractFlowExecutionPropertyResolver extends PropertyReso public void setValue(Object base, Object property, Object value) throws EvaluationException, PropertyNotFoundException { - if ((base instanceof FlowExecution)) { + if (base instanceof FlowExecution) { FlowExecution execution = (FlowExecution) base; assertPropertyNameValid(property); doSetAttribute(execution, (String) property, value); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/DelegatingFlowVariableResolver.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/DelegatingFlowVariableResolver.java index 8ea04536..3a765b9d 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/DelegatingFlowVariableResolver.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/DelegatingFlowVariableResolver.java @@ -26,10 +26,10 @@ import org.springframework.webflow.execution.FlowExecution; * Custom variable resolver that searches the current flow execution for variables to resolve. The search algorithm * looks in flash scope first, then flow scope, then conversation scope. If no variable is found this resolver delegates * to the next resolver in the chain. - * + *

* Suitable for use along side other variable resolvers to support EL binding expressions like {#bean.property} where * "bean" could be a property in any supported scope. - * + *

* Consider combining use of this class with a Spring {@link DelegatingVariableResolver} to also support * lazy-initialized binding variables managed by a Spring application context using custom bean scopes. Also consider * such a Spring-backed managed bean facility as the sole-provider for centralized JSF managed bean references. diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionHolder.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionHolder.java index d6965dab..d5cfeba2 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionHolder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionHolder.java @@ -26,13 +26,18 @@ import org.springframework.webflow.execution.repository.FlowExecutionLock; /** * A holder storing a reference to a flow execution and the key of that flow execution if it has been (or is about to * be) managed in a repository. + *

+ * An instance of this class will be associated with the current request. It is used to hold on to flow execution + * related information while processing a request. + * + * @see FlowExecutionHolderUtils * * @author Keith Donald */ public class FlowExecutionHolder implements Serializable { /** - * The flow execution continuation key (may be null if the flow execution has not yet been generated a repository + * The flow execution continuation key (may be null if the flow execution has not yet been assigned a repository * key). May change as well over the life of this object, as a flow execution can be given a new key to capture its * state at another point in time. */ @@ -96,14 +101,14 @@ public class FlowExecutionHolder implements Serializable { } /** - * Returns the flow execution lock + * Returns the flow execution lock. */ public FlowExecutionLock getFlowExecutionLock() { return flowExecutionLock; } /** - * Sets the lock acquired on the flow execution + * Sets the lock acquired on the flow execution. * @param lock the flow execution lock */ public void setFlowExecutionLock(FlowExecutionLock lock) { @@ -138,7 +143,7 @@ public class FlowExecutionHolder implements Serializable { } /** - * Unlock the held flow execution if necessary. + * Unlock the held flow execution if necessary and clear the lock. */ public void unlockFlowExecutionIfNecessary() { if (flowExecutionLock != null) { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionHolderUtils.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionHolderUtils.java index 13747924..098c5148 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionHolderUtils.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionHolderUtils.java @@ -22,15 +22,22 @@ import javax.faces.el.EvaluationException; import org.springframework.webflow.execution.FlowExecution; /** - * A static utility class for accessing the current flow execution holder. + * A static utility class for accessing the current {@link FlowExecutionHolder flow execution holder}. *

- * By default, the current flow execution holder is stored associated with the current thread in the + * By default, the current flow execution holder is stored associated with the current request in the * {@link FacesContext}'s {@link ExternalContext#getRequestMap()}. * * @author Keith Donald */ public class FlowExecutionHolderUtils { + /** + * Returns the key used to index the flow execution holder in the request attributes. + */ + static String getFlowExecutionHolderKey() { + return FlowExecutionHolder.class.getName(); + } + /** * Returns the current flow execution holder for the given faces context. * @param context faces context @@ -100,11 +107,4 @@ public class FlowExecutionHolderUtils { context.getExternalContext().getRequestMap().remove(getFlowExecutionHolderKey()); } } - - /** - * Returns the key used to index the flow execution holder in the request attributes. - */ - static String getFlowExecutionHolderKey() { - return FlowExecutionHolder.class.getName(); - } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionPropertyResolver.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionPropertyResolver.java index 71667c48..863a77bb 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionPropertyResolver.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionPropertyResolver.java @@ -27,6 +27,8 @@ import org.springframework.webflow.execution.FlowExecution; * scopes as java.util.Maps: "flowScope", "conversationScope", and "flashScope". Also supports attribute searching when * no scope prefix is specified. The search order is flash, flow, conversation. * + * @see FlowExecutionVariableResolver + * * @author Keith Donald */ public class FlowExecutionPropertyResolver extends AbstractFlowExecutionPropertyResolver { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionVariableResolver.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionVariableResolver.java index d689a5c1..bebf6ffd 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionVariableResolver.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowExecutionVariableResolver.java @@ -24,9 +24,9 @@ import org.springframework.webflow.execution.FlowExecution; /** * Custom variable resolver that resolves to a thread-bound FlowExecution object for binding expressions prefixed with a * {@link #FLOW_EXECUTION_VARIABLE_NAME}. For instance "flowExecution.conversationScope.myProperty". - * + *

* This class is designed to be used with a {@link FlowExecutionPropertyResolver}. - * + *

* This class is a more flexible alternative to the {@link FlowVariableResolver} which is expected to be used ONLY with * a {@link FlowPropertyResolver} to resolve flow scope variables ONLY. It is more flexible because it provides access * to any scope structure of a {@link FlowExecution} object. @@ -47,7 +47,7 @@ public class FlowExecutionVariableResolver extends VariableResolver { /** * Creates a new flow executon variable resolver that resolves the current FlowExecution object. - * @param resolverDelegate the resolver to delegate to when the variable is not named "flowExecution". + * @param resolverDelegate the resolver to delegate to when the variable is not named "flowExecution" */ public FlowExecutionVariableResolver(VariableResolver resolverDelegate) { this.resolverDelegate = resolverDelegate; diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowFacesUtils.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowFacesUtils.java index 00fd5cd6..e8a5c2d8 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowFacesUtils.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowFacesUtils.java @@ -38,27 +38,27 @@ public class FlowFacesUtils { /** * Bean name of a custom flow executor implementation. - * + *

* Note the flow executor object is used only at configuration time to extract other lower-level services needed by * the JSF integration (flow execution repository, flow execution factory). The runtime FlowExecutor interface is * never used by this JSF integration. */ - private static final String FLOW_EXECUTOR_BEAN_NAME = "flowExecutor"; + public static final String FLOW_EXECUTOR_BEAN_NAME = "flowExecutor"; /** * Bean name of a custom flow execution repository implementation. */ - private static final String FLOW_EXECUTION_REPOSITORY_BEAN_NAME = "flowExecutionRepository"; + public static final String FLOW_EXECUTION_REPOSITORY_BEAN_NAME = "flowExecutionRepository"; /** * Bean name of a custom flow definition locator implementation. */ - private static final String FLOW_DEFINITION_LOCATOR_BEAN_NAME = "flowDefinitionLocator"; + public static final String FLOW_DEFINITION_LOCATOR_BEAN_NAME = "flowDefinitionLocator"; /** * Bean name of a custom flow execution factory implementation. */ - private static final String FLOW_EXECUTION_FACTORY_BEAN_NAME = "flowExecutionFactory"; + public static final String FLOW_EXECUTION_FACTORY_BEAN_NAME = "flowExecutionFactory"; /** * The default flow execution repository implementation to use. @@ -72,8 +72,9 @@ public class FlowFacesUtils { /** * Returns the locator for flow definitions to use in a JSF environment. Searches for a bean in the root web - * application context named {@link #FLOW_DEFINITION_LOCATOR_BEAN_NAME}. A bean of type - * {@link FlowDefinitionLocator} must exist by this name. + * application context named {@link #FLOW_DEFINITION_LOCATOR_BEAN_NAME}. This bean must of type + * {@link FlowDefinitionLocator}. As a fallback, this method will try to lookup the + * {@link #getFlowExecutor(FacesContext)} to obtains its flow definition locator. * @param context the faces context * @return the flow definition locator */ @@ -105,6 +106,8 @@ public class FlowFacesUtils { * @return the flow execution repository */ public synchronized static FlowExecutionRepository getExecutionRepository(FacesContext context) { + // note: synchronized because this sets the defaultExecutionRepository static member + ApplicationContext ac = FacesContextUtils.getRequiredWebApplicationContext(context); if (ac.containsBean(FLOW_EXECUTION_REPOSITORY_BEAN_NAME)) { return (FlowExecutionRepository) ac.getBean(FLOW_EXECUTION_REPOSITORY_BEAN_NAME, @@ -127,11 +130,13 @@ public class FlowFacesUtils { * Returns the flow execution factory to use in a JSF environment. Searches for a bean in the root web application * context named {@link #FLOW_EXECUTION_FACTORY_BEAN_NAME}. If no such bean exists with this name, falls back on * the repository configured by a bean with name {@link #FLOW_EXECUTOR_BEAN_NAME}. If no bean exists with that - * name, uses the default factory implementation. + * name, uses the default factory implementation ({@link FlowExecutionImplFactory}). * @param context the faces context * @return the flow execution factory */ public synchronized static FlowExecutionFactory getExecutionFactory(FacesContext context) { + // note: synchronized because this sets the defaultExecutionFactory static member + ApplicationContext ac = FacesContextUtils.getRequiredWebApplicationContext(context); if (ac.containsBean(FLOW_EXECUTION_FACTORY_BEAN_NAME)) { return (FlowExecutionFactory) ac.getBean(FLOW_EXECUTION_FACTORY_BEAN_NAME, FlowExecutionFactory.class); @@ -155,7 +160,7 @@ public class FlowFacesUtils { * @param context the faces context * @return the flow executor, or null if no such bean exists */ - private synchronized static FlowExecutorImpl getFlowExecutor(FacesContext context) { + public static FlowExecutorImpl getFlowExecutor(FacesContext context) { ApplicationContext ac = FacesContextUtils.getRequiredWebApplicationContext(context); if (ac.containsBean(FLOW_EXECUTOR_BEAN_NAME)) { return (FlowExecutorImpl) ac.getBean(FLOW_EXECUTOR_BEAN_NAME, FlowExecutorImpl.class); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowPhaseListener.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowPhaseListener.java index 092fe96e..8ab6d1c7 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowPhaseListener.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowPhaseListener.java @@ -411,7 +411,6 @@ public class FlowPhaseListener implements PhaseListener { * holder component implementation, for example--to handle flow execution restoration/access exceptions in a certain * way. * @return the flow execution key state holder - * @see #saveInViewRoot(FacesContext, String) */ protected FlowExecutionKeyStateHolder createFlowExecutionKeyStateHolder() { return new FlowExecutionKeyStateHolder(); @@ -557,9 +556,10 @@ public class FlowPhaseListener implements PhaseListener { } /** - * Standard default view id resolver which uses the web flow view name as the jsf view id + * Standard default view id mapper which uses the Web Flow view name as the JSF view id. */ public static class DefaultViewIdMapper implements ViewIdMapper { + public String mapViewId(String viewName) { return viewName; } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowPropertyResolver.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowPropertyResolver.java index 12cde8e9..0315e5c0 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowPropertyResolver.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowPropertyResolver.java @@ -26,10 +26,10 @@ import org.springframework.web.jsf.FacesContextUtils; import org.springframework.webflow.execution.FlowExecution; /** - * Custom property resolver that resolves flow session scope attributes of the current flow execution. This resolver - * will also create and set the attribute value to a bean from the root Spring Web Application Context if the value does - * not already exist, allowing for lazy-initialized binding variables. - * + * Custom property resolver that resolves flow scope attributes of the current flow execution. This resolver will also + * create and set the attribute value to a bean from the root Spring Web Application Context if the value does not + * already exist, allowing for lazy-initialized binding variables. + *

* Designed mainly to be used with the {@link FlowVariableResolver}. This is the original property resolver implemented * with Spring Web Flow 1.0. In general, prefer {@link DelegatingFlowVariableResolver} or * {@link FlowExecutionVariableResolver} over use of this class. Also, consider use of the @@ -54,7 +54,7 @@ public class FlowPropertyResolver extends AbstractFlowExecutionPropertyResolver Object value = execution.getActiveSession().getScope().get(attributeName); // note that MyFaces returns Object.class for a null value here, but // as I read the JSF spec, null should be returned when the object - // type can not be determined this certainly seems to be the case + // type cannot be determined this certainly seems to be the case // for a map value which doesn' even exist return (value == null) ? null : value.getClass(); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowSystemCleanupFilter.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowSystemCleanupFilter.java index 47ef15fd..9031cfc2 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowSystemCleanupFilter.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowSystemCleanupFilter.java @@ -27,7 +27,7 @@ import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.webflow.context.ExternalContextHolder; /** - * A servlet filter used to guarantee that web flow context information is cleaned up in a JSF environment. Most useful + * A servlet filter used to guarantee that Web Flow context information is cleaned up in a JSF environment. Most useful * to ensure no possibility of a flow execution remaining locked due to an uncaught JSF exception. * * @author Ben Hale @@ -46,8 +46,8 @@ public class FlowSystemCleanupFilter extends OncePerRequestFilter { /** * Cleans up the current flow execution in the request context if necessary. Specifically, handles unlocking the - * execution if necessary and setting the holder to null. Can be safely called even if no execution is bound or one - * is bound but not locked. + * execution if necessary and setting the holder to null in the request. Can be safely called even if no execution + * is bound or one is bound but not locked. * @param request the servlet request */ private void cleanupCurrentFlowExecution(ServletRequest request) { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowVariableResolver.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowVariableResolver.java index 5b0d97d7..494d2983 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowVariableResolver.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowVariableResolver.java @@ -23,11 +23,11 @@ import javax.faces.el.VariableResolver; * Custom variable resolver that resolves the current FlowExecution object for binding expressions prefixed with * {@link #FLOW_SCOPE_VARIABLE}. For instance "flowScope.myBean.myProperty". Designed to be used in conjunction with * {@link FlowPropertyResolver} only. - * + *

* This class is the original flow execution variable resolver implementation introduced in Spring Web Flow's JSF * support available since 1.0. In general, prefer use of {@link DelegatingFlowVariableResolver} or * {@link FlowExecutionVariableResolver} to this implementation as they are both considerably more flexible. - * + *

* This resolver should only be used with the {@link FlowPropertyResolver} which can only resolve flow-scoped variables. * May be deprecated in a future release of Spring Web Flow. * diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfExternalContext.java index 17bb9dfb..87cc3a48 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfExternalContext.java @@ -152,8 +152,14 @@ public class JsfExternalContext implements ExternalContext { this.outcome = outcome; } + public String toString() { + return new ToStringCreator(this).append("actionId", actionId).append("outcome", outcome).append("facesContext", + facesContext).toString(); + } + /** * An accessor of a JSF session map. + * * @author Keith Donald */ private static class SessionSharedMap extends SharedMapDecorator { @@ -171,7 +177,8 @@ public class JsfExternalContext implements ExternalContext { } /** - * An accessor of an JSF application map. + * An accessor of a JSF application map. + * * @author Keith Donald */ private static class ApplicationSharedMap extends SharedMapDecorator { @@ -187,9 +194,4 @@ public class JsfExternalContext implements ExternalContext { return facesContext.getExternalContext().getContext(); } } - - public String toString() { - return new ToStringCreator(this).append("actionId", actionId).append("outcome", outcome).append("facesContext", - facesContext).toString(); - } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfFlowConfigurationException.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfFlowConfigurationException.java index 9d069ffd..946cb15a 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfFlowConfigurationException.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfFlowConfigurationException.java @@ -24,10 +24,16 @@ import org.springframework.webflow.core.FlowException; */ public class JsfFlowConfigurationException extends FlowException { + /** + * Create a new configuration exception. + */ public JsfFlowConfigurationException(String msg) { super(msg); } + /** + * Create a new configuration exception caused by an underlying exception. + */ public JsfFlowConfigurationException(String msg, Throwable cause) { super(msg, cause); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/ViewIdMapper.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/ViewIdMapper.java index 22061858..526eed83 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/ViewIdMapper.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/ViewIdMapper.java @@ -21,7 +21,7 @@ import javax.faces.application.ViewHandler; * Interface to be implemented by objects that can map Web Flow view names to JSF view identifiers. JSF view identifiers * are used to determine if the current view has changed and to create views by delegating to the application's * {@link ViewHandler}. - * + *

* A view handler typically treats a JSF view id as the physical location of a view template encapsulating a page * layout. The JSF view id normally specifies the physical location of the view template minus a suffix. View handlers * typically replace the suffix of any view id with their own default suffix (e.g. ".jsp" or ".xhtml") and then try to