diff --git a/spring-webflow-reference/src/portlet.xml b/spring-webflow-reference/src/portlet.xml
index a6e19b62..190a5d9d 100644
--- a/spring-webflow-reference/src/portlet.xml
+++ b/spring-webflow-reference/src/portlet.xml
@@ -190,6 +190,12 @@ externalContext.requestMap.portletMode
The Portlet API only allows redirects to be requested from an action request.
Because views are rendered on the render request, views and view-states cannot trigger a redirect.
+ The externalRedirect: view prefix is a convenience for Servlet based flows.
+ An IllegalStateException is thrown if a redirect is requested from a render request.
+
+
+ This limitation can be worked around for an end-state by implementing the FlowHandler.handleExecutionOutcome method.
+ This callback provides the ActionResponse object which supports redirects.
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java
index f9018b39..de64c99a 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/context/portlet/PortletExternalContext.java
@@ -235,19 +235,31 @@ public class PortletExternalContext implements ExternalContext {
}
public void requestFlowExecutionRedirect() {
+ if (isRenderPhase()) {
+ throw new IllegalStateException("Redirects are not allowed durring the portlet render phase");
+ }
flowExecutionRedirectRequested = true;
}
public void requestExternalRedirect(String uri) {
+ if (isRenderPhase()) {
+ throw new IllegalStateException("Redirects are not allowed durring the portlet render phase");
+ }
externalRedirectUrl = uri;
}
public void requestFlowDefinitionRedirect(String flowId, MutableAttributeMap input) {
+ if (isRenderPhase()) {
+ throw new IllegalStateException("Redirects are not allowed durring the portlet render phase");
+ }
flowDefinitionRedirectFlowId = flowId;
flowDefinitionRedirectFlowInput = input;
}
public void requestRedirectInPopup() {
+ if (isRenderPhase()) {
+ throw new IllegalStateException("Redirects are not allowed durring the portlet render phase");
+ }
redirectInPopup = true;
}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/context/portlet/PortletExternalContextTests.java b/spring-webflow/src/test/java/org/springframework/webflow/context/portlet/PortletExternalContextTests.java
index 37cf7da7..f31cb01a 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/context/portlet/PortletExternalContextTests.java
+++ b/spring-webflow/src/test/java/org/springframework/webflow/context/portlet/PortletExternalContextTests.java
@@ -22,6 +22,8 @@ import org.springframework.mock.web.portlet.MockActionResponse;
import org.springframework.mock.web.portlet.MockPortletContext;
import org.springframework.mock.web.portlet.MockPortletRequest;
import org.springframework.mock.web.portlet.MockPortletResponse;
+import org.springframework.mock.web.portlet.MockRenderRequest;
+import org.springframework.mock.web.portlet.MockRenderResponse;
import org.springframework.webflow.context.servlet.ServletExternalContext;
/**
@@ -37,11 +39,20 @@ public class PortletExternalContextTests extends TestCase {
private PortletExternalContext context;
+ private MockPortletRequest renderRequest;
+
+ private MockPortletResponse renderResponse;
+
+ private PortletExternalContext renderContext;
+
protected void setUp() {
portletContext = new MockPortletContext();
request = new MockActionRequest();
response = new MockActionResponse();
context = new PortletExternalContext(portletContext, request, response);
+ renderRequest = new MockRenderRequest();
+ renderResponse = new MockRenderResponse();
+ renderContext = new PortletExternalContext(portletContext, renderRequest, renderResponse);
}
public void testGetContextPath() {
@@ -76,18 +87,45 @@ public class PortletExternalContextTests extends TestCase {
assertTrue(context.getFlowExecutionRedirectRequested());
}
+ public void testCommitExecutionRedirectRenderRequest() {
+ try {
+ renderContext.requestFlowExecutionRedirect();
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ // we want this
+ }
+ }
+
public void testCommitFlowRedirect() {
context.requestFlowDefinitionRedirect("foo", null);
assertTrue(context.getFlowDefinitionRedirectRequested());
assertEquals("foo", context.getFlowRedirectFlowId());
}
+ public void testCommitFlowRedirectRenderRequest() {
+ try {
+ renderContext.requestFlowDefinitionRedirect("foo", null);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ // we want this
+ }
+ }
+
public void testCommitExternalRedirect() {
context.requestExternalRedirect("foo");
assertTrue(context.getExternalRedirectRequested());
assertEquals("foo", context.getExternalRedirectUrl());
}
+ public void testCommitExternalRedirectRenderRequest() {
+ try {
+ renderContext.requestExternalRedirect("foo");
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ // we want this
+ }
+ }
+
public void testCommitExecutionRedirectPopup() {
context.requestFlowExecutionRedirect();
context.requestRedirectInPopup();
@@ -111,6 +149,15 @@ public class PortletExternalContextTests extends TestCase {
assertTrue(context.getRedirectInPopup());
}
+ public void testExecutionRedirectPopupRenderRequest() {
+ try {
+ renderContext.requestRedirectInPopup();
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ // we want this
+ }
+ }
+
public void testResponseAllowed() {
assertFalse(context.isResponseAllowed());
}