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 72ce5945..33ed8bcf 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
@@ -41,23 +41,6 @@ public class FlowExecutionHolderUtils {
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?");
- }
- }
-
/**
* Sets the current flow execution holder for the given faces context.
* @param holder the flow execution holder
@@ -75,6 +58,23 @@ public class FlowExecutionHolderUtils {
public static boolean isFlowExecutionRestored(FacesContext context) {
return getFlowExecutionHolder(context) != null;
}
+
+ /**
+ * 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?");
+ }
+ }
private static String getFlowExecutionHolderKey() {
return FlowExecutionHolder.class.getName();
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 ee817682..5c3fbaf8 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
@@ -73,6 +73,12 @@ import org.springframework.webflow.executor.support.ResponseInstructionHandler;
*/
public class FlowPhaseListener implements PhaseListener {
+ /**
+ * The name of the attribute the flow execution key will be tracked under in the JSF View Root for managing the
+ * current flow execution key.
+ */
+ private static final String FLOW_EXECUTION_KEY_VIEW_ROOT_ATTRIBUTE = "_flowExecutionKey";
+
/**
* Logger, usable by subclasses.
*/
@@ -163,7 +169,8 @@ public class FlowPhaseListener implements PhaseListener {
if (event.getPhaseId() == PhaseId.RESTORE_VIEW) {
ExternalContextHolder.setExternalContext(new JsfExternalContext(event.getFacesContext()));
restoreFlowExecution(event.getFacesContext());
- } else if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
+ }
+ else if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
try {
if (FlowExecutionHolderUtils.isFlowExecutionRestored(event.getFacesContext())) {
FlowExecutionHolder holder = FlowExecutionHolderUtils.getFlowExecutionHolder(event
@@ -199,9 +206,10 @@ public class FlowPhaseListener implements PhaseListener {
}
else {
// restore the key from an attribute in the root of the component tree
- flowExecutionKey = repository.parseFlowExecutionKey((String)facesContext.getViewRoot().getAttributes().get("_flowExecutionKey"));
+ flowExecutionKey = repository.parseFlowExecutionKey((String) facesContext.getViewRoot().getAttributes()
+ .get(FLOW_EXECUTION_KEY_VIEW_ROOT_ATTRIBUTE));
// remove it (it should always be placed back before response rendering)
- facesContext.getViewRoot().getAttributes().remove("_flowExecutionKey");
+ facesContext.getViewRoot().getAttributes().remove(FLOW_EXECUTION_KEY_VIEW_ROOT_ATTRIBUTE);
}
FlowExecutionLock lock = repository.getLock(flowExecutionKey);
lock.lock();
@@ -213,8 +221,7 @@ public class FlowPhaseListener implements PhaseListener {
lock), facesContext);
}
else if (argumentHandler.isFlowIdPresent(context)) {
- // launch a new flow execution (this could happen as part of a flow
- // redirect)
+ // launch a new flow execution (this could happen as part of a flow redirect)
String flowId = argumentHandler.extractFlowId(context);
FlowDefinition flowDefinition = getLocator(context).getFlowDefinition(flowId);
FlowExecution flowExecution = getFactory(context).createFlowExecution(flowDefinition);
@@ -245,6 +252,11 @@ public class FlowPhaseListener implements PhaseListener {
}
}
+ /**
+ * Prepare the appropriate JSF response (e.g. rendering a view, sending a redirect, etc).
+ * @param context the context
+ * @param holder the holder
+ */
protected void prepareResponse(final JsfExternalContext context, final FlowExecutionHolder holder) {
generateKey(context, holder);
ViewSelection selectedView = holder.getViewSelection();
@@ -284,20 +296,28 @@ public class FlowPhaseListener implements PhaseListener {
}.handleQuietly(new ResponseInstruction(holder.getFlowExecution(), selectedView));
}
+ /**
+ * Prepare the JSF view for rendering.
+ * @param facesContext the faces context
+ * @param holder the holder of the current flow execution
+ */
protected void prepareApplicationView(FacesContext facesContext, FlowExecutionHolder holder) {
ApplicationView forward = (ApplicationView) holder.getViewSelection();
if (forward != null) {
+ // expose the view's "model map" in the request map
putInto(facesContext.getExternalContext().getRequestMap(), forward.getModel());
+ // update the root component if necessary
updateViewRoot(facesContext, viewIdMapper.mapViewId(forward.getViewName()));
}
- Map requestMap = facesContext.getExternalContext().getRequestMap();
String flowExecutionKey = holder.getFlowExecution().isActive() ? holder.getFlowExecutionKey().toString() : null;
if (flowExecutionKey != null) {
// expose to view root for preservation in the component tree
if (viewRootAttributeMapPresent(facesContext)) {
- facesContext.getViewRoot().getAttributes().put("_flowExecutionKey", flowExecutionKey);
+ facesContext.getViewRoot().getAttributes()
+ .put(FLOW_EXECUTION_KEY_VIEW_ROOT_ATTRIBUTE, flowExecutionKey);
}
}
+ Map requestMap = facesContext.getExternalContext().getRequestMap();
argumentHandler.exposeFlowExecutionContext(flowExecutionKey, holder.getFlowExecution(), requestMap);
}
@@ -326,40 +346,42 @@ public class FlowPhaseListener implements PhaseListener {
}
}
}
-
+
// private helpers
private JsfExternalContext getCurrentContext() {
return (JsfExternalContext) ExternalContextHolder.getExternalContext();
}
-
+
/**
- * Returns true if the root of the component tree contains the flow execution key attribute, used
- * to restore the flow execution on subsequent reqests.
+ * Returns true if the root of the component tree contains the flow execution key attribute, used to restore the
+ * flow execution on subsequent reqests.
* @param facesContext the key
* @return true if yes, false otherwise
*/
private boolean isFlowExecutionKeyInViewRoot(FacesContext facesContext) {
if (viewRootAttributeMapPresent(facesContext)) {
- return facesContext.getViewRoot().getAttributes().containsKey("_flowExecutionKey");
- } else {
+ return facesContext.getViewRoot().getAttributes().containsKey(FLOW_EXECUTION_KEY_VIEW_ROOT_ATTRIBUTE);
+ }
+ else {
return false;
}
}
/**
* Simple little helper that returns true if the view root attribute map is non-null.
- * @param facesContext the faces context
+ * @param facesContext the faces context
* @return true if so, false otherwise
*/
private boolean viewRootAttributeMapPresent(FacesContext facesContext) {
if (facesContext.getViewRoot() != null && facesContext.getViewRoot().getAttributes() != null) {
return true;
- } else {
+ }
+ else {
return false;
}
}
-
+
private void updateViewRoot(FacesContext facesContext, String viewId) {
UIViewRoot viewRoot = facesContext.getViewRoot();
if (viewRoot == null || hasViewChanged(viewRoot, viewId)) {
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 68a5ce19..69b7ba9b 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
@@ -57,8 +57,7 @@ public class FlowPropertyResolver extends PropertyResolver {
return resolverDelegate.getType(base, index);
}
else {
- // can't access flow scope by index, so can't determine type. Return
- // null per JSF spec
+ // can't access flow scope by index, so can't determine type. Return null per JSF spec
return null;
}
}
@@ -88,7 +87,7 @@ public class FlowPropertyResolver extends PropertyResolver {
return resolverDelegate.getValue(base, index);
}
else {
- throw new ReferenceSyntaxException("Cannot apply an index value to Flow map");
+ throw new ReferenceSyntaxException("Cannot apply an index value to flow scope map");
}
}
@@ -97,7 +96,7 @@ public class FlowPropertyResolver extends PropertyResolver {
return resolverDelegate.getValue(base, property);
}
if (!(property instanceof String)) {
- throw new PropertyNotFoundException("Unable to get value from Flow map, as key is non-String");
+ throw new PropertyNotFoundException("Unable to get value from flow scope map - key is non-String");
}
FlowExecution execution = (FlowExecution)base;
String attributeName = (String)property;
@@ -108,8 +107,7 @@ public class FlowPropertyResolver extends PropertyResolver {
WebApplicationContext wac = getWebApplicationContext(context);
if (wac.containsBean(attributeName)) {
// note: this resolver doesn't care, but this should normally be
- // either a stateless singleton bean, or a stateful/stateless
- // prototype
+ // either a stateless singleton bean, or a stateful/stateless prototype
value = wac.getBean(attributeName);
execution.getActiveSession().getScope().put(attributeName, value);
}
@@ -135,7 +133,7 @@ public class FlowPropertyResolver extends PropertyResolver {
if (!(base instanceof FlowExecution)) {
resolverDelegate.setValue(base, index, value);
}
- throw new ReferenceSyntaxException("Can not apply an index value to Flow map");
+ throw new ReferenceSyntaxException("Cannot apply an index value to flow scope");
}
public void setValue(Object base, Object property, Object value) throws EvaluationException,
@@ -147,7 +145,7 @@ public class FlowPropertyResolver extends PropertyResolver {
if (property == null || !(property instanceof String)
|| ((String)property).length() == 0) {
throw new PropertyNotFoundException(
- "Attempt to set Flow attribute with null name, empty name, or non-String name");
+ "Attempt to set flow attribute with null name, empty name, or non-String name");
}
FlowExecution execution = (FlowExecution)base;
execution.getActiveSession().getScope().put((String)property, value);