diff --git a/spring-faces/src/main/java/META-INF/spring-faces/SpringFaces-Dojo.js b/spring-faces/src/main/java/META-INF/spring-faces/SpringFaces-Dojo.js
index b76da745..54dee8ca 100644
--- a/spring-faces/src/main/java/META-INF/spring-faces/SpringFaces-Dojo.js
+++ b/spring-faces/src/main/java/META-INF/spring-faces/SpringFaces-Dojo.js
@@ -104,6 +104,23 @@ SpringFaces.DojoAjaxHandler.prototype = {
handleResponse: function(response, ioArgs) {
//alert("handling the response");
+ //First check if this response should redirect
+ var redirectURL = ioArgs.xhr.getResponseHeader('Flow-Redirect-URL');
+ var modalViewHeader = ioArgs.xhr.getResponseHeader('Flow-Modal-View');
+ var modalView = dojo.isString(modalViewHeader) && modalViewHeader.length > 0;
+
+ if (dojo.isString(redirectURL) && redirectURL.length > 0) {
+ if (modalView) {
+ //render a popup with the new URL
+ SpringFaces.AjaxHandler.renderURLToModalDialog(redirectURL, ioArgs);
+ return response;
+ }
+ else {
+ window.location.pathname = redirectURL;
+ return response;
+ }
+ }
+
//Extract and store all
-
\ No newline at end of file
diff --git a/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xhtml b/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xhtml
index 068f9c36..b8084dff 100755
--- a/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xhtml
+++ b/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xhtml
@@ -33,7 +33,7 @@
-
+
diff --git a/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xml b/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xml
index 694b5231..125ad4f3 100755
--- a/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xml
+++ b/spring-webflow-samples/booking-jsf/src/main/webapp/flow/main/main.xml
@@ -25,7 +25,12 @@
-
+
+
+
+
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java
index 57a2d0b6..610d435d 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/context/ExternalContext.java
@@ -35,6 +35,7 @@ import org.springframework.webflow.core.collection.SharedAttributeMap;
*
* @author Keith Donald
* @author Erwin Vervaet
+ * @author Jeremy Grelle
*/
public interface ExternalContext {
@@ -205,4 +206,12 @@ public interface ExternalContext {
*/
public boolean isResponseCommitted();
+ /**
+ * Returns true if the current request is an Ajax request, determined by the value of the http accept header.
+ * @return true if the current request is an Ajax request
+ */
+ public boolean isAjaxRequest();
+
+ public void setResponseHeader(String name, String value);
+
}
\ 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 2b49b786..3f440996 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
@@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.style.ToStringCreator;
+import org.springframework.util.StringUtils;
import org.springframework.webflow.context.AbstractFlowRequestInfo;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.context.ExternalContextHolder;
@@ -49,12 +50,22 @@ import org.springframework.webflow.executor.FlowExecutor;
*
* @author Keith Donald
* @author Erwin Vervaet
+ * @author Jeremy Grelle
*/
public class ServletExternalContext implements ExternalContext {
/** The default encoding scheme: UTF-8 */
private static final String DEFAULT_ENCODING_SCHEME = "UTF-8";
+ /** The accept header value that signifies an Ajax request */
+ private static final String AJAX_ACCEPT_CONTENT_TYPE = "text/html;type=ajax";
+
+ /** Alternate request paramater to indicate an ajax request for cases when control of the header is not available */
+ private static final String AJAX_SOURCE_PARAM = "ajaxSource";
+
+ /** The response header to be set on an Ajax redirect */
+ private static final String FLOW_REDIRECT_URL_HEADER = "Flow-Redirect-URL";
+
/**
* The context.
*/
@@ -412,7 +423,11 @@ public class ServletExternalContext implements ExternalContext {
}
private void sendRedirect(String targetUrl) throws IOException {
- response.sendRedirect(response.encodeRedirectURL(targetUrl));
+ if (isAjaxRequest()) {
+ setResponseHeader(FLOW_REDIRECT_URL_HEADER, response.encodeRedirectURL(targetUrl));
+ } else {
+ response.sendRedirect(response.encodeRedirectURL(targetUrl));
+ }
}
public String toString() {
@@ -446,7 +461,7 @@ public class ServletExternalContext implements ExternalContext {
public void issueRedirect() throws IOException {
FlowExecutionRequestInfo requestInfo = (FlowExecutionRequestInfo) getRequestInfo();
String targetUrl = buildFlowExecutionUrl(requestInfo, true);
- response.sendRedirect(response.encodeRedirectURL(targetUrl));
+ sendRedirect(targetUrl);
}
}
@@ -458,7 +473,21 @@ public class ServletExternalContext implements ExternalContext {
public void issueRedirect() throws IOException {
FlowDefinitionRequestInfo requestInfo = (FlowDefinitionRequestInfo) getRequestInfo();
String targetUrl = buildFlowDefinitionUrl(requestInfo);
- response.sendRedirect(response.encodeRedirectURL(targetUrl));
+ sendRedirect(targetUrl);
}
}
+
+ public boolean isAjaxRequest() {
+ String acceptHeader = request.getHeader("Accept");
+ String ajaxParam = request.getParameter(AJAX_SOURCE_PARAM);
+ if (AJAX_ACCEPT_CONTENT_TYPE.equals(acceptHeader) || StringUtils.hasText(ajaxParam)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void setResponseHeader(String name, String value) {
+ response.setHeader(name, value);
+ }
}
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java
index e659f3d1..e2be964b 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java
@@ -33,6 +33,10 @@ import org.springframework.webflow.execution.ViewFactory;
*/
public class ViewState extends TransitionableState {
+ private static final String FLOW_MODAL_VIEW_HEADER = "Flow-Modal-View";
+
+ private static final String MODAL_ATTR = "modal";
+
/**
* The list of actions to be executed when this state is entered.
*/
@@ -79,6 +83,10 @@ public class ViewState extends TransitionableState {
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
context.assignFlowExecutionKey();
+ if (context.getExternalContext().isAjaxRequest()
+ && Boolean.TRUE.equals(context.getCurrentState().getAttributes().getBoolean(MODAL_ATTR))) {
+ context.getExternalContext().setResponseHeader(FLOW_MODAL_VIEW_HEADER, "true");
+ }
if (shouldRedirect(context)) {
context.sendFlowExecutionRedirect();
} else {
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java
index acb13306..06641fe8 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java
@@ -17,6 +17,7 @@ package org.springframework.webflow.test;
import java.io.PrintWriter;
import java.util.HashMap;
+import java.util.Map;
import org.springframework.binding.collection.SharedMapDecorator;
import org.springframework.webflow.context.ExternalContext;
@@ -73,6 +74,10 @@ public class MockExternalContext implements ExternalContext {
private FlowException exceptionResult;
+ private boolean ajaxRequest;
+
+ private Map responseHeaders = new HashMap();
+
/**
* Creates a mock external context with an empty request parameter map. Allows for bean style usage.
*/
@@ -302,4 +307,20 @@ public class MockExternalContext implements ExternalContext {
public FlowException getExceptionResult() {
return exceptionResult;
}
+
+ public boolean isAjaxRequest() {
+ return ajaxRequest;
+ }
+
+ public void setAjaxRequest(boolean ajaxRequest) {
+ this.ajaxRequest = ajaxRequest;
+ }
+
+ public void setResponseHeader(String name, String value) {
+ this.responseHeaders.put(name, value);
+ }
+
+ public String getResponseHeader(String name) {
+ return (String) responseHeaders.get(name);
+ }
}
\ No newline at end of file