From 4f8eb72e6556f7b2287ac4e9166edbe127af285a Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Sun, 1 Apr 2007 12:42:39 +0000 Subject: [PATCH] swf273 and swf276 and swf229 --- .../executor/jsf/FlowExecutionHolder.java | 43 +++++++++---- .../jsf/FlowExecutionHolderUtils.java | 4 -- .../executor/jsf/FlowNavigationHandler.java | 2 - .../executor/jsf/FlowPhaseListener.java | 61 +++++++++---------- 4 files changed, 60 insertions(+), 50 deletions(-) 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 471c49da..f79bd1ae 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 @@ -21,6 +21,7 @@ import org.springframework.core.style.ToStringCreator; import org.springframework.webflow.execution.FlowExecution; import org.springframework.webflow.execution.ViewSelection; import org.springframework.webflow.execution.repository.FlowExecutionKey; +import org.springframework.webflow.execution.repository.FlowExecutionLock; /** * A holder storing a reference to a flow execution and the key of that flow @@ -44,10 +45,16 @@ public class FlowExecutionHolder implements Serializable { */ private FlowExecution flowExecution; + /** + * The lock obtained to exclusively manipulate the flow execution. + */ + private FlowExecutionLock flowExecutionLock; + + /** + * The currently selected view selection for this request. + */ private ViewSelection viewSelection; - - private boolean needsSave; - + /** * Creates a new flow execution holder for a flow execution that has not yet * been placed in a repository. @@ -58,13 +65,17 @@ public class FlowExecutionHolder implements Serializable { } /** - * Creates a new flow execution holder. + * Creates a new flow execution holder for a flow execution that has been + * restored from a repository. * @param flowExecutionKey the continuation key * @param flowExecution the flow execution to hold + * @param flowExecutionLock the lock acquired on the flow execution */ - public FlowExecutionHolder(FlowExecutionKey flowExecutionKey, FlowExecution flowExecution) { + public FlowExecutionHolder(FlowExecutionKey flowExecutionKey, FlowExecution flowExecution, + FlowExecutionLock flowExecutionLock) { this.flowExecutionKey = flowExecutionKey; this.flowExecution = flowExecution; + this.flowExecutionLock = flowExecutionLock; } /** @@ -87,23 +98,29 @@ public class FlowExecutionHolder implements Serializable { public FlowExecution getFlowExecution() { return flowExecution; } + + /** + * Returns the flow execution lock + */ + public FlowExecutionLock getFlowExecutionLock() { + return flowExecutionLock; + } + /** + * Returns the view selected from the current flow execution request. + */ public ViewSelection getViewSelection() { return viewSelection; } + /** + * Sets the selected view from the current flow execution request. + * @param viewSelection the view selection + */ public void setViewSelection(ViewSelection viewSelection) { this.viewSelection = viewSelection; } - public boolean needsSave() { - return needsSave; - } - - public void markNeedsSave() { - this.needsSave = true; - } - public String toString() { return new ToStringCreator(this).append("flowExecutionKey", flowExecutionKey).append("flowExecution", flowExecution).toString(); 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 aac7886b..0c34d5d7 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 @@ -55,8 +55,4 @@ public class FlowExecutionHolderUtils { public static boolean isFlowExecutionRestored(FacesContext context) { return getFlowExecutionHolder(context) != null; } - - public static boolean isFlowExecutionChanged(FacesContext context) { - return isFlowExecutionRestored(context) && getFlowExecutionHolder(context).needsSave(); - } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowNavigationHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowNavigationHandler.java index 663e3a61..8456883f 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowNavigationHandler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowNavigationHandler.java @@ -123,7 +123,6 @@ public class FlowNavigationHandler extends DecoratingNavigationHandler { FlowExecutionHolder holder = FlowExecutionHolderUtils.getFlowExecutionHolder(facesContext); ViewSelection selectedView = holder.getFlowExecution().signalEvent(eventId, context); holder.setViewSelection(selectedView); - holder.markNeedsSave(); } } else { @@ -138,7 +137,6 @@ public class FlowNavigationHandler extends DecoratingNavigationHandler { FlowExecutionHolderUtils.setFlowExecutionHolder(holder, facesContext); ViewSelection selectedView = flowExecution.start(createInput(flowExecution, context), context); holder.setViewSelection(selectedView); - holder.markNeedsSave(); } else { // no flow id submitted, proceed with std navigation 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 b1bcb43f..8da8720f 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 @@ -37,6 +37,7 @@ import org.springframework.webflow.execution.FlowExecution; import org.springframework.webflow.execution.FlowExecutionFactory; import org.springframework.webflow.execution.ViewSelection; import org.springframework.webflow.execution.repository.FlowExecutionKey; +import org.springframework.webflow.execution.repository.FlowExecutionLock; import org.springframework.webflow.execution.repository.FlowExecutionRepository; import org.springframework.webflow.execution.support.ApplicationView; import org.springframework.webflow.execution.support.ExternalRedirect; @@ -51,24 +52,20 @@ import org.springframework.webflow.executor.support.ResponseInstructionHandler; * JSF phase listener that is responsible for managing a {@link FlowExecution} * object representing an active user conversation so that other JSF artifacts * that execute in different phases of the JSF lifecycle may have access to it. - *

- * This phase listener implements the following algorithm: - *

* * @author Colin Sampaleanu * @author Keith Donald @@ -138,9 +135,15 @@ public class FlowPhaseListener implements PhaseListener { public void afterPhase(PhaseEvent event) { if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) { try { - if (FlowExecutionHolderUtils.isFlowExecutionChanged(event.getFacesContext())) { - saveFlowExecution(getCurrentContext(), FlowExecutionHolderUtils.getFlowExecutionHolder(event - .getFacesContext())); + if (FlowExecutionHolderUtils.isFlowExecutionRestored(event.getFacesContext())) { + FlowExecutionHolder holder = FlowExecutionHolderUtils.getFlowExecutionHolder(event + .getFacesContext()); + try { + saveFlowExecution(getCurrentContext(), holder); + } + finally { + holder.getFlowExecutionLock().unlock(); + } } } finally { @@ -163,12 +166,13 @@ public class FlowPhaseListener implements PhaseListener { FlowExecutionRepository repository = getRepository(context); FlowExecutionKey flowExecutionKey = repository.parseFlowExecutionKey(argumentHandler .extractFlowExecutionKey(context)); + FlowExecutionLock lock = repository.getLock(flowExecutionKey); FlowExecution flowExecution = repository.getFlowExecution(flowExecutionKey); if (logger.isDebugEnabled()) { logger.debug("Loaded existing flow execution from repository with id '" + flowExecutionKey + "'"); } - FlowExecutionHolderUtils.setFlowExecutionHolder(new FlowExecutionHolder(flowExecutionKey, flowExecution), - facesContext); + FlowExecutionHolderUtils.setFlowExecutionHolder(new FlowExecutionHolder(flowExecutionKey, flowExecution, + lock), facesContext); } else if (argumentHandler.isFlowIdPresent(context)) { // launch a new flow execution (this could happen as part of a flow @@ -183,7 +187,6 @@ public class FlowPhaseListener implements PhaseListener { logger.debug("Started new flow execution"); } holder.setViewSelection(selectedView); - holder.markNeedsSave(); } } @@ -199,24 +202,20 @@ public class FlowPhaseListener implements PhaseListener { } protected void prepareResponse(final JsfExternalContext context, final FlowExecutionHolder holder) { - if (holder.needsSave()) { - generateKey(context, holder); - } + generateKey(context, holder); ViewSelection selectedView = holder.getViewSelection(); if (selectedView == null) { selectedView = holder.getFlowExecution().refresh(context); holder.setViewSelection(selectedView); } - new ResponseInstructionHandler() { - protected void handleApplicationView(ApplicationView view) throws Exception { prepareApplicationView(context.getFacesContext(), holder); } protected void handleFlowDefinitionRedirect(FlowDefinitionRedirect redirect) throws Exception { - String url = argumentHandler.createFlowDefinitionUrl((FlowDefinitionRedirect) holder.getViewSelection(), - context); + String url = argumentHandler.createFlowDefinitionUrl( + (FlowDefinitionRedirect) holder.getViewSelection(), context); sendRedirect(url, context); } @@ -227,8 +226,8 @@ public class FlowPhaseListener implements PhaseListener { } protected void handleExternalRedirect(ExternalRedirect redirect) throws Exception { - String flowExecutionKey = holder.getFlowExecution().isActive() ? holder.getFlowExecutionKey().toString() - : null; + String flowExecutionKey = holder.getFlowExecution().isActive() ? holder.getFlowExecutionKey() + .toString() : null; String url = argumentHandler.createExternalUrl((ExternalRedirect) holder.getViewSelection(), flowExecutionKey, context); sendRedirect(url, context); @@ -237,7 +236,7 @@ public class FlowPhaseListener implements PhaseListener { protected void handleNull() throws Exception { // nothing to do } - + }.handleQuietly(new ResponseInstruction(holder.getFlowExecution(), selectedView)); } @@ -248,8 +247,8 @@ public class FlowPhaseListener implements PhaseListener { updateViewRoot(facesContext, viewIdMapper.mapViewId(forward.getViewName())); } Map requestMap = facesContext.getExternalContext().getRequestMap(); - argumentHandler.exposeFlowExecutionContext(holder.getFlowExecutionKey().toString(), holder.getFlowExecution(), - requestMap); + String flowExecutionKey = holder.getFlowExecution().isActive() ? holder.getFlowExecutionKey().toString() : null; + argumentHandler.exposeFlowExecutionContext(flowExecutionKey, holder.getFlowExecution(), requestMap); } private void updateViewRoot(FacesContext facesContext, String viewId) {