Statics on FlowFacesUtils are now public: they're supposed to be well known names.

JavaDoc polishing.
This commit is contained in:
Erwin Vervaet
2008-06-05 07:13:27 +00:00
parent 7f1a70b776
commit 47418094e4
15 changed files with 76 additions and 49 deletions

View File

@@ -8,7 +8,11 @@ Changes in version 1.0.6 ()
General General
* JavaDoc polishing. * 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) Changes in version 1.0.5 (03.10.2007)
------------------------------------- -------------------------------------

View File

@@ -24,6 +24,9 @@ import org.springframework.webflow.execution.FlowExecution;
/** /**
* Base class for property resolvers that get and set flow execution attributes. * Base class for property resolvers that get and set flow execution attributes.
* <p>
* 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 * @author Keith Donald
*/ */
@@ -61,7 +64,7 @@ public abstract class AbstractFlowExecutionPropertyResolver extends PropertyReso
public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException { public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException {
if (base instanceof FlowExecution) { 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; return null;
} else { } else {
return resolverDelegate.getType(base, index); 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, public void setValue(Object base, Object property, Object value) throws EvaluationException,
PropertyNotFoundException { PropertyNotFoundException {
if ((base instanceof FlowExecution)) { if (base instanceof FlowExecution) {
FlowExecution execution = (FlowExecution) base; FlowExecution execution = (FlowExecution) base;
assertPropertyNameValid(property); assertPropertyNameValid(property);
doSetAttribute(execution, (String) property, value); doSetAttribute(execution, (String) property, value);

View File

@@ -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 * 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 * 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. * to the next resolver in the chain.
* * <p>
* Suitable for use along side other variable resolvers to support EL binding expressions like {#bean.property} where * 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. * "bean" could be a property in any supported scope.
* * <p>
* Consider combining use of this class with a Spring {@link DelegatingVariableResolver} to also support * 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 * 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. * such a Spring-backed managed bean facility as the sole-provider for centralized JSF managed bean references.

View File

@@ -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 * 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. * be) managed in a repository.
* <p>
* 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 * @author Keith Donald
*/ */
public class FlowExecutionHolder implements Serializable { 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 * 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. * 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() { public FlowExecutionLock getFlowExecutionLock() {
return flowExecutionLock; return flowExecutionLock;
} }
/** /**
* Sets the lock acquired on the flow execution * Sets the lock acquired on the flow execution.
* @param lock the flow execution lock * @param lock the flow execution lock
*/ */
public void setFlowExecutionLock(FlowExecutionLock 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() { public void unlockFlowExecutionIfNecessary() {
if (flowExecutionLock != null) { if (flowExecutionLock != null) {

View File

@@ -22,15 +22,22 @@ import javax.faces.el.EvaluationException;
import org.springframework.webflow.execution.FlowExecution; 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}.
* <p> * <p>
* 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()}. * {@link FacesContext}'s {@link ExternalContext#getRequestMap()}.
* *
* @author Keith Donald * @author Keith Donald
*/ */
public class FlowExecutionHolderUtils { 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. * Returns the current flow execution holder for the given faces context.
* @param context faces context * @param context faces context
@@ -100,11 +107,4 @@ public class FlowExecutionHolderUtils {
context.getExternalContext().getRequestMap().remove(getFlowExecutionHolderKey()); 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();
}
} }

View File

@@ -27,6 +27,8 @@ import org.springframework.webflow.execution.FlowExecution;
* scopes as java.util.Maps: "flowScope", "conversationScope", and "flashScope". Also supports attribute searching when * 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. * no scope prefix is specified. The search order is flash, flow, conversation.
* *
* @see FlowExecutionVariableResolver
*
* @author Keith Donald * @author Keith Donald
*/ */
public class FlowExecutionPropertyResolver extends AbstractFlowExecutionPropertyResolver { public class FlowExecutionPropertyResolver extends AbstractFlowExecutionPropertyResolver {

View File

@@ -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 * 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". * {@link #FLOW_EXECUTION_VARIABLE_NAME}. For instance "flowExecution.conversationScope.myProperty".
* * <p>
* This class is designed to be used with a {@link FlowExecutionPropertyResolver}. * This class is designed to be used with a {@link FlowExecutionPropertyResolver}.
* * <p>
* This class is a more flexible alternative to the {@link FlowVariableResolver} which is expected to be used ONLY with * 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 * 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. * 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. * 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) { public FlowExecutionVariableResolver(VariableResolver resolverDelegate) {
this.resolverDelegate = resolverDelegate; this.resolverDelegate = resolverDelegate;

View File

@@ -38,27 +38,27 @@ public class FlowFacesUtils {
/** /**
* Bean name of a custom flow executor implementation. * Bean name of a custom flow executor implementation.
* * <p>
* Note the flow executor object is used only at configuration time to extract other lower-level services needed by * 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 * the JSF integration (flow execution repository, flow execution factory). The runtime FlowExecutor interface is
* never used by this JSF integration. * 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. * 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. * 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. * 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. * 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 * 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 * application context named {@link #FLOW_DEFINITION_LOCATOR_BEAN_NAME}. This bean must of type
* {@link FlowDefinitionLocator} must exist by this name. * {@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 * @param context the faces context
* @return the flow definition locator * @return the flow definition locator
*/ */
@@ -105,6 +106,8 @@ public class FlowFacesUtils {
* @return the flow execution repository * @return the flow execution repository
*/ */
public synchronized static FlowExecutionRepository getExecutionRepository(FacesContext context) { public synchronized static FlowExecutionRepository getExecutionRepository(FacesContext context) {
// note: synchronized because this sets the defaultExecutionRepository static member
ApplicationContext ac = FacesContextUtils.getRequiredWebApplicationContext(context); ApplicationContext ac = FacesContextUtils.getRequiredWebApplicationContext(context);
if (ac.containsBean(FLOW_EXECUTION_REPOSITORY_BEAN_NAME)) { if (ac.containsBean(FLOW_EXECUTION_REPOSITORY_BEAN_NAME)) {
return (FlowExecutionRepository) ac.getBean(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 * 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 * 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 * 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 * @param context the faces context
* @return the flow execution factory * @return the flow execution factory
*/ */
public synchronized static FlowExecutionFactory getExecutionFactory(FacesContext context) { public synchronized static FlowExecutionFactory getExecutionFactory(FacesContext context) {
// note: synchronized because this sets the defaultExecutionFactory static member
ApplicationContext ac = FacesContextUtils.getRequiredWebApplicationContext(context); ApplicationContext ac = FacesContextUtils.getRequiredWebApplicationContext(context);
if (ac.containsBean(FLOW_EXECUTION_FACTORY_BEAN_NAME)) { if (ac.containsBean(FLOW_EXECUTION_FACTORY_BEAN_NAME)) {
return (FlowExecutionFactory) ac.getBean(FLOW_EXECUTION_FACTORY_BEAN_NAME, FlowExecutionFactory.class); return (FlowExecutionFactory) ac.getBean(FLOW_EXECUTION_FACTORY_BEAN_NAME, FlowExecutionFactory.class);
@@ -155,7 +160,7 @@ public class FlowFacesUtils {
* @param context the faces context * @param context the faces context
* @return the flow executor, or null if no such bean exists * @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); ApplicationContext ac = FacesContextUtils.getRequiredWebApplicationContext(context);
if (ac.containsBean(FLOW_EXECUTOR_BEAN_NAME)) { if (ac.containsBean(FLOW_EXECUTOR_BEAN_NAME)) {
return (FlowExecutorImpl) ac.getBean(FLOW_EXECUTOR_BEAN_NAME, FlowExecutorImpl.class); return (FlowExecutorImpl) ac.getBean(FLOW_EXECUTOR_BEAN_NAME, FlowExecutorImpl.class);

View File

@@ -411,7 +411,6 @@ public class FlowPhaseListener implements PhaseListener {
* holder component implementation, for example--to handle flow execution restoration/access exceptions in a certain * holder component implementation, for example--to handle flow execution restoration/access exceptions in a certain
* way. * way.
* @return the flow execution key state holder * @return the flow execution key state holder
* @see #saveInViewRoot(FacesContext, String)
*/ */
protected FlowExecutionKeyStateHolder createFlowExecutionKeyStateHolder() { protected FlowExecutionKeyStateHolder createFlowExecutionKeyStateHolder() {
return new FlowExecutionKeyStateHolder(); 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 static class DefaultViewIdMapper implements ViewIdMapper {
public String mapViewId(String viewName) { public String mapViewId(String viewName) {
return viewName; return viewName;
} }

View File

@@ -26,10 +26,10 @@ import org.springframework.web.jsf.FacesContextUtils;
import org.springframework.webflow.execution.FlowExecution; import org.springframework.webflow.execution.FlowExecution;
/** /**
* Custom property resolver that resolves flow session scope attributes of the current flow execution. This resolver * Custom property resolver that resolves flow scope attributes of the current flow execution. This resolver will also
* will also create and set the attribute value to a bean from the root Spring Web Application Context if the value does * create and set the attribute value to a bean from the root Spring Web Application Context if the value does not
* not already exist, allowing for lazy-initialized binding variables. * already exist, allowing for lazy-initialized binding variables.
* * <p>
* Designed mainly to be used with the {@link FlowVariableResolver}. This is the original property resolver implemented * 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 * with Spring Web Flow 1.0. In general, prefer {@link DelegatingFlowVariableResolver} or
* {@link FlowExecutionVariableResolver} over use of this class. Also, consider use of the * {@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); Object value = execution.getActiveSession().getScope().get(attributeName);
// note that MyFaces returns Object.class for a null value here, but // 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 // 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 // for a map value which doesn' even exist
return (value == null) ? null : value.getClass(); return (value == null) ? null : value.getClass();
} }

View File

@@ -27,7 +27,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.webflow.context.ExternalContextHolder; 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. * to ensure no possibility of a flow execution remaining locked due to an uncaught JSF exception.
* *
* @author Ben Hale * @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 * 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 * execution if necessary and setting the holder to null in the request. Can be safely called even if no execution
* is bound but not locked. * is bound or one is bound but not locked.
* @param request the servlet request * @param request the servlet request
*/ */
private void cleanupCurrentFlowExecution(ServletRequest request) { private void cleanupCurrentFlowExecution(ServletRequest request) {

View File

@@ -23,11 +23,11 @@ import javax.faces.el.VariableResolver;
* Custom variable resolver that resolves the current FlowExecution object for binding expressions prefixed with * 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 #FLOW_SCOPE_VARIABLE}. For instance "flowScope.myBean.myProperty". Designed to be used in conjunction with
* {@link FlowPropertyResolver} only. * {@link FlowPropertyResolver} only.
* * <p>
* This class is the original flow execution variable resolver implementation introduced in Spring Web Flow's JSF * 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 * 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. * {@link FlowExecutionVariableResolver} to this implementation as they are both considerably more flexible.
* * <p>
* This resolver should only be used with the {@link FlowPropertyResolver} which can only resolve flow-scoped variables. * 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. * May be deprecated in a future release of Spring Web Flow.
* *

View File

@@ -152,8 +152,14 @@ public class JsfExternalContext implements ExternalContext {
this.outcome = outcome; 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. * An accessor of a JSF session map.
*
* @author Keith Donald * @author Keith Donald
*/ */
private static class SessionSharedMap extends SharedMapDecorator { 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 * @author Keith Donald
*/ */
private static class ApplicationSharedMap extends SharedMapDecorator { private static class ApplicationSharedMap extends SharedMapDecorator {
@@ -187,9 +194,4 @@ public class JsfExternalContext implements ExternalContext {
return facesContext.getExternalContext().getContext(); return facesContext.getExternalContext().getContext();
} }
} }
public String toString() {
return new ToStringCreator(this).append("actionId", actionId).append("outcome", outcome).append("facesContext",
facesContext).toString();
}
} }

View File

@@ -24,10 +24,16 @@ import org.springframework.webflow.core.FlowException;
*/ */
public class JsfFlowConfigurationException extends FlowException { public class JsfFlowConfigurationException extends FlowException {
/**
* Create a new configuration exception.
*/
public JsfFlowConfigurationException(String msg) { public JsfFlowConfigurationException(String msg) {
super(msg); super(msg);
} }
/**
* Create a new configuration exception caused by an underlying exception.
*/
public JsfFlowConfigurationException(String msg, Throwable cause) { public JsfFlowConfigurationException(String msg, Throwable cause) {
super(msg, cause); super(msg, cause);
} }

View File

@@ -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 * 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 * are used to determine if the current view has changed and to create views by delegating to the application's
* {@link ViewHandler}. * {@link ViewHandler}.
* * <p>
* A view handler typically treats a JSF view id as the physical location of a view template encapsulating a page * 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 * 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 * typically replace the suffix of any view id with their own default suffix (e.g. ".jsp" or ".xhtml") and then try to