diff --git a/build.gradle b/build.gradle index 080cf81f..7deb87df 100644 --- a/build.gradle +++ b/build.gradle @@ -202,8 +202,8 @@ project("spring-faces") { provided("javax.el:el-api:2.2") provided("javax.servlet:javax.servlet-api:3.0.1") provided("javax.portlet:portlet-api:2.0") - provided("com.sun.faces:jsf-api:2.1.7") - provided("com.sun.faces:jsf-impl:2.1.7") + provided("com.sun.faces:jsf-api:2.2.4") + provided("com.sun.faces:jsf-impl:2.2.4") provided("org.apache.myfaces.core:myfaces-impl:2.1.7") optional("com.sun.facelets:jsf-facelets:1.1.14") optional("org.springframework.security:spring-security-core:$springSecurityVersion") @@ -215,7 +215,7 @@ project("spring-faces") { exclude group: "com.sun.jdmk", module: "jmxtools" exclude group: "com.sun.jmx", module: "jmxri" } - testCompile("org.apache.myfaces.test:myfaces-test20:1.0.4") + testCompile("org.apache.myfaces.test:myfaces-test22:1.0.5") testCompile("org.apache.tomcat:tomcat-jasper-el:7.0.27") testCompile("org.slf4j:jcl-over-slf4j:$slf4jVersion") testCompile("org.slf4j:slf4j-log4j12:$slf4jVersion") { diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContextLifecycleListener.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContextLifecycleListener.java index 9b2b339f..0273973f 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContextLifecycleListener.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContextLifecycleListener.java @@ -22,18 +22,31 @@ import org.springframework.webflow.execution.FlowExecutionListenerAdapter; import org.springframework.webflow.execution.RequestContext; /** - * A {@link FlowExecutionListener} that creates a {@link FlowFacesContext} instance when a flow request is submitted and - * releases it when the request has been processed. - * + * A {@link FlowExecutionListener} that creates a {@link FlowFacesContext} + * instance when a flow request is submitted and releases it when the request + * has been processed. + * * @author Rossen Stoyanchev */ public class FlowFacesContextLifecycleListener extends FlowExecutionListenerAdapter { + public static final String DEFAULT_FACES_CONTEXT = + FlowFacesContextLifecycleListener.class.getName() + ".DEFAULT_FACES_CONTEXT"; + + /** * Creates a new instance of {@link FlowFacesContext} that is then available for the duration of the request. * @param context the current flow request context */ public void requestSubmitted(RequestContext context) { + + FacesContext facesContext = getRequestFacesContext(context); + if (facesContext != null) { + // FacesContext already created, just wrap it (sets "current" instance internally) + new FlowFacesContext(context, facesContext); + return; + } + FlowFacesContext.newInstance(context, FlowLifecycle.newInstance()); } @@ -42,6 +55,17 @@ public class FlowFacesContextLifecycleListener extends FlowExecutionListenerAdap * @param context the source of the event */ public void requestProcessed(RequestContext context) { + + if (getRequestFacesContext(context) != null) { + return; + } + FacesContext.getCurrentInstance().release(); } + + + private FacesContext getRequestFacesContext(RequestContext context) { + return (FacesContext) context.getExternalContext().getRequestMap().get(DEFAULT_FACES_CONTEXT); + } + } diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfFlowHandlerAdapter.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfFlowHandlerAdapter.java index a7819704..6e8f1a5f 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfFlowHandlerAdapter.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfFlowHandlerAdapter.java @@ -15,6 +15,9 @@ */ package org.springframework.faces.webflow; +import javax.faces.context.FacesContext; +import javax.faces.context.PartialResponseWriter; +import javax.faces.lifecycle.Lifecycle; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -25,24 +28,37 @@ import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter; /** * An extension of {@link FlowHandlerAdapter} that replaces the default {@link AjaxHandler} instance with a * {@link JsfAjaxHandler}. - * + * * @author Rossen Stoyanchev * @since 2.2.0 */ public class JsfFlowHandlerAdapter extends FlowHandlerAdapter { + public void afterPropertiesSet() throws Exception { - boolean initializeAjaxHandler = getAjaxHandler() == null; + + boolean isAjaxHandlerConfigured = (getAjaxHandler() != null); super.afterPropertiesSet(); - if (initializeAjaxHandler) { - JsfAjaxHandler ajaxHandler = new JsfAjaxHandler(); - ajaxHandler.setApplicationContext(getApplicationContext()); - setAjaxHandler(ajaxHandler); + + if (!isAjaxHandlerConfigured) { + JsfAjaxHandler handler = new JsfAjaxHandler(); + handler.setApplicationContext(getApplicationContext()); + setAjaxHandler(handler); } } public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - return super.handle(request, response, handler); + + FacesContextHelper helper = new FacesContextHelper(); + try { + FacesContext facesContext = helper.getFacesContext(getServletContext(), request, response); + request.setAttribute(FlowFacesContextLifecycleListener.DEFAULT_FACES_CONTEXT, facesContext); + return super.handle(request, response, handler); + + } finally { + request.removeAttribute(FlowFacesContextLifecycleListener.DEFAULT_FACES_CONTEXT); + helper.releaseIfNecessary(); + } } } diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/context/portlet/PortletExternalContextImpl.java b/spring-faces/src/main/java/org/springframework/faces/webflow/context/portlet/PortletExternalContextImpl.java index a8982bd3..f68c497b 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/context/portlet/PortletExternalContextImpl.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/context/portlet/PortletExternalContextImpl.java @@ -583,7 +583,7 @@ public class PortletExternalContextImpl extends ExternalContext { private static class MojarraFlashFactory { public Flash newFlash(ExternalContext context) { - return ELFlash.getFlash(context, true); + return (Flash) ELFlash.getFlash(); } } diff --git a/spring-faces/src/test/java/org/springframework/faces/webflow/JsfAjaxHandlerTests.java b/spring-faces/src/test/java/org/springframework/faces/webflow/JsfAjaxHandlerTests.java index 18548e8a..98151085 100644 --- a/spring-faces/src/test/java/org/springframework/faces/webflow/JsfAjaxHandlerTests.java +++ b/spring-faces/src/test/java/org/springframework/faces/webflow/JsfAjaxHandlerTests.java @@ -23,9 +23,7 @@ public class JsfAjaxHandlerTests extends TestCase { public void testSendAjaxRedirect() throws Exception { this.ajaxHandler.sendAjaxRedirectInternal("/target", this.jsfMock.request(), this.jsfMock.response(), false); - assertEquals( - "\n", - this.jsfMock.contentAsString()); + assertTrue(this.jsfMock.contentAsString().matches("")); assertEquals("application/xml", this.jsfMock.response().getContentType()); }