From 4eeb09618f7d3747e9b7de1683cf69061b6090d1 Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Mon, 2 Apr 2007 23:47:46 +0000 Subject: [PATCH] delegating flow resolver --- .../src/main/webapp/WEB-INF/faces-config.xml | 27 ++----- .../webapp/WEB-INF/flows/sellitem-flow.xml | 4 +- .../main/webapp/WEB-INF/webflow-config.xml | 21 ----- .../src/main/webapp/categoryForm.jsp | 9 +-- .../src/main/webapp/priceAndItemCountForm.jsp | 6 +- .../src/main/webapp/shippingDetailsForm.jsp | 11 ++- .../jsf/DelegatingFlowVariableResolver.java | 81 +++++++++++++++++++ .../jsf/FlowExecutionHolderUtils.java | 39 +++++++-- .../jsf/FlowExecutionVariableResolver.java | 7 +- .../executor/jsf/FlowVariableResolver.java | 6 +- 10 files changed, 137 insertions(+), 74 deletions(-) create mode 100644 spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/DelegatingFlowVariableResolver.java diff --git a/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/faces-config.xml b/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/faces-config.xml index 5ea0a83d..95b69676 100644 --- a/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/faces-config.xml +++ b/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/faces-config.xml @@ -1,33 +1,22 @@ - - - org.springframework.web.jsf.DelegatingNavigationHandlerProxy + org.springframework.webflow.executor.jsf.FlowNavigationHandler + + org.springframework.webflow.executor.jsf.FlowExecutionVariableResolver + - org.springframework.webflow.executor.jsf.FlowPropertyResolver + org.springframework.webflow.executor.jsf.FlowExecutionPropertyResolver - - org.springframework.webflow.executor.jsf.FlowVariableResolver - - - org.springframework.web.jsf.DelegatingVariableResolver - - - - org.springframework.web.jsf.WebApplicationContextVariableResolver - - - - - org.springframework.web.jsf.DelegatingPhaseListenerMulticaster - + + org.springframework.webflow.executor.jsf.FlowPhaseListener + \ No newline at end of file diff --git a/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/flows/sellitem-flow.xml b/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/flows/sellitem-flow.xml index 49a7c3a8..52fcab1e 100644 --- a/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/flows/sellitem-flow.xml +++ b/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/flows/sellitem-flow.xml @@ -3,7 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd"> - + + + diff --git a/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/webflow-config.xml b/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/webflow-config.xml index bf4d198d..56e6e88f 100644 --- a/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/webflow-config.xml +++ b/spring-webflow-samples/sellitem-jsf/src/main/webapp/WEB-INF/webflow-config.xml @@ -16,25 +16,4 @@ - - - - - - - - - \ No newline at end of file diff --git a/spring-webflow-samples/sellitem-jsf/src/main/webapp/categoryForm.jsp b/spring-webflow-samples/sellitem-jsf/src/main/webapp/categoryForm.jsp index 0359b6b5..1da2433e 100644 --- a/spring-webflow-samples/sellitem-jsf/src/main/webapp/categoryForm.jsp +++ b/spring-webflow-samples/sellitem-jsf/src/main/webapp/categoryForm.jsp @@ -21,17 +21,17 @@

Select category

- + - + diff --git a/spring-webflow-samples/sellitem-jsf/src/main/webapp/priceAndItemCountForm.jsp b/spring-webflow-samples/sellitem-jsf/src/main/webapp/priceAndItemCountForm.jsp index 328f2633..9b0842da 100644 --- a/spring-webflow-samples/sellitem-jsf/src/main/webapp/priceAndItemCountForm.jsp +++ b/spring-webflow-samples/sellitem-jsf/src/main/webapp/priceAndItemCountForm.jsp @@ -18,7 +18,6 @@
-

Enter price and item count


Price:Price:
Item count:Item count:
Category: - + @@ -41,12 +41,11 @@
Is shipping required?: - +
-
@@ -26,7 +25,7 @@ @@ -37,7 +36,7 @@ @@ -47,7 +46,6 @@ diff --git a/spring-webflow-samples/sellitem-jsf/src/main/webapp/shippingDetailsForm.jsp b/spring-webflow-samples/sellitem-jsf/src/main/webapp/shippingDetailsForm.jsp index 06ebcaad..3499d728 100644 --- a/spring-webflow-samples/sellitem-jsf/src/main/webapp/shippingDetailsForm.jsp +++ b/spring-webflow-samples/sellitem-jsf/src/main/webapp/shippingDetailsForm.jsp @@ -22,22 +22,22 @@
Price: - +
Item count: - +
-
- + - + - + - + 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 new file mode 100644 index 00000000..e9dd0eba --- /dev/null +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/DelegatingFlowVariableResolver.java @@ -0,0 +1,81 @@ +/* + * Copyright 2004-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.webflow.executor.jsf; + +import javax.faces.context.FacesContext; +import javax.faces.el.EvaluationException; +import javax.faces.el.VariableResolver; + +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. + * + * @author Keith Donald + */ +public class DelegatingFlowVariableResolver extends VariableResolver { + + /** + * The standard variable resolver to delegate to if this one doesn't apply. + */ + private VariableResolver resolverDelegate; + + /** + * Create a new FlowExecutionVariableResolver, using the given original VariableResolver. + *

+ * A JSF implementation will automatically pass its original resolver into the constructor of a configured resolver, + * provided that there is a corresponding constructor argument. + * + * @param resolverDelegate the original VariableResolver + */ + public DelegatingFlowVariableResolver(VariableResolver resolverDelegate) { + this.resolverDelegate = resolverDelegate; + } + + /** + * Return the original VariableResolver that this resolver delegates to. + */ + protected final VariableResolver getResolverDelegate() { + return resolverDelegate; + } + + /** + * Check flash/flow/conversation scope. If the variable is not found, delegate to next variable resolver in the + * chain. + */ + public Object resolveVariable(FacesContext context, String name) throws EvaluationException { + FlowExecution execution = FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context); + // try flash/flow/conversation + if (execution.getActiveSession().getFlashMap().contains(name)) { + return execution.getActiveSession().getFlashMap().get(name); + } + else if (execution.getActiveSession().getScope().contains(name)) { + return execution.getActiveSession().getScope().get(name); + } + else if (execution.getConversationScope().contains(name)) { + return execution.getConversationScope().get(name); + } + else { + // neither found a value, delegate to next resolver in the chain + return resolverDelegate.resolveVariable(context, name); + } + } +} \ No newline at end of file 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 0c34d5d7..72ce5945 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 @@ -17,13 +17,15 @@ package org.springframework.webflow.executor.jsf; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; +import javax.faces.el.EvaluationException; + +import org.springframework.webflow.execution.FlowExecution; /** * A static utility class for accessing the current flow execution holder. *

- * By default, the current flow execution holder is stored associated with the - * current thread in the {@link FacesContext}'s - * {@link ExternalContext#getRequestMap()}. + * By default, the current flow execution holder is stored associated with the current thread in the + * {@link FacesContext}'s {@link ExternalContext#getRequestMap()}. * * @author Keith Donald * @author Craig McClanahan @@ -36,7 +38,24 @@ public class FlowExecutionHolderUtils { * @return the flow execution holder, or null if none set. */ public static FlowExecutionHolder getFlowExecutionHolder(FacesContext context) { - return (FlowExecutionHolder)context.getExternalContext().getRequestMap().get(getFlowExecutionHolderKey()); + return (FlowExecutionHolder) context.getExternalContext().getRequestMap().get(getFlowExecutionHolderKey()); + } + + /** + * Returns the current flow execution holder for the given faces context. + * @param context faces context + * @return the flow execution holder or null if none set + * @throws EvaluationException if no flow execution was bound + */ + public static FlowExecution getRequiredCurrentFlowExecution(FacesContext context) throws EvaluationException { + FlowExecutionHolder holder = getFlowExecutionHolder(context); + if (holder != null) { + return holder.getFlowExecution(); + } + else { + throw new EvaluationException( + "FlowExecution is not bound to current thread context - has the flow ended or expired?"); + } } /** @@ -48,11 +67,17 @@ public class FlowExecutionHolderUtils { context.getExternalContext().getRequestMap().put(getFlowExecutionHolderKey(), holder); } + /** + * Returns true if the flow execution has been restored in the current thread. + * @param context the faces context + * @return true if restored, false otherwise + */ + public static boolean isFlowExecutionRestored(FacesContext context) { + return getFlowExecutionHolder(context) != null; + } + private static String getFlowExecutionHolderKey() { return FlowExecutionHolder.class.getName(); } - public static boolean isFlowExecutionRestored(FacesContext context) { - return getFlowExecutionHolder(context) != null; - } } \ No newline at end of file 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 e1f69082..7b2799e5 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 @@ -72,12 +72,7 @@ public class FlowExecutionVariableResolver extends VariableResolver { return resolverDelegate.resolveVariable(context, name); } else { - FlowExecutionHolder holder = FlowExecutionHolderUtils.getFlowExecutionHolder(context); - if (holder == null) - throw new EvaluationException("'" + FLOW_EXECUTION_VARIABLE_NAME - + "' variable prefix specified but a FlowExecution is not bound to current thread context: " - + "has the flow ended or expired?"); - return holder.getFlowExecution(); + return FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context); } } } \ No newline at end of file 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 2528ad3c..12c78f08 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 @@ -68,11 +68,7 @@ public class FlowVariableResolver extends VariableResolver { return resolverDelegate.resolveVariable(context, name); } else { - FlowExecutionHolder holder = FlowExecutionHolderUtils.getFlowExecutionHolder(context); - if (holder == null) - throw new EvaluationException( - "'flowScope' variable prefix specified but a FlowExecution is not bound to current thread context - has the flow ended or expired?"); - return holder.getFlowExecution(); + return FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context); } } } \ No newline at end of file

Price:Price:
Item count:Item count:
Category:Category:
Shipping:Shipping:
Shipping type: - + @@ -45,7 +45,6 @@
-