diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/AjaxViewRoot.java b/spring-faces/src/main/java/org/springframework/faces/ui/AjaxViewRoot.java index 28b2fcac..4c52bde8 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/AjaxViewRoot.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/AjaxViewRoot.java @@ -177,8 +177,8 @@ public class AjaxViewRoot extends DelegatingViewRoot { try { String formId = findContainingFormId(context); if (StringUtils.hasLength(formId)) { - String script = "dojo.byId('" + formId + "').action = " - + context.getApplication().getViewHandler().getActionURL(context, getViewId()); + String script = "dojo.byId('" + formId + "').action = '" + + context.getApplication().getViewHandler().getActionURL(context, getViewId()) + "'"; writer.startElement("script", null); writer.writeText(script, null); writer.endElement("script"); 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 a5713e15..b7b17b3f 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 @@ -51,6 +51,8 @@ public class JsfView implements View { private String viewId; + private boolean restored = false; + public JsfView(UIViewRoot viewRoot, Lifecycle facesLifecycle, RequestContext context) { this.viewRoot = viewRoot; this.viewId = viewRoot.getViewId(); @@ -79,8 +81,17 @@ public class JsfView implements View { } } - public void postback() { - // TODO - implement Postback JSF lifecycle + public void resume() { + FacesContext facesContext = FlowFacesContext.newInstance(context, facesLifecycle); + try { + if (restored && !facesContext.getResponseComplete() && !facesContext.getRenderResponse()) { + facesLifecycle.execute(facesContext); + facesContext.renderResponse(); + } + } finally { + facesContext.release(); + } + } public boolean eventSignaled() { @@ -99,4 +110,8 @@ public class JsfView implements View { public String toString() { return "[JSFView = '" + viewId + "']"; } + + public void setRestored(boolean restored) { + this.restored = restored; + } } \ 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 ec0a6a29..e3ca1a85 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 @@ -70,8 +70,6 @@ public class JsfViewFactory implements ViewFactory { FacesContext facesContext = FlowFacesContext.newInstance(context, lifecycle); try { - boolean restored = false; - if (!facesContext.getRenderResponse()) { JsfUtils.notifyBeforeListeners(PhaseId.RESTORE_VIEW, lifecycle, facesContext); } @@ -85,7 +83,7 @@ public class JsfViewFactory implements ViewFactory { logger.debug("Existing view root found for '" + viewName + "'"); } view = createJsfView(facesContext.getViewRoot(), lifecycle, context); - restored = true; + view.setRestored(true); } else { UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewName); if (viewRoot != null) { @@ -95,14 +93,14 @@ public class JsfViewFactory implements ViewFactory { view = createJsfView(viewRoot, lifecycle, context); facesContext.setViewRoot(view.getViewRoot()); processComponentBinding(facesContext, view.getViewRoot()); - restored = true; + view.setRestored(true); } else { if (logger.isDebugEnabled()) { logger.debug("Creating view root for '" + viewName + "'"); } view = createJsfView(viewHandler.createView(facesContext, viewName), lifecycle, context); facesContext.setViewRoot(view.getViewRoot()); - restored = false; + view.setRestored(true); } } @@ -110,11 +108,6 @@ public class JsfViewFactory implements ViewFactory { JsfUtils.notifyAfterListeners(PhaseId.RESTORE_VIEW, lifecycle, facesContext); } - if (restored && !facesContext.getResponseComplete() && !facesContext.getRenderResponse()) { - lifecycle.execute(facesContext); - facesContext.renderResponse(); - } - return view; } finally { facesContext.release(); 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 9fbcd8f9..77b9cc09 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 @@ -19,7 +19,6 @@ import org.easymock.EasyMock; 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; @@ -112,111 +111,6 @@ public class JsfViewFactoryTests extends TestCase { assertFalse("The lifecycle should not have been invoked", ((NoEventLifecycle) lifecycle).executed); } - /** - * View already exists in flash scope and must be restored and the lifecycle executed, no event signaled - */ - public final void testGetView_Restore_NoEvent() { - - lifecycle = new NoEventLifecycle(jsfMock.lifecycle()); - factory = new JsfViewFactory(parser.parseExpression(VIEW_ID, new ParserContextImpl().template().eval( - RequestContext.class).expect(String.class)), null, lifecycle); - - UIViewRoot existingRoot = new UIViewRoot(); - existingRoot.setViewId(VIEW_ID); - ((MockViewHandler) viewHandler).setRestoreView(existingRoot); - - EasyMock.replay(new Object[] { context }); - - View restoredView = factory.getView(context); - - assertNotNull("A View was not restored", restoredView); - assertTrue("A JsfView was expected", restoredView instanceof JsfView); - assertEquals("View name did not match", VIEW_ID, ((JsfView) restoredView).getViewRoot().getViewId()); - assertFalse("An unexpected event was signaled,", restoredView.eventSignaled()); - assertTrue("The lifecycle should have been invoked", ((NoEventLifecycle) lifecycle).executed); - } - - /** - * Ajax Request - View already exists in flash scope and must be restored and the lifecycle executed, no event - * signaled - */ - public final void testGetView_Restore_Ajax_NoEvent() { - - lifecycle = new NoEventLifecycle(jsfMock.lifecycle()); - factory = new JsfViewFactory(parser.parseExpression(VIEW_ID, new ParserContextImpl().template().eval( - RequestContext.class).expect(String.class)), null, lifecycle); - - UIViewRoot existingRoot = new UIViewRoot(); - existingRoot.setViewId(VIEW_ID); - ((MockViewHandler) viewHandler).setRestoreView(existingRoot); - - request.addHeader("Accept", "text/html;type=ajax"); - - EasyMock.expect(context.getCurrentState()).andReturn(new ModalViewState()); - - EasyMock.replay(new Object[] { context }); - - View restoredView = factory.getView(context); - - assertNotNull("A View was not restored", restoredView); - assertTrue("A JsfView was expected", restoredView instanceof JsfView); - assertTrue("An AjaxViewRoot was not set", ((JsfView) restoredView).getViewRoot() instanceof AjaxViewRoot); - assertEquals("View name did not match", VIEW_ID, ((JsfView) restoredView).getViewRoot().getViewId()); - assertFalse("An unexpected event was signaled,", restoredView.eventSignaled()); - assertTrue("The lifecycle should have been invoked", ((NoEventLifecycle) lifecycle).executed); - } - - /** - * View already exists in flowscope and must be restored and the lifecycle executed, an event is signaled - */ - public final void testGetView_Restore_EventSignaled() { - - lifecycle = new EventSignalingLifecycle(jsfMock.lifecycle()); - factory = new JsfViewFactory(parser.parseExpression(VIEW_ID, new ParserContextImpl().template().eval( - RequestContext.class).expect(String.class)), null, lifecycle); - - UIViewRoot existingRoot = new UIViewRoot(); - existingRoot.setViewId(VIEW_ID); - ((MockViewHandler) viewHandler).setRestoreView(existingRoot); - - EasyMock.replay(new Object[] { context }); - - View restoredView = factory.getView(context); - - assertNotNull("A View was not restored", restoredView); - assertTrue("A JsfView was expected", restoredView instanceof JsfView); - assertEquals("View name did not match", VIEW_ID, ((JsfView) restoredView).getViewRoot().getViewId()); - assertTrue("No event was signaled,", restoredView.eventSignaled()); - assertEquals("Event should be " + event, event, restoredView.getEvent().getId()); - assertTrue("The lifecycle should have been invoked", ((EventSignalingLifecycle) lifecycle).executed); - } - - /** - * Third party sets the view root before RESTORE_VIEW - */ - public final void testGetView_ExternalViewRoot() { - - lifecycle = new NoEventLifecycle(jsfMock.lifecycle()); - factory = new JsfViewFactory(parser.parseExpression(VIEW_ID, new ParserContextImpl().template().eval( - RequestContext.class).expect(String.class)), null, lifecycle); - - UIViewRoot newRoot = new UIViewRoot(); - newRoot.setViewId(VIEW_ID); - jsfMock.facesContext().setViewRoot(newRoot); - jsfMock.facesContext().renderResponse(); - - EasyMock.replay(new Object[] { context }); - - View newView = factory.getView(context); - - assertNotNull("A View was not created", newView); - assertTrue("A JsfView was expected", newView instanceof JsfView); - assertEquals("View name did not match", VIEW_ID, ((JsfView) newView).getViewRoot().getViewId()); - assertSame("View root was not the third party instance", newRoot, ((JsfView) newView).getViewRoot()); - assertFalse("An unexpected event was signaled,", newView.eventSignaled()); - assertTrue("The lifecycle should have been invoked", ((NoEventLifecycle) lifecycle).executed); - } - private class NoEventLifecycle extends FlowLifecycle { boolean executed = false;