diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/FlowExecutionImpl.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/FlowExecutionImpl.java
index bf08c425..499717fb 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/FlowExecutionImpl.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/FlowExecutionImpl.java
@@ -242,7 +242,8 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
}
public void resume(ExternalContext externalContext) throws FlowExecutionException, IllegalStateException {
- Assert.state(status == FlowExecutionStatus.STARTED, "This flow execution cannot be resumed; it is not active");
+ Assert.state(status == FlowExecutionStatus.STARTED,
+ "This flow execution cannot be resumed; it is not started or has ended");
if (logger.isDebugEnabled()) {
logger.debug("Resuming in " + externalContext);
}
@@ -376,6 +377,9 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
void endActiveFlowSession(String outcome, MutableAttributeMap output, RequestControlContext context) {
FlowSessionImpl session = getActiveSessionInternal();
+ if (session == null) {
+ throw new IllegalArgumentException("Cannot end the active FlowSession when one has not been activated");
+ }
if (session.isRoot()) {
status = FlowExecutionStatus.ENDING;
}
@@ -548,18 +552,16 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
* @return the new flow session
*/
private FlowSessionImpl activateSession(Flow flow) {
- FlowSessionImpl session;
- if (!flowSessions.isEmpty()) {
- FlowSessionImpl parent = getActiveSessionInternal();
- session = createFlowSession(flow, parent);
- } else {
- session = createFlowSession(flow, null);
- }
+ FlowSessionImpl parent = getActiveSessionInternal();
+ FlowSessionImpl session = createFlowSession(flow, parent);
flowSessions.add(session);
return session;
}
private FlowSessionImpl getActiveSessionInternal() {
+ if (flowSessions.isEmpty()) {
+ return null;
+ }
return (FlowSessionImpl) flowSessions.getLast();
}
@@ -645,8 +647,9 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
* Returns the current flow which may or may not yet be active.
*/
private Flow getCurrentFlow() {
- if (isActive()) {
- return getActiveSessionInternal().getFlow();
+ FlowSessionImpl session = getActiveSessionInternal();
+ if (session != null) {
+ return session.getFlow();
} else {
return flow;
}
@@ -654,8 +657,11 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
private State getCurrentState() {
FlowSessionImpl session = getActiveSessionInternal();
- State currentState = (State) session.getState();
- return currentState;
+ if (session != null) {
+ return (State) session.getState();
+ } else {
+ return null;
+ }
}
}
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/RequestControlContextImpl.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/RequestControlContextImpl.java
index a29726cf..80be2f31 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/RequestControlContextImpl.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/impl/RequestControlContextImpl.java
@@ -32,6 +32,7 @@ import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.FlowExecutionContext;
import org.springframework.webflow.execution.FlowExecutionException;
import org.springframework.webflow.execution.FlowExecutionKey;
+import org.springframework.webflow.execution.FlowSession;
import org.springframework.webflow.execution.View;
/**
@@ -98,11 +99,13 @@ class RequestControlContextImpl implements RequestControlContext {
// implementing RequestContext
public FlowDefinition getActiveFlow() {
- return flowExecution.getActiveSession().getDefinition();
+ FlowSession session = flowExecution.getActiveSession();
+ return session != null ? session.getDefinition() : null;
}
public StateDefinition getCurrentState() {
- return flowExecution.getActiveSession().getState();
+ FlowSession session = flowExecution.getActiveSession();
+ return session != null ? session.getState() : null;
}
public TransitionDefinition getMatchingTransition(String eventId) throws IllegalStateException {
@@ -122,11 +125,13 @@ class RequestControlContextImpl implements RequestControlContext {
}
public MutableAttributeMap getViewScope() throws IllegalStateException {
- return flowExecution.getActiveSession().getViewScope();
+ FlowSession session = flowExecution.getActiveSession();
+ return session != null ? session.getViewScope() : null;
}
public MutableAttributeMap getFlowScope() {
- return flowExecution.getActiveSession().getScope();
+ FlowSession session = flowExecution.getActiveSession();
+ return session != null ? session.getScope() : null;
}
public MutableAttributeMap getConversationScope() {
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionContext.java b/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionContext.java
index 181f26e2..87915df4 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionContext.java
@@ -90,9 +90,9 @@ public interface FlowExecutionContext {
/**
* Returns the active flow session of this flow execution. The active flow session is the currently executing
* session. It may be the "root flow" session, or it may be a subflow session if this flow execution has spawned a
- * subflow. Returns null of this flow execution is in the process of starting or has ended.
+ * subflow. Returns null of this flow execution is in the process of starting.
* @return the active flow session
- * @throws IllegalStateException if this flow execution has not been started at all
+ * @throws IllegalStateException if this flow execution has not been started at all or has ended
*/
public FlowSession getActiveSession() throws IllegalStateException;
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/execution/RequestContext.java b/spring-webflow/src/main/java/org/springframework/webflow/execution/RequestContext.java
index a492a7e6..09a0c627 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/execution/RequestContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/execution/RequestContext.java
@@ -106,17 +106,21 @@ public interface RequestContext {
/**
* Returns a mutable map for accessing and/or setting attributes in view scope. View scoped attributes exist for
* the life of the current view state.
- * @return the view scope
+ * @return the view scope, or null if the flow execution is in the process of starting but has not yet completed
+ * startup
* @see #inViewState()
- * @throws IllegalStateException this flow is not in a view-state
+ * @throws IllegalStateException if this flow is not in a view-state, or the flow execution has not been started at
+ * all or has ended
*/
public MutableAttributeMap getViewScope() throws IllegalStateException;
/**
* Returns a mutable map for accessing and/or setting attributes in flow scope. Flow scoped attributes exist for
* the life of the active flow session.
- * @return the flow scope
+ * @return the flow scope, or null if the the flow execution is in the process of starting but has not yet completed
+ * startup
* @see FlowSession
+ * @throws IllegalStateException if the flow execution has not been started at all or has ended
*/
public MutableAttributeMap getFlowScope();
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/FlowExecutionImplTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/FlowExecutionImplTests.java
index 74f712de..eceae582 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/FlowExecutionImplTests.java
+++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/impl/FlowExecutionImplTests.java
@@ -148,6 +148,8 @@ public class FlowExecutionImplTests extends TestCase {
} catch (FlowExecutionException e) {
assertEquals(flow.getId(), e.getFlowId());
assertNull(e.getStateId());
+ assertTrue(e.getCause() instanceof IllegalStateException);
+ assertTrue(e.getCause().getMessage().equals("Oops"));
}
}