From 30ea4171b033340baeaaf31d6ad0ca2fdc17799a Mon Sep 17 00:00:00 2001 From: Jeremy Grelle Date: Wed, 12 Mar 2008 20:57:39 +0000 Subject: [PATCH] Richfaces integration. --- spring-faces/ivy.xml | 1 + .../src/main/java/META-INF/faces-config.xml | 1 - .../faces/mvc/JsfController.java | 16 +++++ .../springframework/faces/mvc/JsfView.java | 2 +- .../mvc/richfaces/RichFacesAjaxHandler.java | 67 +++++++++++++++++++ .../faces/webflow/FlowFacesContext.java | 22 +++++- .../faces/webflow/FlowLifecycle.java | 14 +++- .../faces/webflow/JsfView.java | 18 ++--- .../faces/webflow/JsfViewFactory.java | 27 +++++--- .../faces/webflow/JsfViewFactoryCreator.java | 11 +-- .../faces/webflow/JsfViewFactoryTests.java | 14 +++- .../faces/webflow/JsfViewTests.java | 16 +++-- .../webflow/execution/View.java | 2 +- .../webflow/mvc/AjaxHandler.java | 8 ++- .../webflow/mvc/FlowController.java | 16 ++--- .../webflow/mvc/FlowHandlerAdapter.java | 16 ++--- .../mvc/SpringJavascriptAjaxHandler.java | 8 ++- 17 files changed, 193 insertions(+), 66 deletions(-) create mode 100644 spring-faces/src/main/java/org/springframework/faces/mvc/JsfController.java create mode 100644 spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java diff --git a/spring-faces/ivy.xml b/spring-faces/ivy.xml index b02cb07f..5db6ac0e 100644 --- a/spring-faces/ivy.xml +++ b/spring-faces/ivy.xml @@ -21,6 +21,7 @@ + diff --git a/spring-faces/src/main/java/META-INF/faces-config.xml b/spring-faces/src/main/java/META-INF/faces-config.xml index 99d5dfb7..e279da38 100644 --- a/spring-faces/src/main/java/META-INF/faces-config.xml +++ b/spring-faces/src/main/java/META-INF/faces-config.xml @@ -10,7 +10,6 @@ org.springframework.faces.model.SelectionTrackingActionListener org.springframework.faces.webflow.FlowVariableResolver org.springframework.faces.webflow.FlowPropertyResolver - org.springframework.faces.webflow.FlowViewStateManager org.springframework.faces.webflow.FlowViewHandler diff --git a/spring-faces/src/main/java/org/springframework/faces/mvc/JsfController.java b/spring-faces/src/main/java/org/springframework/faces/mvc/JsfController.java new file mode 100644 index 00000000..914d3b17 --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/mvc/JsfController.java @@ -0,0 +1,16 @@ +package org.springframework.faces.mvc; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +public class JsfController extends AbstractController { + + protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Auto-generated method stub"); + } + +} diff --git a/spring-faces/src/main/java/org/springframework/faces/mvc/JsfView.java b/spring-faces/src/main/java/org/springframework/faces/mvc/JsfView.java index c6db6e25..ec2b84ba 100644 --- a/spring-faces/src/main/java/org/springframework/faces/mvc/JsfView.java +++ b/spring-faces/src/main/java/org/springframework/faces/mvc/JsfView.java @@ -85,7 +85,7 @@ public class JsfView extends AbstractUrlBasedView { private void populateRequestMap(FacesContext facesContext, Map model) { Iterator i = model.keySet().iterator(); while (i.hasNext()) { - Object key = i.next(); + String key = i.next().toString(); facesContext.getExternalContext().getRequestMap().put(key, model.get(key)); } } diff --git a/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java b/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java new file mode 100644 index 00000000..9c6f5a51 --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java @@ -0,0 +1,67 @@ +package org.springframework.faces.mvc.richfaces; + +import java.io.IOException; + +import javax.faces.FactoryFinder; +import javax.faces.context.FacesContext; +import javax.faces.context.FacesContextFactory; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.ajax4jsf.context.AjaxContext; +import org.springframework.faces.webflow.FlowLifecycle; +import org.springframework.webflow.mvc.SpringJavascriptAjaxHandler; + +public class RichFacesAjaxHandler extends SpringJavascriptAjaxHandler { + + public boolean isAjaxRequest(ServletContext context, HttpServletRequest request, HttpServletResponse response) { + FacesContextHelper helper = new FacesContextHelper(); + if (AjaxContext.getCurrentInstance(helper.getFacesContext(context, request, response)).isAjaxRequest( + helper.getFacesContext(context, request, response))) { + helper.cleanup(); + return true; + } else { + helper.cleanup(); + return super.isAjaxRequest(context, request, response); + } + } + + public void sendAjaxRedirect(ServletContext context, HttpServletRequest request, HttpServletResponse response, + String targetUrl, boolean popup) throws IOException { + FacesContextHelper helper = new FacesContextHelper(); + if (AjaxContext.getCurrentInstance(helper.getFacesContext(context, request, response)).isAjaxRequest( + helper.getFacesContext(context, request, response))) { + helper.cleanup(); + response.sendRedirect(response.encodeRedirectURL(targetUrl)); + } else { + helper.cleanup(); + super.sendAjaxRedirect(context, request, response, targetUrl, popup); + } + } + + private static class FacesContextHelper { + + private boolean created = false; + + protected FacesContext getFacesContext(ServletContext context, HttpServletRequest request, + HttpServletResponse response) { + if (FacesContext.getCurrentInstance() != null) { + return FacesContext.getCurrentInstance(); + } else { + created = true; + FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder + .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); + FacesContext defaultFacesContext = facesContextFactory.getFacesContext(context, request, response, + FlowLifecycle.newInstance()); + return defaultFacesContext; + } + } + + protected void cleanup() { + if (created) { + FacesContext.getCurrentInstance().release(); + } + } + } +} diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContext.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContext.java index a3f783ab..1f53967f 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContext.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContext.java @@ -19,13 +19,16 @@ import java.lang.reflect.Method; import java.util.Iterator; import javax.el.ELContext; +import javax.faces.FactoryFinder; import javax.faces.application.Application; import javax.faces.application.FacesMessage; import javax.faces.component.UIViewRoot; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; +import javax.faces.context.FacesContextFactory; import javax.faces.context.ResponseStream; import javax.faces.context.ResponseWriter; +import javax.faces.lifecycle.Lifecycle; import javax.faces.render.RenderKit; import org.springframework.binding.message.Message; @@ -47,12 +50,12 @@ public class FlowFacesContext extends FacesContext { /** * The key for storing the responseComplete flag */ - static final String RESPONSE_COMPLETE_KEY = "responseComplete"; + static final String RESPONSE_COMPLETE_KEY = "webFlowResponseComplete"; /** * The key for storing the renderResponse flag */ - static final String RENDER_RESPONSE_KEY = "renderResponse"; + static final String RENDER_RESPONSE_KEY = "webFlowRenderResponse"; /** * The key for storing the renderResponse flag @@ -64,6 +67,21 @@ public class FlowFacesContext extends FacesContext { */ private FacesContext delegate; + public static FlowFacesContext newInstance(RequestContext context, Lifecycle lifecycle) { + FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder + .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); + FacesContext defaultFacesContext = facesContextFactory.getFacesContext(context.getExternalContext() + .getNativeContext(), context.getExternalContext().getNativeRequest(), context.getExternalContext() + .getNativeResponse(), lifecycle); + FlowFacesContext instance = new FlowFacesContext(context, defaultFacesContext); + + // Ensure that FlowViewStateManager is first in the chain + FlowViewStateManager sm = new FlowViewStateManager(instance.getApplication().getStateManager()); + instance.getApplication().setStateManager(sm); + + return instance; + } + public FlowFacesContext(RequestContext context, FacesContext delegate) { this.context = context; this.delegate = delegate; diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowLifecycle.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowLifecycle.java index b4868cf4..420c1c7e 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowLifecycle.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowLifecycle.java @@ -16,10 +16,12 @@ package org.springframework.faces.webflow; import javax.faces.FacesException; +import javax.faces.FactoryFinder; import javax.faces.context.FacesContext; import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; import javax.faces.lifecycle.Lifecycle; +import javax.faces.lifecycle.LifecycleFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -33,13 +35,21 @@ import org.apache.commons.logging.LogFactory; * * @author Jeremy Grelle */ -class FlowLifecycle extends Lifecycle { +public class FlowLifecycle extends Lifecycle { private static final Log logger = LogFactory.getLog(FlowLifecycle.class); private final Lifecycle delegate; - public FlowLifecycle(Lifecycle delegate) { + public static Lifecycle newInstance() { + LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder + .getFactory(FactoryFinder.LIFECYCLE_FACTORY); + Lifecycle defaultLifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE); + return new FlowLifecycle(defaultLifecycle); + + } + + FlowLifecycle(Lifecycle delegate) { this.delegate = delegate; } diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfView.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfView.java index ebe6c3a2..255ac393 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfView.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfView.java @@ -18,10 +18,8 @@ package org.springframework.faces.webflow; import java.io.IOException; import javax.faces.FacesException; -import javax.faces.FactoryFinder; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; -import javax.faces.context.FacesContextFactory; import javax.faces.event.PhaseId; import javax.faces.lifecycle.Lifecycle; @@ -51,8 +49,11 @@ public class JsfView implements View { private RequestContext context; + private String viewId; + public JsfView(UIViewRoot viewRoot, Lifecycle facesLifecycle, RequestContext context) { this.viewRoot = viewRoot; + this.viewId = viewRoot.getViewId(); this.facesLifecycle = facesLifecycle; this.context = context; } @@ -74,7 +75,7 @@ public class JsfView implements View { * This implementation performs the standard duties of the JSF RENDER_RESPONSE phase. */ public void render() throws IOException { - FacesContext facesContext = createFlowFacesContext(); + FacesContext facesContext = FlowFacesContext.newInstance(context, facesLifecycle); facesContext.setViewRoot(viewRoot); facesContext.renderResponse(); try { @@ -91,16 +92,7 @@ public class JsfView implements View { } } - private FacesContext createFlowFacesContext() { - FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder - .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); - FacesContext defaultFacesContext = facesContextFactory.getFacesContext(context.getExternalContext() - .getNativeContext(), context.getExternalContext().getNativeRequest(), context.getExternalContext() - .getNativeResponse(), facesLifecycle); - return new FlowFacesContext(context, defaultFacesContext); - } - public String toString() { - return "[JSFView = '" + viewRoot.getViewId() + "']"; + return "[JSFView = '" + viewId + "']"; } } \ No newline at end of file diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java index ccf9ffbf..ec0a6a29 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java @@ -17,15 +17,16 @@ package org.springframework.faces.webflow; import java.util.Iterator; -import javax.faces.FactoryFinder; import javax.faces.application.ViewHandler; import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; -import javax.faces.context.FacesContextFactory; import javax.faces.el.ValueBinding; import javax.faces.event.PhaseId; import javax.faces.lifecycle.Lifecycle; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -33,9 +34,12 @@ import org.springframework.binding.expression.Expression; import org.springframework.core.io.ContextResource; import org.springframework.core.io.ResourceLoader; import org.springframework.faces.ui.AjaxViewRoot; +import org.springframework.webflow.context.ExternalContext; import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.View; import org.springframework.webflow.execution.ViewFactory; +import org.springframework.webflow.mvc.AjaxHandler; +import org.springframework.webflow.mvc.SpringJavascriptAjaxHandler; /** * JSF-specific {@link ViewFactory} implementation. @@ -64,7 +68,7 @@ public class JsfViewFactory implements ViewFactory { public View getView(RequestContext context) { - FacesContext facesContext = createFlowFacesContext(context, lifecycle); + FacesContext facesContext = FlowFacesContext.newInstance(context, lifecycle); try { boolean restored = false; @@ -118,20 +122,21 @@ public class JsfViewFactory implements ViewFactory { } private JsfView createJsfView(UIViewRoot root, Lifecycle lifecycle, RequestContext context) { - if (context.getExternalContext().isAjaxRequest()) { + if (isSpringJavascriptAjaxRequest(context.getExternalContext())) { return new JsfView(new AjaxViewRoot(root), lifecycle, context); } else { return new JsfView(root, lifecycle, context); } } - private FacesContext createFlowFacesContext(RequestContext context, Lifecycle lifecycle) { - FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder - .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); - FacesContext defaultFacesContext = facesContextFactory.getFacesContext(context.getExternalContext() - .getNativeContext(), context.getExternalContext().getNativeRequest(), context.getExternalContext() - .getNativeResponse(), lifecycle); - return new FlowFacesContext(context, defaultFacesContext); + private boolean isSpringJavascriptAjaxRequest(ExternalContext context) { + if (context.getNativeContext() instanceof ServletContext) { + AjaxHandler handler = new SpringJavascriptAjaxHandler(); + return handler.isAjaxRequest((ServletContext) context.getNativeContext(), (HttpServletRequest) context + .getNativeRequest(), (HttpServletResponse) context.getNativeResponse()); + } else { + return false; + } } private String resolveViewName(RequestContext context) { diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactoryCreator.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactoryCreator.java index 11a7cc74..9175ca55 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactoryCreator.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactoryCreator.java @@ -15,9 +15,7 @@ */ package org.springframework.faces.webflow; -import javax.faces.FactoryFinder; import javax.faces.lifecycle.Lifecycle; -import javax.faces.lifecycle.LifecycleFactory; import org.springframework.binding.expression.Expression; import org.springframework.core.io.ResourceLoader; @@ -43,16 +41,9 @@ public class JsfViewFactoryCreator implements ViewFactoryCreator { return viewStateId + FACELETS_EXTENSION; } - private Lifecycle createFlowFacesLifecycle() { - LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder - .getFactory(FactoryFinder.LIFECYCLE_FACTORY); - Lifecycle defaultLifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE); - return new FlowLifecycle(defaultLifecycle); - } - private Lifecycle getLifecycle() { if (lifecycle == null) { - lifecycle = createFlowFacesLifecycle(); + lifecycle = FlowLifecycle.newInstance(); } return lifecycle; } diff --git a/spring-faces/src/test/java/org/springframework/faces/webflow/JsfViewFactoryTests.java b/spring-faces/src/test/java/org/springframework/faces/webflow/JsfViewFactoryTests.java index 8da33eb9..9fbcd8f9 100644 --- a/spring-faces/src/test/java/org/springframework/faces/webflow/JsfViewFactoryTests.java +++ b/spring-faces/src/test/java/org/springframework/faces/webflow/JsfViewFactoryTests.java @@ -20,6 +20,9 @@ import org.jboss.el.ExpressionFactoryImpl; import org.springframework.binding.expression.ExpressionParser; import org.springframework.binding.expression.support.ParserContextImpl; import org.springframework.faces.ui.AjaxViewRoot; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockServletContext; import org.springframework.webflow.core.collection.AttributeMap; import org.springframework.webflow.core.collection.LocalAttributeMap; import org.springframework.webflow.core.collection.LocalParameterMap; @@ -54,10 +57,19 @@ public class JsfViewFactoryTests extends TestCase { private MockExternalContext extContext = new MockExternalContext(); + private MockServletContext servletContext = new MockServletContext(); + + private MockHttpServletRequest request = new MockHttpServletRequest(); + + private MockHttpServletResponse response = new MockHttpServletResponse(); + private String event = "foo"; protected void setUp() throws Exception { configureJsf(); + extContext.setNativeContext(servletContext); + extContext.setNativeRequest(request); + extContext.setNativeResponse(response); RequestContextHolder.setRequestContext(context); EasyMock.expect(context.getFlashScope()).andStubReturn(flashMap); EasyMock.expect(context.getExternalContext()).andStubReturn(extContext); @@ -138,7 +150,7 @@ public class JsfViewFactoryTests extends TestCase { existingRoot.setViewId(VIEW_ID); ((MockViewHandler) viewHandler).setRestoreView(existingRoot); - extContext.setAjaxRequest(true); + request.addHeader("Accept", "text/html;type=ajax"); EasyMock.expect(context.getCurrentState()).andReturn(new ModalViewState()); diff --git a/spring-faces/src/test/java/org/springframework/faces/webflow/JsfViewTests.java b/spring-faces/src/test/java/org/springframework/faces/webflow/JsfViewTests.java index 2e0aef4f..4ff824bf 100644 --- a/spring-faces/src/test/java/org/springframework/faces/webflow/JsfViewTests.java +++ b/spring-faces/src/test/java/org/springframework/faces/webflow/JsfViewTests.java @@ -88,8 +88,12 @@ public class JsfViewTests extends TestCase { EasyMock.expect(requestContext.getFlowScope()).andStubReturn(flowMap); EasyMock.expect(requestContext.getFlowExecutionContext()).andStubReturn(flowExecutionContext); EasyMock.expect(flowExecutionContext.getKey()).andStubReturn(key); - EasyMock.expect(flashMap.put(EasyMock.matches("renderResponse"), EasyMock.anyObject())).andStubReturn(null); - EasyMock.expect(flashMap.put(EasyMock.matches("responseComplete"), EasyMock.anyObject())).andStubReturn(null); + EasyMock.expect( + flashMap.put(EasyMock.matches(FlowFacesContext.RENDER_RESPONSE_KEY), EasyMock + .anyObject())).andStubReturn(null); + EasyMock.expect( + flashMap.put(EasyMock.matches(FlowFacesContext.RESPONSE_COMPLETE_KEY), EasyMock + .anyObject())).andStubReturn(null); EasyMock.replay(new Object[] { requestContext, flowExecutionContext, flowMap, flashMap }); @@ -103,8 +107,12 @@ public class JsfViewTests extends TestCase { EasyMock.expect(requestContext.getExternalContext()).andStubReturn(new MockExternalContext()); EasyMock.expect(requestContext.getFlashScope()).andStubReturn(flashMap); - EasyMock.expect(flashMap.put(EasyMock.matches("renderResponse"), EasyMock.anyObject())).andStubReturn(null); - EasyMock.expect(flashMap.put(EasyMock.matches("responseComplete"), EasyMock.anyObject())).andStubReturn(null); + EasyMock.expect( + flashMap.put(EasyMock.matches(FlowFacesContext.RENDER_RESPONSE_KEY), EasyMock + .anyObject())).andStubReturn(null); + EasyMock.expect( + flashMap.put(EasyMock.matches(FlowFacesContext.RESPONSE_COMPLETE_KEY), EasyMock + .anyObject())).andStubReturn(null); EasyMock.replay(new Object[] { requestContext, flowExecutionContext, flashMap }); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/execution/View.java b/spring-webflow/src/main/java/org/springframework/webflow/execution/View.java index 080efb35..1b3d43a9 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/execution/View.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/execution/View.java @@ -29,7 +29,7 @@ public interface View { /** * Well-known attribute name for storing a render fragments value. */ - public static final String RENDER_FRAGMENTS_ATTRIBUTE = "webflowRenderFragments"; + public static final String RENDER_FRAGMENTS_ATTRIBUTE = "flowRenderFragments"; /** * Render this view's content. diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/AjaxHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/AjaxHandler.java index 029848c2..84534498 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/AjaxHandler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/AjaxHandler.java @@ -15,6 +15,9 @@ */ package org.springframework.webflow.mvc; +import java.io.IOException; + +import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -29,7 +32,7 @@ public interface AjaxHandler { * Is the current request an Ajax request? * @param request the current request */ - public boolean isAjaxRequest(HttpServletRequest request); + public boolean isAjaxRequest(ServletContext context, HttpServletRequest request, HttpServletResponse response); /** * Send a redirect request to the Ajax client. This should cause the client-side agent to send a new request to the @@ -38,5 +41,6 @@ public interface AjaxHandler { * @param targetUrl the target url to redirect to * @param popup wheter the redirect should be sent from a new popup dialog window */ - public void sendAjaxRedirect(HttpServletResponse response, String targetUrl, boolean popup); + public void sendAjaxRedirect(ServletContext context, HttpServletRequest request, HttpServletResponse response, + String targetUrl, boolean popup) throws IOException; } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/FlowController.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/FlowController.java index 0775d57f..b2b51218 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/FlowController.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/FlowController.java @@ -149,7 +149,7 @@ public class FlowController extends AbstractController { protected ServletExternalContext createServletExternalContext(HttpServletRequest request, HttpServletResponse response) { ServletExternalContext context = new ServletExternalContext(getServletContext(), request, response, urlHandler); - context.setAjaxRequest(ajaxHandler.isAjaxRequest(request)); + context.setAjaxRequest(ajaxHandler.isAjaxRequest(getServletContext(), request, response)); return context; } @@ -191,13 +191,13 @@ public class FlowController extends AbstractController { if (logger.isDebugEnabled()) { logger.debug("Sending flow execution redirect to " + url); } - sendRedirect(context, response, url); + sendRedirect(context, request, response, url); return null; } else if (context.externalRedirectRequested()) { if (logger.isDebugEnabled()) { logger.debug("Sending external redirect to " + context.getExternalRedirectUrl()); } - sendRedirect(context, response, context.getExternalRedirectUrl()); + sendRedirect(context, request, response, context.getExternalRedirectUrl()); return null; } else { // nothing to do: flow has handled the response @@ -211,13 +211,13 @@ public class FlowController extends AbstractController { if (logger.isDebugEnabled()) { logger.debug("Sending flow definition to " + url); } - sendRedirect(context, response, url); + sendRedirect(context, request, response, url); return null; } else if (context.externalRedirectRequested()) { if (logger.isDebugEnabled()) { logger.debug("Sending external redirect to " + context.getExternalRedirectUrl()); } - sendRedirect(context, response, context.getExternalRedirectUrl()); + sendRedirect(context, request, response, context.getExternalRedirectUrl()); return null; } else { return handleFlowOutcome(result.getFlowId(), result.getEndedOutcome(), result.getEndedOutput(), @@ -228,10 +228,10 @@ public class FlowController extends AbstractController { } } - private void sendRedirect(ServletExternalContext context, HttpServletResponse response, String targetUrl) - throws IOException { + private void sendRedirect(ServletExternalContext context, HttpServletRequest request, HttpServletResponse response, + String targetUrl) throws IOException { if (context.isAjaxRequest()) { - ajaxHandler.sendAjaxRedirect(response, targetUrl, context.redirectInPopup()); + ajaxHandler.sendAjaxRedirect(getServletContext(), request, response, targetUrl, context.redirectInPopup()); } else { response.sendRedirect(response.encodeRedirectURL(targetUrl)); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/FlowHandlerAdapter.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/FlowHandlerAdapter.java index c34c1e15..4d014841 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/FlowHandlerAdapter.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/FlowHandlerAdapter.java @@ -134,7 +134,7 @@ public class FlowHandlerAdapter extends WebApplicationObjectSupport implements H protected ServletExternalContext createServletExternalContext(HttpServletRequest request, HttpServletResponse response) { ServletExternalContext context = new ServletExternalContext(getServletContext(), request, response, urlHandler); - context.setAjaxRequest(ajaxHandler.isAjaxRequest(request)); + context.setAjaxRequest(ajaxHandler.isAjaxRequest(getServletContext(), request, response)); return context; } @@ -176,13 +176,13 @@ public class FlowHandlerAdapter extends WebApplicationObjectSupport implements H if (logger.isDebugEnabled()) { logger.debug("Sending flow execution redirect to " + url); } - sendRedirect(context, response, url); + sendRedirect(context, request, response, url); return null; } else if (context.externalRedirectRequested()) { if (logger.isDebugEnabled()) { logger.debug("Sending external redirect to " + context.getExternalRedirectUrl()); } - sendRedirect(context, response, context.getExternalRedirectUrl()); + sendRedirect(context, request, response, context.getExternalRedirectUrl()); return null; } else { return null; @@ -195,13 +195,13 @@ public class FlowHandlerAdapter extends WebApplicationObjectSupport implements H if (logger.isDebugEnabled()) { logger.debug("Sending flow definition to " + url); } - sendRedirect(context, response, url); + sendRedirect(context, request, response, url); return null; } else if (context.externalRedirectRequested()) { if (logger.isDebugEnabled()) { logger.debug("Sending external redirect to " + context.getExternalRedirectUrl()); } - sendRedirect(context, response, context.getExternalRedirectUrl()); + sendRedirect(context, request, response, context.getExternalRedirectUrl()); return null; } else { ModelAndView mv = handler.handleExecutionOutcome(result.getEndedOutcome(), result.getEndedOutput(), @@ -214,10 +214,10 @@ public class FlowHandlerAdapter extends WebApplicationObjectSupport implements H } } - private void sendRedirect(ServletExternalContext context, HttpServletResponse response, String targetUrl) - throws IOException { + private void sendRedirect(ServletExternalContext context, HttpServletRequest request, HttpServletResponse response, + String targetUrl) throws IOException { if (context.isAjaxRequest()) { - ajaxHandler.sendAjaxRedirect(response, targetUrl, context.redirectInPopup()); + ajaxHandler.sendAjaxRedirect(getServletContext(), request, response, targetUrl, context.isAjaxRequest()); } else { response.sendRedirect(response.encodeRedirectURL(targetUrl)); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/SpringJavascriptAjaxHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/SpringJavascriptAjaxHandler.java index 2ea6a0ed..cb0b7b17 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/SpringJavascriptAjaxHandler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/SpringJavascriptAjaxHandler.java @@ -15,6 +15,9 @@ */ package org.springframework.webflow.mvc; +import java.io.IOException; + +import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -48,7 +51,7 @@ public class SpringJavascriptAjaxHandler implements AjaxHandler { */ private static final String AJAX_SOURCE_PARAM = "ajaxSource"; - public boolean isAjaxRequest(HttpServletRequest request) { + public boolean isAjaxRequest(ServletContext context, HttpServletRequest request, HttpServletResponse response) { String acceptHeader = request.getHeader("Accept"); String ajaxParam = request.getParameter(AJAX_SOURCE_PARAM); if (AJAX_ACCEPT_CONTENT_TYPE.equals(acceptHeader) || StringUtils.hasText(ajaxParam)) { @@ -58,7 +61,8 @@ public class SpringJavascriptAjaxHandler implements AjaxHandler { } } - public void sendAjaxRedirect(HttpServletResponse response, String targetUrl, boolean popup) { + public void sendAjaxRedirect(ServletContext context, HttpServletRequest request, HttpServletResponse response, + String targetUrl, boolean popup) throws IOException { if (popup) { response.setHeader(POPUP_VIEW_HEADER, "true"); }