swf273 and swf276 and swf229

This commit is contained in:
Keith Donald
2007-04-01 12:42:39 +00:00
parent 8688c10ae5
commit 4f8eb72e65
4 changed files with 60 additions and 50 deletions

View File

@@ -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();

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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.
* <p>
* This phase listener implements the following algorithm:
* <ul>
* <li>On BEFORE_RESTORE_VIEW, restore the {@link FlowExecution} the user is
* <p> This phase listener implements the following algorithm: <ul> <li>On
* BEFORE_RESTORE_VIEW, restore the {@link FlowExecution} the user is
* participating in if a call to
* {@link FlowExecutorArgumentHandler#extractFlowExecutionKey(ExternalContext)}
* returns a submitted flow execution identifier. Place the restored flow
* execution in a holder that other JSF artifacts such as VariableResolvers,
* PropertyResolvers, and NavigationHandlers may access during the request
* lifecycle.
* <li>On BEFORE_RENDER_RESPONSE, if a flow execution was restored in the
* RESTORE_VIEW phase generate a new key for identifying the updated execution
* within a the selected {@link FlowExecutionRepository}. Expose managed flow
* execution attributes to the views before rendering.
* <li>On AFTER_RENDER_RESPONSE, if a flow execution was restored in the
* RESTORE_VIEW phase <em>save</em> the updated execution to the repository
* using the new key generated in the BEFORE_RENDER_RESPONSE phase.
* </ul>
* lifecycle. <li>On BEFORE_RENDER_RESPONSE, if a flow execution was restored
* in the RESTORE_VIEW phase generate a new key for identifying the updated
* execution within a the selected {@link FlowExecutionRepository}. Expose
* managed flow execution attributes to the views before rendering. <li>On
* AFTER_RENDER_RESPONSE, if a flow execution was restored in the RESTORE_VIEW
* phase <em>save</em> the updated execution to the repository using the new
* key generated in the BEFORE_RENDER_RESPONSE phase. </ul>
*
* @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) {