diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowPartialViewContext.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowPartialViewContext.java new file mode 100644 index 00000000..ba7f7f2a --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowPartialViewContext.java @@ -0,0 +1,64 @@ +/* + * Copyright 2004-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.faces.webflow; + +import java.util.Arrays; +import java.util.Collection; + +import javax.faces.context.PartialViewContext; +import javax.faces.context.PartialViewContextWrapper; + +import org.springframework.webflow.execution.RequestContext; +import org.springframework.webflow.execution.RequestContextHolder; +import org.springframework.webflow.execution.View; + +/** + * Web Flow {@link PartialViewContext} implementation allowing ids for partial rendering to be specified from the + * server-side. This is done in a flow definition with the <render fragments="..." /> action. + * + * @author Rossen Stoyanchev + */ +public class FlowPartialViewContext extends PartialViewContextWrapper { + + private PartialViewContext delegate; + + public FlowPartialViewContext(PartialViewContext delegate) { + this.delegate = delegate; + } + + @Override + public PartialViewContext getWrapped() { + return delegate; + } + + @Override + public void setPartialRequest(boolean isPartialRequest) { + getWrapped().setPartialRequest(isPartialRequest); + } + + @Override + public Collection getRenderIds() { + if (JsfUtils.isFlowRequest()) { + RequestContext requestContext = RequestContextHolder.getRequestContext(); + String[] fragmentIds = (String[]) requestContext.getFlashScope().get(View.RENDER_FRAGMENTS_ATTRIBUTE); + if (fragmentIds != null && fragmentIds.length > 0) { + return Arrays.asList(fragmentIds); + } + } + return getWrapped().getRenderIds(); + } + +} diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/Jsf2FlowFacesContext.java b/spring-faces/src/main/java/org/springframework/faces/webflow/Jsf2FlowFacesContext.java index fc4e5bcc..eb456971 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/Jsf2FlowFacesContext.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/Jsf2FlowFacesContext.java @@ -45,12 +45,6 @@ public class Jsf2FlowFacesContext extends FlowFacesContext { private ExternalContext externalContext; - /* - * This partialViewContext duplicates the one FacesContextImpl because the constructor of FacesContextImpl calls - * getPartialViewContext(), which causes it to be instantiated with an instance of FacesContextImpl. This leads to - * issues with adding and showing validation messages during Ajax requests because the FlowFacesContext is - * effectively bypassed. - */ private PartialViewContext partialViewContext; public Jsf2FlowFacesContext(RequestContext context, FacesContext delegate) { @@ -58,9 +52,10 @@ public class Jsf2FlowFacesContext extends FlowFacesContext { this.externalContext = new Jsf2FlowExternalContext(getDelegate().getExternalContext()); - PartialViewContextFactory f = (PartialViewContextFactory) FactoryFinder + PartialViewContextFactory factory = (PartialViewContextFactory) FactoryFinder .getFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY); - this.partialViewContext = f.getPartialViewContext(this); + PartialViewContext partialViewContextDelegate = factory.getPartialViewContext(this); + this.partialViewContext = new FlowPartialViewContext(partialViewContextDelegate); } public ExternalContext getExternalContext() { diff --git a/spring-faces/src/test/java/org/springframework/faces/webflow/FlowPartialViewContextTests.java b/spring-faces/src/test/java/org/springframework/faces/webflow/FlowPartialViewContextTests.java new file mode 100644 index 00000000..a31185ff --- /dev/null +++ b/spring-faces/src/test/java/org/springframework/faces/webflow/FlowPartialViewContextTests.java @@ -0,0 +1,49 @@ +package org.springframework.faces.webflow; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import javax.faces.context.PartialViewContext; +import javax.faces.context.PartialViewContextWrapper; + +import junit.framework.TestCase; + +import org.springframework.webflow.execution.RequestContext; +import org.springframework.webflow.execution.RequestContextHolder; +import org.springframework.webflow.execution.View; +import org.springframework.webflow.test.MockRequestContext; + +public class FlowPartialViewContextTests extends TestCase { + + public void testReturnFragmentIds() throws Exception { + String[] fragmentIds = new String[] { "foo", "bar" }; + + RequestContext requestContext = new MockRequestContext(); + requestContext.getFlashScope().asMap().put(View.RENDER_FRAGMENTS_ATTRIBUTE, fragmentIds); + RequestContextHolder.setRequestContext(requestContext); + + assertEquals(Arrays.asList(fragmentIds), new FlowPartialViewContext(null).getRenderIds()); + } + + public void testNoFragmentIds() throws Exception { + final List renderIds = Arrays.asList("foo", "bar"); + FlowPartialViewContext context = new FlowPartialViewContext(new PartialViewContextWrapper() { + public Collection getRenderIds() { + return renderIds; + } + + public void setPartialRequest(boolean isPartialRequest) { + } + + public PartialViewContext getWrapped() { + return null; + } + }); + + RequestContextHolder.setRequestContext(new MockRequestContext()); + + assertEquals(renderIds, context.getRenderIds()); + } + +} \ No newline at end of file