From 84abdc91755f5886915c342da2a92cc274f6dcaf Mon Sep 17 00:00:00 2001 From: Jeremy Grelle Date: Mon, 13 Apr 2009 22:50:21 +0000 Subject: [PATCH] Adjusting JSF implementation to the refactored View interface. --- .../faces/webflow/FlowViewHandler.java | 3 +- .../faces/webflow/JsfView.java | 20 +++++----- .../faces/webflow/ViewRootHolder.java | 2 - .../faces/webflow/JsfViewTests.java | 40 ++++++++++++++----- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewHandler.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewHandler.java index e2b5e522..55399b19 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewHandler.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewHandler.java @@ -28,6 +28,7 @@ import org.springframework.core.io.ContextResource; import org.springframework.core.io.Resource; import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.RequestContextHolder; +import org.springframework.webflow.execution.View; /** * Simple delegating {@link ViewHandler} implementation that provides JSF Form's with the correct FlowExecution URL, @@ -120,7 +121,7 @@ public class FlowViewHandler extends ViewHandler { private UIViewRoot restoreFlowView(FacesContext facesContext, String resourcePath) { RequestContext context = RequestContextHolder.getRequestContext(); - ViewRootHolder holder = (ViewRootHolder) context.getFlashScope().get(ViewRootHolder.VIEW_ROOT_HOLDER_KEY); + ViewRootHolder holder = (ViewRootHolder) context.getFlashScope().get(View.USER_EVENT_STATE_ATTRIBUTE); if (holder != null && holder.getViewRoot().getViewId().equals(resourcePath)) { return holder.getViewRoot(); } else { 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 08a18db0..10c9962b 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 @@ -97,24 +97,27 @@ public class JsfView implements View { return requestContext.getRequestParameters().size() > 1; } + /* + * Executes postback-processing portions of the standard JSF lifecycle including APPLY_REQUEST_VALUES through + * INVOKE_APPLICATION. + */ public void processUserEvent() { - /* - * Executes postback-processing portions of the standard JSF lifecycle including APPLY_REQUEST_VALUES through - * INVOKE_APPLICATION. - */ FacesContext facesContext = FlowFacesContext.newInstance(requestContext, facesLifecycle); facesContext.setViewRoot(viewRoot); try { - // TODO - render response / response complete check - facesLifecycle.execute(facesContext); + // Must respect these flags in case user set them during RESTORE_VIEW phase + if (!facesContext.getRenderResponse() && !facesContext.getResponseComplete()) { + facesLifecycle.execute(facesContext); + } } finally { facesContext.release(); } } public Object getUserEventState() { - // TODO - return view root holder - return null; + // Set the temporary UIViewRoot state in Flash for the redirect, regardless of whether the lifecycle + // executed or not (i.e., it's still necessary when starting a flow and rendering a new view instance) + return new ViewRootHolder(getViewRoot()); } public boolean hasFlowEvent() { @@ -134,5 +137,4 @@ public class JsfView implements View { private String getEventId() { return (String) requestContext.getExternalContext().getRequestMap().get(EVENT_KEY); } - } \ No newline at end of file diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/ViewRootHolder.java b/spring-faces/src/main/java/org/springframework/faces/webflow/ViewRootHolder.java index 5034a57c..14a51555 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/ViewRootHolder.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/ViewRootHolder.java @@ -24,8 +24,6 @@ import javax.faces.component.UIViewRoot; */ class ViewRootHolder { - static final String VIEW_ROOT_HOLDER_KEY = "flowViewRootHolder"; - private UIViewRoot viewRoot; public ViewRootHolder(UIViewRoot viewRoot) { 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 a651db70..1b905eaa 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 @@ -24,6 +24,7 @@ import org.springframework.webflow.execution.FlowExecutionKey; import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.RequestContextHolder; import org.springframework.webflow.test.MockExternalContext; +import org.springframework.webflow.test.MockParameterMap; public class JsfViewTests extends TestCase { @@ -126,12 +127,10 @@ public class JsfViewTests extends TestCase { /** * View already exists in view scope and must be restored and the lifecycle executed, no event signaled */ - public final void testResume_Restored_NoEvent() { + public final void testProcessUserEvent_Restored_NoEvent() { EasyMock.expect(flashScope.getBoolean(EasyMock.matches(FlowFacesContext.RENDER_RESPONSE_KEY))).andStubReturn( Boolean.FALSE); - EasyMock.expect(flashScope.put(EasyMock.matches(ViewRootHolder.VIEW_ROOT_HOLDER_KEY), EasyMock.anyObject())) - .andStubReturn(null); EasyMock.expect(flashScope.put(EasyMock.matches(FlowFacesContext.RENDER_RESPONSE_KEY), EasyMock.anyObject())) .andStubReturn(null); @@ -154,12 +153,10 @@ public class JsfViewTests extends TestCase { * Ajax Request - View already exists in view scope and must be restored and the lifecycle executed, no event * signaled */ - public final void testGetView_Restore_Ajax_NoEvent() { + public final void testProcessUserEvent_Restored_Ajax_NoEvent() { EasyMock.expect(flashScope.getBoolean(EasyMock.matches(FlowFacesContext.RENDER_RESPONSE_KEY))).andStubReturn( Boolean.FALSE); - EasyMock.expect(flashScope.put(EasyMock.matches(ViewRootHolder.VIEW_ROOT_HOLDER_KEY), EasyMock.anyObject())) - .andStubReturn(null); EasyMock.expect(flashScope.put(EasyMock.matches(FlowFacesContext.RENDER_RESPONSE_KEY), EasyMock.anyObject())) .andStubReturn(null); @@ -182,12 +179,10 @@ public class JsfViewTests extends TestCase { /** * View already exists in view scope and must be restored and the lifecycle executed, an event is signaled */ - public final void testGetView_Restore_EventSignaled() { + public final void testProcessUserEvent_Restored_EventSignaled() { EasyMock.expect(flashScope.getBoolean(EasyMock.matches(FlowFacesContext.RENDER_RESPONSE_KEY))).andStubReturn( Boolean.FALSE); - EasyMock.expect(flashScope.put(EasyMock.matches(ViewRootHolder.VIEW_ROOT_HOLDER_KEY), EasyMock.anyObject())) - .andStubReturn(null); EasyMock.expect(flashScope.put(EasyMock.matches(FlowFacesContext.RENDER_RESPONSE_KEY), EasyMock.anyObject())) .andStubReturn(null); @@ -207,6 +202,33 @@ public class JsfViewTests extends TestCase { assertTrue("The lifecycle should have been invoked", ((EventSignalingLifecycle) lifecycle).executed); } + public final void testUserEventQueued_GETRefresh() { + + MockParameterMap requestParameterMap = new MockParameterMap(); + requestParameterMap.put("execution", "e1s1"); + + EasyMock.expect(context.getRequestParameters()).andStubReturn(requestParameterMap); + EasyMock.replay(new Object[] { context, flowExecutionContext, flowMap, flashScope }); + + JsfView createdView = new JsfView(new UIViewRoot(), jsfMock.lifecycle(), context); + + assertFalse("No user ever should be queued", createdView.userEventQueued()); + } + + public final void testUserEventQueued_FormSubmitted() { + + MockParameterMap requestParameterMap = new MockParameterMap(); + requestParameterMap.put("execution", "e1s1"); + requestParameterMap.put("javax.faces.ViewState", "e1s1"); + + EasyMock.expect(context.getRequestParameters()).andStubReturn(requestParameterMap); + EasyMock.replay(new Object[] { context, flowExecutionContext, flowMap, flashScope }); + + JsfView createdView = new JsfView(new UIViewRoot(), jsfMock.lifecycle(), context); + + assertTrue("User event should be queued", createdView.userEventQueued()); + } + private class ExceptionalViewHandler extends MockViewHandler { public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException { throw new IOException("Rendering blew up");