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 a20e2ff5..81becdf7 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 @@ -74,22 +74,30 @@ public class JsfViewFactory implements ViewFactory { } JsfView view; String viewName = resolveViewName(context); - UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewName); - if (viewRoot != null) { + if (viewAlreadySet(facesContext, viewName)) { if (logger.isDebugEnabled()) { - logger.debug("View root restored for '" + viewName + "'"); + logger.debug("Existing view root found for '" + viewName + "'"); } - view = createJsfView(viewRoot, lifecycle, context); - facesContext.setViewRoot(view.getViewRoot()); - processComponentBinding(facesContext, view.getViewRoot()); + view = createJsfView(facesContext.getViewRoot(), lifecycle, context); view.setRestored(true); } else { - if (logger.isDebugEnabled()) { - logger.debug("Creating view root for '" + viewName + "'"); + UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewName); + if (viewRoot != null) { + if (logger.isDebugEnabled()) { + logger.debug("View root restored for '" + viewName + "'"); + } + view = createJsfView(viewRoot, lifecycle, context); + facesContext.setViewRoot(view.getViewRoot()); + processComponentBinding(facesContext, view.getViewRoot()); + 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()); + view.setRestored(true); } - view = createJsfView(viewHandler.createView(facesContext, viewName), lifecycle, context); - facesContext.setViewRoot(view.getViewRoot()); - view.setRestored(true); } JsfUtils.notifyAfterListeners(PhaseId.RESTORE_VIEW, lifecycle, facesContext); return view; @@ -98,6 +106,15 @@ public class JsfViewFactory implements ViewFactory { } } + private boolean viewAlreadySet(FacesContext facesContext, String viewId) { + if (facesContext.getViewRoot() != null && facesContext.getViewRoot().getViewId().equals(viewId)) { + // the corner case where a BEFORE_VIEW PhaseListener has handled setting the UIViewRoot + return true; + } else { + return false; + } + } + private JsfView createJsfView(UIViewRoot root, Lifecycle lifecycle, RequestContext context) { if (isSpringJavascriptAjaxRequest(context.getExternalContext())) { return new JsfView(new AjaxViewRoot(root), lifecycle, context); @@ -107,7 +124,7 @@ public class JsfViewFactory implements ViewFactory { } private boolean isSpringJavascriptAjaxRequest(ExternalContext context) { - // this is not that clean + // this is not very clean if (context.getNativeContext() instanceof ServletContext) { AjaxHandler handler = new SpringJavascriptAjaxHandler(); return handler.isAjaxRequest((ServletContext) context.getNativeContext(), (HttpServletRequest) context 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 0c4e1973..2c988a60 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 @@ -165,27 +165,27 @@ public class JsfViewFactoryTests extends TestCase { /** * Third party sets the view root before RESTORE_VIEW */ - // public final void testGetView_ExternalViewRoot() { - // - // lifecycle = new NoExecutionLifecycle(jsfMock.lifecycle()); - // factory = new JsfViewFactory(parser.parseExpression(VIEW_ID, new FluentParserContext().template().evaluate( - // RequestContext.class).expectResult(String.class)), 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.hasFlowEvent()); - // } + public final void testGetView_ExternalViewRoot() { + lifecycle = new NoExecutionLifecycle(jsfMock.lifecycle()); + factory = new JsfViewFactory(parser.parseExpression(VIEW_ID, new FluentParserContext().template().evaluate( + RequestContext.class).expectResult(String.class)), 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.hasFlowEvent()); + } + private class NoExecutionLifecycle extends FlowLifecycle { public NoExecutionLifecycle(Lifecycle delegate) {