diff --git a/spring-webflow-samples/booking-jsf/src/main/webapp/WEB-INF/config/web-application-config.xml b/spring-webflow-samples/booking-jsf/src/main/webapp/WEB-INF/config/web-application-config.xml
index 41f9403e..79ca7c98 100755
--- a/spring-webflow-samples/booking-jsf/src/main/webapp/WEB-INF/config/web-application-config.xml
+++ b/spring-webflow-samples/booking-jsf/src/main/webapp/WEB-INF/config/web-application-config.xml
@@ -11,26 +11,29 @@
+
+
+
+
-
+
-
+
-
-
+
diff --git a/spring-webflow-samples/booking-jsf/src/main/webapp/WEB-INF/web.xml b/spring-webflow-samples/booking-jsf/src/main/webapp/WEB-INF/web.xml
index b24a711c..e6515d92 100755
--- a/spring-webflow-samples/booking-jsf/src/main/webapp/WEB-INF/web.xml
+++ b/spring-webflow-samples/booking-jsf/src/main/webapp/WEB-INF/web.xml
@@ -45,7 +45,7 @@
Spring Web MVC Dispatcher Servlet
- org.springframework.web.servlet.DispacherServlet
+ org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/config/web-application-config.xml
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContextHolder.java b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContextHolder.java
index a7136ead..3c48a463 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContextHolder.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContextHolder.java
@@ -15,8 +15,6 @@
*/
package org.springframework.webflow.context;
-import org.springframework.util.Assert;
-
/**
* Simple holder class that associates an {@link ExternalContext} instance with the current thread. The ExternalContext
* will not be inherited by any child threads spawned by the current thread.
@@ -43,14 +41,13 @@ public final class ExternalContextHolder {
/**
* Return the ExternalContext associated with the current thread, if any.
* @return the current ExternalContext
- * @throws IllegalStateException if no ExternalContext is bound to this thread
*/
public static ExternalContext getExternalContext() {
- Assert.state(externalContextHolder.get() != null, "No external context is bound to this thread");
return (ExternalContext) externalContextHolder.get();
}
// not instantiable
private ExternalContextHolder() {
}
+
}
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java
index a41df447..817c1a43 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/context/servlet/ServletExternalContext.java
@@ -243,6 +243,8 @@ public class ServletExternalContext implements ExternalContext {
private void init(ServletContext context, HttpServletRequest request, HttpServletResponse response,
FlowUrlHandler flowUrlHandler) {
this.context = context;
+ this.request = request;
+ this.response = response;
this.requestParameterMap = new LocalParameterMap(new HttpServletRequestParameterMap(request));
this.requestMap = new LocalAttributeMap(new HttpServletRequestMap(request));
this.sessionMap = new LocalSharedAttributeMap(new HttpSessionMap(request));
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/FlowExecutorImpl.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/FlowExecutorImpl.java
index 5f1c97a4..9957264c 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/executor/FlowExecutorImpl.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/FlowExecutorImpl.java
@@ -17,6 +17,7 @@ package org.springframework.webflow.executor;
import org.springframework.util.Assert;
import org.springframework.webflow.context.ExternalContext;
+import org.springframework.webflow.context.ExternalContextHolder;
import org.springframework.webflow.core.FlowException;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.definition.FlowDefinition;
@@ -104,36 +105,52 @@ public class FlowExecutorImpl implements FlowExecutor {
public FlowExecutionResult launchExecution(String flowId, MutableAttributeMap input, ExternalContext context)
throws FlowException {
- FlowDefinition flowDefinition = definitionLocator.getFlowDefinition(flowId);
- FlowExecution flowExecution = executionFactory.createFlowExecution(flowDefinition);
- flowExecution.start(input, context);
- if (!flowExecution.hasEnded()) {
- executionRepository.putFlowExecution(flowExecution);
- return FlowExecutionResult.createPausedResult(flowExecution.getDefinition().getId(), flowExecution.getKey()
- .toString());
- } else {
- return FlowExecutionResult.createEndedResult(flowExecution.getDefinition().getId(), flowExecution
- .getOutcome());
+ ExternalContextHolder.setExternalContext(context);
+ try {
+ FlowDefinition flowDefinition = definitionLocator.getFlowDefinition(flowId);
+ FlowExecution flowExecution = executionFactory.createFlowExecution(flowDefinition);
+ flowExecution.start(input, context);
+ if (!flowExecution.hasEnded()) {
+ executionRepository.putFlowExecution(flowExecution);
+ return createPausedResult(flowExecution);
+ } else {
+ return createEndResult(flowExecution);
+ }
+ } finally {
+ ExternalContextHolder.setExternalContext(null);
}
}
public FlowExecutionResult resumeExecution(String flowExecutionKey, ExternalContext context) throws FlowException {
- FlowExecutionKey key = executionRepository.parseFlowExecutionKey(flowExecutionKey);
- FlowExecutionLock lock = executionRepository.getLock(key);
try {
- FlowExecution flowExecution = executionRepository.getFlowExecution(key);
- flowExecution.resume(context);
- if (!flowExecution.hasEnded()) {
- executionRepository.putFlowExecution(flowExecution);
- return FlowExecutionResult.createPausedResult(flowExecution.getDefinition().getId(), flowExecution
- .getKey().toString());
- } else {
- executionRepository.removeFlowExecution(flowExecution);
- return FlowExecutionResult.createEndedResult(flowExecution.getDefinition().getId(), flowExecution
- .getOutcome());
+ ExternalContextHolder.setExternalContext(context);
+ FlowExecutionKey key = executionRepository.parseFlowExecutionKey(flowExecutionKey);
+ FlowExecutionLock lock = executionRepository.getLock(key);
+ try {
+ FlowExecution flowExecution = executionRepository.getFlowExecution(key);
+ flowExecution.resume(context);
+ if (!flowExecution.hasEnded()) {
+ executionRepository.putFlowExecution(flowExecution);
+ return createPausedResult(flowExecution);
+ } else {
+ executionRepository.removeFlowExecution(flowExecution);
+ return createEndResult(flowExecution);
+ }
+ } finally {
+ lock.unlock();
}
} finally {
- lock.unlock();
+ ExternalContextHolder.setExternalContext(null);
}
}
+
+ private FlowExecutionResult createEndResult(FlowExecution flowExecution) {
+ return FlowExecutionResult.createEndedResult(flowExecution.getDefinition().getId(), flowExecution.getOutcome());
+ }
+
+ private FlowExecutionResult createPausedResult(FlowExecution flowExecution) {
+ return FlowExecutionResult.createPausedResult(flowExecution.getDefinition().getId(), flowExecution.getKey()
+ .toString());
+ }
+
}
\ No newline at end of file
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/context/servlet/ServletExternalContextTests.java b/spring-webflow/src/test/java/org/springframework/webflow/context/servlet/ServletExternalContextTests.java
index 66588ef1..13f985a5 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/context/servlet/ServletExternalContextTests.java
+++ b/spring-webflow/src/test/java/org/springframework/webflow/context/servlet/ServletExternalContextTests.java
@@ -19,12 +19,15 @@ import junit.framework.TestCase;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
/**
* Unit tests for {@link ServletExternalContext}.
*/
public class ServletExternalContextTests extends TestCase {
+ private MockServletContext servletContext;
+
private MockHttpServletRequest request;
private MockHttpServletResponse response;
@@ -32,12 +35,63 @@ public class ServletExternalContextTests extends TestCase {
private ServletExternalContext context;
protected void setUp() {
+ servletContext = new MockServletContext();
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
+ context = new ServletExternalContext(servletContext, request, response);
}
- public void testtest() {
+ public void testGetContextPath() {
+ request.setContextPath("/foo");
+ assertEquals("/foo", request.getContextPath());
+ }
+ public void testRequestParameters() {
+ assertTrue(context.getRequestParameterMap().isEmpty());
+ }
+
+ public void testGetNativeObjects() {
+ assertEquals(servletContext, context.getNativeContext());
+ assertEquals(request, context.getNativeRequest());
+ assertEquals(response, context.getNativeResponse());
+ }
+
+ public void testNotAnAjaxRequest() {
+ assertFalse(context.isAjaxRequest());
+ }
+
+ public void testAjaxRequestAcceptHeader() {
+ request.addHeader("Accept", "text/html;type=ajax");
+ assertTrue(context.isAjaxRequest());
+ }
+
+ public void testAjaxRequestParam() {
+ request.addParameter("ajaxSource", "myButton");
+ assertTrue(context.isAjaxRequest());
+ }
+
+ public void testNotResponseCommitted() {
+ assertFalse(context.isResponseCommitted());
+ }
+
+ public void testCommitExecutionRedirect() {
+ context.requestFlowExecutionRedirect();
+ assertTrue(context.isResponseCommitted());
+ assertTrue(context.flowExecutionRedirectRequested());
+ }
+
+ public void testCommitFlowRedirect() {
+ context.requestFlowDefinitionRedirect("foo", null);
+ assertTrue(context.isResponseCommitted());
+ assertTrue(context.flowDefinitionRedirectRequested());
+ assertEquals("foo", context.getFlowRedirectFlowId());
+ }
+
+ public void testCommitExternalRedirect() {
+ context.requestExternalRedirect("foo");
+ assertTrue(context.isResponseCommitted());
+ assertTrue(context.externalRedirectRequested());
+ assertEquals("foo", context.getExternalRedirectUrl());
}
}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/executor/FlowExecutorImplTests.java b/spring-webflow/src/test/java/org/springframework/webflow/executor/FlowExecutorImplTests.java
index c7ae49ca..c4d8fde0 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/executor/FlowExecutorImplTests.java
+++ b/spring-webflow/src/test/java/org/springframework/webflow/executor/FlowExecutorImplTests.java
@@ -3,6 +3,7 @@ package org.springframework.webflow.executor;
import junit.framework.TestCase;
import org.easymock.EasyMock;
+import org.springframework.webflow.context.ExternalContextHolder;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.definition.FlowDefinition;
@@ -66,6 +67,7 @@ public class FlowExecutorImplTests extends TestCase {
assertFalse(result.ended());
assertNull(result.getEndedOutcome());
assertNull(result.getEndedOutput());
+ assertNull(ExternalContextHolder.getExternalContext());
verifyMocks();
}
@@ -94,6 +96,7 @@ public class FlowExecutorImplTests extends TestCase {
assertTrue(result.getEndedOutput().isEmpty());
assertFalse(result.paused());
assertNull(result.getPausedKey());
+ assertNull(ExternalContextHolder.getExternalContext());
verifyMocks();
}
@@ -130,6 +133,7 @@ public class FlowExecutorImplTests extends TestCase {
assertFalse(result.ended());
assertNull(result.getEndedOutcome());
assertNull(result.getEndedOutput());
+ assertNull(ExternalContextHolder.getExternalContext());
verifyMocks();
}
@@ -169,7 +173,7 @@ public class FlowExecutorImplTests extends TestCase {
assertEquals(output, result.getEndedOutput());
assertFalse(result.paused());
assertNull(result.getPausedKey());
-
+ assertNull(ExternalContextHolder.getExternalContext());
verifyMocks();
}