You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2016/05/13 22:35:50 UTC
svn commit: r1743767 - in /myfaces/core/trunk/impl/src:
main/java/org/apache/myfaces/application/
main/java/org/apache/myfaces/flow/ main/java/org/apache/myfaces/flow/cdi/
main/java/org/apache/myfaces/flow/impl/
main/java/org/apache/myfaces/flow/util/ ...
Author: lu4242
Date: Fri May 13 22:35:49 2016
New Revision: 1743767
URL: http://svn.apache.org/viewvc?rev=1743767&view=rev
Log:
MYFACES-4045 Review Faces Flow reentrant condition
Added:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/util/
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/util/FlowUtils.java
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowA/
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowA/content.xhtml
- copied unchanged from r1743449, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/content.xhtml
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowA/flowA.xhtml
- copied, changed from r1743449, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/flow5.xhtml
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowB/
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowB/content.xhtml
- copied unchanged from r1743449, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/content.xhtml
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowB/flowB.xhtml
- copied, changed from r1743449, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/flow5.xhtml
Modified:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/DefaultCDIFacesFlowProvider.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopedContextImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/impl/DefaultFacesFlowProvider.java
myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesCDIRequestTestCase.java
myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml
myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java Fri May 13 22:35:49 2016
@@ -564,7 +564,8 @@ public class NavigationHandlerImpl
{
if (startFlow)
{
- if (flowHandler.isActive(facesContext, targetFlow.getDefiningDocumentId(), targetFlow.getId()))
+ if (flowHandler.isActive(facesContext, targetFlow.getDefiningDocumentId(), targetFlow.getId())
+ && targetFlowCallNode == null)
{
// Add the transition to exit from the flow
Flow baseReturnFlow = navigationContext.getCurrentFlow(facesContext);
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/FlowHandlerImpl.java Fri May 13 22:35:49 2016
@@ -232,11 +232,12 @@ public class FlowHandlerImpl extends Flo
}
else
{
- // Both sourceFlow and targetFlow are not null, so we need to check the direction
+ // Both sourceFlow and targetFlow are not null, if there is no call node set (force enter flow)
+ // we need to check the direction
// If targetFlow is on the stack, remove elements until get there.
// If targetFlow is not there, add it to the stack.
List<_FlowContextualInfo> currentFlowStack = getCurrentFlowStack(context, clientWindow);
- if (currentFlowStack != null)
+ if (currentFlowStack != null && outboundCallNode == null)
{
FlowReference targetFlowReference = new FlowReference(
targetFlow.getDefiningDocumentId(), targetFlow.getId());
@@ -302,7 +303,7 @@ public class FlowHandlerImpl extends Flo
if (sourceFlowIndex != -1)
{
- // From sourceFlowIndex, add all flows
+ // From sourceFlowIndex, remove(add to flowsToRemove list) all flows
traverseDependantFlows(sourceFlowReference, sourceFlowIndex+1, currentFlowStack, flowsToRemove);
// Remove all marked elements
@@ -314,7 +315,16 @@ public class FlowHandlerImpl extends Flo
FlowReference fr = fci.getFlowReference();
doBeforeExitFlow(context, getFlow(context, fr.getDocumentId(), fr.getId()));
//popFlowReference(context, clientWindow, currentFlowStack, i);
- currentFlowStack.remove(fci);
+
+ //Remove flows from the last to the first to keep the right sequence.
+ for (int j = currentFlowStack.size()-1; j >= 0; j--)
+ {
+ if (currentFlowStack.get(j) == fci)
+ {
+ currentFlowStack.remove(j);
+ break;
+ }
+ }
}
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/DefaultCDIFacesFlowProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/DefaultCDIFacesFlowProvider.java?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/DefaultCDIFacesFlowProvider.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/DefaultCDIFacesFlowProvider.java Fri May 13 22:35:49 2016
@@ -27,6 +27,7 @@ import javax.enterprise.inject.spi.BeanM
import javax.faces.context.FacesContext;
import javax.faces.flow.Flow;
import org.apache.myfaces.cdi.util.CDIUtils;
+import org.apache.myfaces.flow.util.FlowUtils;
import org.apache.myfaces.spi.FacesFlowProvider;
/**
@@ -102,8 +103,7 @@ public class DefaultCDIFacesFlowProvider
mapKey);
if (map == null)
{
- map = new FlowScopeMap(getBeanManager(), flow.getClientWindowFlowId(
- facesContext.getExternalContext().getClientWindow()));
+ map = new FlowScopeMap(getBeanManager(), FlowUtils.getFlowMapKey(facesContext, flow));
facesContext.getAttributes().put(mapKey, map);
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java Fri May 13 22:35:49 2016
@@ -45,7 +45,7 @@ import org.apache.myfaces.cdi.view.Appli
import org.apache.myfaces.context.ReleaseableExternalContext;
import org.apache.myfaces.context.servlet.StartupFacesContextImpl;
import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
-import org.apache.myfaces.flow.FlowReference;
+import org.apache.myfaces.flow.util.FlowUtils;
import org.apache.myfaces.shared.config.MyfacesConfig;
import org.apache.myfaces.shared.context.ExceptionHandlerImpl;
@@ -308,26 +308,6 @@ public class FlowScopeBeanHolder impleme
}
}
- public String getFlowMapKey(FacesContext facesContext, FlowReference flowReference)
- {
- Flow flow = null;
- if (flowReference.getDocumentId() == null)
- {
- flow = facesContext.getApplication().getFlowHandler().getFlow(
- facesContext, "", flowReference.getId());
- }
- else
- {
- flow = facesContext.getApplication().getFlowHandler().getFlow(
- facesContext, flowReference.getDocumentId(), flowReference.getId());
- }
- if (flow != null)
- {
- return flow.getClientWindowFlowId(facesContext.getExternalContext().getClientWindow());
- }
- return null;
- }
-
public void createCurrentFlowScope(FacesContext facesContext)
{
ClientWindow cw = facesContext.getExternalContext().getClientWindow();
@@ -335,8 +315,7 @@ public class FlowScopeBeanHolder impleme
FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
Flow flow = flowHandler.getCurrentFlow(facesContext);
- String flowMapKey = flow.getClientWindowFlowId(
- facesContext.getExternalContext().getClientWindow());
+ String flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
List<String> activeFlowKeys = activeFlowMapKeys.get(baseKey);
if (activeFlowKeys == null)
@@ -356,8 +335,7 @@ public class FlowScopeBeanHolder impleme
FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
Flow flow = flowHandler.getCurrentFlow(facesContext);
- String flowMapKey = flow.getClientWindowFlowId(
- facesContext.getExternalContext().getClientWindow());
+ String flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
ContextualStorage contextualStorage = storageMap.remove(flowMapKey);
if (contextualStorage != null)
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopedContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopedContextImpl.java?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopedContextImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopedContextImpl.java Fri May 13 22:35:49 2016
@@ -37,6 +37,7 @@ import org.apache.myfaces.cdi.util.BeanP
import org.apache.myfaces.cdi.util.ContextualInstanceInfo;
import org.apache.myfaces.cdi.util.ContextualStorage;
import org.apache.myfaces.flow.FlowReference;
+import org.apache.myfaces.flow.util.FlowUtils;
/**
* Minimal implementation of FlowScope.
@@ -110,8 +111,7 @@ public class FlowScopedContextImpl imple
Flow flow = flowHandler.getCurrentFlow(facesContext);
if (flow != null)
{
- flowMapKey = flow.getClientWindowFlowId(
- facesContext.getExternalContext().getClientWindow());
+ flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
}
return flowMapKey;
}
@@ -182,7 +182,7 @@ public class FlowScopedContextImpl imple
FlowReference reference = flowBeanReferences.get(((Bean)bean).getBeanClass());
if (reference != null)
{
- String flowMapKey = getFlowScopeBeanHolder().getFlowMapKey(facesContext, reference);
+ String flowMapKey = FlowUtils.getFlowMapKey(facesContext, reference);
if (flowMapKey != null)
{
ContextualStorage storage = getContextualStorage(false, flowMapKey);
@@ -243,7 +243,7 @@ public class FlowScopedContextImpl imple
FlowReference reference = flowBeanReferences.get(((Bean)bean).getBeanClass());
if (reference != null)
{
- String flowMapKey = getFlowScopeBeanHolder().getFlowMapKey(facesContext, reference);
+ String flowMapKey = FlowUtils.getFlowMapKey(facesContext, reference);
if (flowMapKey != null)
{
ContextualStorage storage = getContextualStorage(false, flowMapKey);
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/impl/DefaultFacesFlowProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/impl/DefaultFacesFlowProvider.java?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/impl/DefaultFacesFlowProvider.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/impl/DefaultFacesFlowProvider.java Fri May 13 22:35:49 2016
@@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHa
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.flow.Flow;
+import org.apache.myfaces.flow.util.FlowUtils;
import org.apache.myfaces.spi.FacesFlowProvider;
/**
@@ -62,8 +63,7 @@ public class DefaultFacesFlowProvider ex
@Override
public void doBeforeExitFlow(FacesContext facesContext, Flow flow)
{
- String flowMapKey = flow.getClientWindowFlowId(
- facesContext.getExternalContext().getClientWindow());
+ String flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
String fullToken = FLOW_SESSION_MAP_SUBKEY_PREFIX + SEPARATOR_CHAR + flowMapKey;
String mapKey = CURRENT_FLOW_SCOPE_MAP+SEPARATOR_CHAR+
@@ -102,12 +102,11 @@ public class DefaultFacesFlowProvider ex
map = (Map<Object, Object>) facesContext.getAttributes().get(mapKey);
if (map == null)
{
- String flowMapKey = flow.getClientWindowFlowId(
- facesContext.getExternalContext().getClientWindow());
+ String flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
- map = new FlowScopeMap(this, flowMapKey);
//String fullToken = FLOW_SESSION_MAP_SUBKEY_PREFIX + SEPARATOR_CHAR + flowMapKey;
//map = createOrRestoreMap(facesContext, fullToken);
+ map = new FlowScopeMap(this, flowMapKey);
facesContext.getAttributes().put(mapKey, map);
}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/util/FlowUtils.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/util/FlowUtils.java?rev=1743767&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/util/FlowUtils.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/flow/util/FlowUtils.java Fri May 13 22:35:49 2016
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.myfaces.flow.util;
+
+import java.util.List;
+import javax.faces.context.FacesContext;
+import javax.faces.flow.Flow;
+import org.apache.myfaces.flow.FlowHandlerImpl;
+import org.apache.myfaces.flow.FlowReference;
+
+/**
+ *
+ */
+public class FlowUtils
+{
+ public static String getFlowMapKey(FacesContext facesContext, FlowReference flowReference)
+ {
+ Flow flow = null;
+ if (flowReference.getDocumentId() == null)
+ {
+ flow = facesContext.getApplication().getFlowHandler().getFlow(
+ facesContext, "", flowReference.getId());
+ }
+ else
+ {
+ flow = facesContext.getApplication().getFlowHandler().getFlow(
+ facesContext, flowReference.getDocumentId(), flowReference.getId());
+ }
+ if (flow != null)
+ {
+ return FlowUtils.getFlowMapKey(facesContext, flow);
+ }
+ return null;
+ }
+
+ public static String getFlowMapKey(FacesContext facesContext, Flow flow)
+ {
+ String flowMapKey = flow.getClientWindowFlowId(
+ facesContext.getExternalContext().getClientWindow());
+ int flowIndex = getFlowIndex(facesContext, flow);
+ if (flowIndex > 0)
+ {
+ flowMapKey = flowMapKey + "_" + flowIndex;
+ }
+ return flowMapKey;
+ }
+
+ private static int getFlowIndex(FacesContext facesContext, Flow flow)
+ {
+ List<Flow> list = FlowHandlerImpl.getActiveFlows(facesContext,
+ facesContext.getApplication().getFlowHandler());
+ FlowReference flowRef = new FlowReference(flow.getDefiningDocumentId(), flow.getId());
+ int flowIndex = 0;
+ for (Flow f : list)
+ {
+ FlowReference fr = new FlowReference(f.getDefiningDocumentId(), f.getId());
+ if (flowRef.equals(fr))
+ {
+ flowIndex++;
+ }
+ }
+ return flowIndex;
+ }
+
+}
Modified: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesCDIRequestTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesCDIRequestTestCase.java?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesCDIRequestTestCase.java (original)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesCDIRequestTestCase.java Fri May 13 22:35:49 2016
@@ -247,5 +247,251 @@ public class FlowMyFacesCDIRequestTestCa
Assert.assertEquals("/flow5/flow5.xhtml", facesContext.getViewRoot().getViewId());
renderResponse();
- }
+ }
+
+ /**
+ * This tests do the following:
+ *
+ * - Start Flow A
+ * - Call Flow B
+ * - Call Flow A
+ * - Call Flow B
+ * - Return from Flow B
+ * - Return from Flow A
+ * - Return from Flow B
+ */
+ @Test
+ public void testFlowA_1() throws Exception
+ {
+ startViewRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ renderResponse();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlowA");
+ client.submit(button);
+
+ processLifecycleExecute();
+
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowA","valueA_1");
+ Assert.assertEquals("/flowA/flowA.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flowA");
+
+ renderResponse();
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_B");
+ client.submit(button2);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowA"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowB","valueB_1");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowB/flowB.xhtml", facesContext.getViewRoot().getViewId());
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_A");
+ client.submit(button3);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowB"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowA","valueA_2");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowA/flowA.xhtml", facesContext.getViewRoot().getViewId());
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_B");
+ client.submit(button4);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowA"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowB","valueB_2");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowB/flowB.xhtml", facesContext.getViewRoot().getViewId());
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button5);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertEquals("valueA_2", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowA"));
+
+ renderResponse();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button6);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertEquals("valueB_1", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowB"));
+
+ renderResponse();
+
+ UICommand button7 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button7);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertEquals("valueA_1", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowA"));
+
+ renderResponse();
+ }
+
+ @Test
+ public void testFlowA_2() throws Exception
+ {
+ startViewRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ renderResponse();
+
+ //Enter flow A
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlowA");
+ client.submit(button);
+
+ processLifecycleExecute();
+
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowA","valueA_1");
+ Assert.assertEquals("/flowA/flowA.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flowA");
+
+ renderResponse();
+
+ //Go to base
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ client.submit(button2);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ // We are still on flowA, just returned to base
+ Assert.assertEquals("flowA", currentFlow.getId());
+
+ renderResponse();
+
+ //Enter flow B
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlowB");
+ client.submit(button3);
+
+ processLifecycleExecute();
+
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowB","valueB_1");
+ Assert.assertEquals("/flowB/flowB.xhtml", facesContext.getViewRoot().getViewId());
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flowB");
+
+ renderResponse();
+
+ // Call flow A through flow call
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_A");
+ client.submit(button4);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowB"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowA","valueA_2");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowA/flowA.xhtml", facesContext.getViewRoot().getViewId());
+
+ // Call flow B through flow call
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_B");
+ client.submit(button5);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowA"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowB","valueB_2");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowB/flowB.xhtml", facesContext.getViewRoot().getViewId());
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button6);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertEquals("valueA_2", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowA"));
+
+ renderResponse();
+
+ UICommand button7 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button7);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertEquals("valueB_1", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowB"));
+
+ renderResponse();
+
+ UICommand button8 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button8);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertEquals("valueA_1", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowA"));
+
+ renderResponse();
+
+ }
}
Modified: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java (original)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/flow/FlowMyFacesRequestTestCase.java Fri May 13 22:35:49 2016
@@ -1425,5 +1425,251 @@ public class FlowMyFacesRequestTestCase
renderResponse();
}
+
+ /**
+ * This tests do the following:
+ *
+ * - Start Flow A
+ * - Call Flow B
+ * - Call Flow A
+ * - Call Flow B
+ * - Return from Flow B
+ * - Return from Flow A
+ * - Return from Flow B
+ */
+ @Test
+ public void testFlowA_1() throws Exception
+ {
+ startViewRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ renderResponse();
+
+ //Enter flow 1
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlowA");
+ client.submit(button);
+
+ processLifecycleExecute();
+
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowA","valueA_1");
+ Assert.assertEquals("/flowA/flowA.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flowA");
+
+ renderResponse();
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_B");
+ client.submit(button2);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowA"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowB","valueB_1");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowB/flowB.xhtml", facesContext.getViewRoot().getViewId());
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_A");
+ client.submit(button3);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowB"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowA","valueA_2");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowA/flowA.xhtml", facesContext.getViewRoot().getViewId());
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_B");
+ client.submit(button4);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowA"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowB","valueB_2");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowB/flowB.xhtml", facesContext.getViewRoot().getViewId());
+
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button5);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertEquals("valueA_2", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowA"));
+
+ renderResponse();
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button6);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertEquals("valueB_1", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowB"));
+
+ renderResponse();
+
+ UICommand button7 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button7);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertEquals("valueA_1", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowA"));
+
+ renderResponse();
+ }
+
+ @Test
+ public void testFlowA_2() throws Exception
+ {
+ startViewRequest("/flow_base.xhtml");
+ processLifecycleExecute();
+
+ ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) facesContext.getApplication().getNavigationHandler();
+
+ renderResponse();
+
+ //Enter flow A
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlowA");
+ client.submit(button);
+
+ processLifecycleExecute();
+
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowA","valueA_1");
+ Assert.assertEquals("/flowA/flowA.xhtml", facesContext.getViewRoot().getViewId());
+
+ Flow currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flowA");
+
+ renderResponse();
+
+ //Go to base
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:go_flow_base");
+ client.submit(button2);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ // We are still on flowA, just returned to base
+ Assert.assertEquals("flowA", currentFlow.getId());
+
+ renderResponse();
+
+ //Enter flow B
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:startFlowB");
+ client.submit(button3);
+ processLifecycleExecute();
+
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowB","valueB_1");
+ Assert.assertEquals("/flowB/flowB.xhtml", facesContext.getViewRoot().getViewId());
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals(currentFlow.getId(), "flowB");
+
+ renderResponse();
+
+ // Call flow A through flow call
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_A");
+ client.submit(button4);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowB"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowA","valueA_2");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowA/flowA.xhtml", facesContext.getViewRoot().getViewId());
+
+ // Call flow B through flow call
+ UICommand button5 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:call_flow_B");
+ client.submit(button5);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertFalse(facesContext.getApplication().getFlowHandler().getCurrentFlowScope().containsKey("flowA"));
+ facesContext.getApplication().getFlowHandler().getCurrentFlowScope().put("flowB","valueB_2");
+
+ renderResponse();
+
+ //Check current view is the begin of flow2
+ Assert.assertEquals("/flowB/flowB.xhtml", facesContext.getViewRoot().getViewId());
+
+ UICommand button6 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button6);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertEquals("valueA_2", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowA"));
+
+ renderResponse();
+
+ UICommand button7 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button7);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowB", currentFlow.getId());
+ Assert.assertEquals("valueB_1", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowB"));
+
+ renderResponse();
+
+ UICommand button8 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:end_flow");
+ client.submit(button8);
+
+ processLifecycleExecute();
+
+ currentFlow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
+ Assert.assertNotNull(currentFlow);
+ Assert.assertEquals("flowA", currentFlow.getId());
+ Assert.assertEquals("valueA_1", facesContext.getApplication().getFlowHandler().getCurrentFlowScope().get("flowA"));
+
+ renderResponse();
+
+ }
+
}
Modified: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml (original)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/WEB-INF/flow1-flow.xml Fri May 13 22:35:49 2016
@@ -251,5 +251,43 @@
</navigation-case>
</navigation-rule>
+ <flow-definition id="flowA">
+
+ <flow-return id="end">
+ <from-outcome>exit</from-outcome>
+ </flow-return>
+
+ <flow-call id="call_flow_B">
+ <flow-reference>
+ <flow-document-id>flow_def_1</flow-document-id>
+ <flow-id>flowB</flow-id>
+ </flow-reference>
+ </flow-call>
+
+ <view id="content">
+ <vdl-document>/flowA/content.xhtml</vdl-document>
+ </view>
+
+ </flow-definition>
+
+ <flow-definition id="flowB">
+
+ <flow-return id="end">
+ <from-outcome>exit</from-outcome>
+ </flow-return>
+
+ <flow-call id="call_flow_A">
+ <flow-reference>
+ <flow-document-id>flow_def_1</flow-document-id>
+ <flow-id>flowA</flow-id>
+ </flow-reference>
+ </flow-call>
+
+ <view id="content">
+ <vdl-document>/flowB/content.xhtml</vdl-document>
+ </view>
+
+ </flow-definition>
+
</faces-config>
Copied: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowA/flowA.xhtml (from r1743449, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/flow5.xhtml)
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowA/flowA.xhtml?p2=myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowA/flowA.xhtml&p1=myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/flow5.xhtml&r1=1743449&r2=1743767&rev=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/flow5.xhtml (original)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowA/flowA.xhtml Fri May 13 22:35:49 2016
@@ -33,6 +33,8 @@
<h:commandButton value="End" action="content"/>
<h:commandButton id="end_flow" value="End" action="end"/>
<h:commandButton id="back_flow" value="Back" action="back"/>
+ <h:commandButton id="go_flow_B" value="Go to base" action="flowB"/>
+ <h:commandButton id="call_flow_B" value="Call Flow B" action="call_flow_B"/>
<h:commandButton id="go_flow_base" value="Go to base" action="flow_base"/>
</h:form>
<!-- resolve outcome is quite useful to check how the flow target is resolved -->
Copied: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowB/flowB.xhtml (from r1743449, myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/flow5.xhtml)
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowB/flowB.xhtml?p2=myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowB/flowB.xhtml&p1=myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/flow5.xhtml&r1=1743449&r2=1743767&rev=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow5/flow5.xhtml (original)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flowB/flowB.xhtml Fri May 13 22:35:49 2016
@@ -33,6 +33,8 @@
<h:commandButton value="End" action="content"/>
<h:commandButton id="end_flow" value="End" action="end"/>
<h:commandButton id="back_flow" value="Back" action="back"/>
+ <h:commandButton id="go_flow_A" value="Go to base" action="flowA"/>
+ <h:commandButton id="call_flow_A" value="Call Flow A" action="call_flow_A"/>
<h:commandButton id="go_flow_base" value="Go to base" action="flow_base"/>
</h:form>
<!-- resolve outcome is quite useful to check how the flow target is resolved -->
Modified: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml?rev=1743767&r1=1743766&r2=1743767&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml (original)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/application/flow/flow_base.xhtml Fri May 13 22:35:49 2016
@@ -38,6 +38,9 @@
<h:commandButton id="returnFlow4" action="back_flow_4" value="Return Flow 4"/>
<h:commandButton id="returnFlow1_3" action="back_flow_1_3" value="Return from Flow 1 and 3"/>
<h:commandButton id="returnFlow1_4" action="back_flow_1_4" value="Return from Flow 1 and 4"/>
+
+ <h:commandButton id="startFlowA" action="flowA" value="Start Flow A"/>
+ <h:commandButton id="startFlowB" action="flowB" value="Start Flow B"/>
</h:form>
</h:panelGrid>
</h:body>