Uploaded image for project: 'MyFaces Core'
  1. MyFaces Core
  2. MYFACES-4542

outbound-parameters not passed to nested flows

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 2.3-next-M7, 4.0.0-RC3
    • 4.0.0-RC4
    • None
    • None

    Description

      A regression was discovered in our testing in RC3 with the switch from JSF managed implicit objects to cdi managed implicit objects.

      In essence, RC2 always used the flowmap (storage?) of the current flow, but RC3 does not. 

      Previously (RC2), the flow scope map was created as with the following stack:

       

      FlowScopeMap.<init>(BeanManager, String) line: 42    
      DefaultCDIFacesFlowProvider.lambda$getCurrentFlowScope$0(FacesContext, Flow, Object) line: 107    
      1548856593.apply(Object) line: not available    
      HashMap<K,V>.computeIfAbsent(K, Function<? super K,? extends V>) line: 1134 DefaultCDIFacesFlowProvider.getCurrentFlowScope(FacesContext) line: 104      <----- Key Call 
      FlowHandlerImpl.getCurrentFlowScope() line: 464    
      FlowScopeImplicitObject.getValue(ELContext) line: 45    
      ImplicitObjectResolver.getValue(ELContext, Object, Object) line: 200    
      CompositeELResolver.getValue(ELContext, Object, Object) line: 62    

       

      Note flow map is initialized with a unique flowMapKey

       

          public FlowScopeMap(DefaultFacesFlowProvider provider, String flowMapKey)
          {
              this._provider = provider;
              this._flowMapKey = flowMapKey;
          }

          
      As for the storage, it's created during a map#put call: 

      FlowScopeContextualStorageHolder(AbstractContextualStorageHolder<T>).getContextualStorage(String, boolean) line: 98
      FlowScopeContextualStorageHolder.getFlowScopeMap(BeanManager, String, boolean) line: 95
      FlowScopeMap.getWrapped(boolean) line: 65
      FlowScopeMap.put(Object, Object) line: 106
      MapELResolver.setValue(ELContext, Object, Object, Object) line: 89

       

      The flowscope is then saved as an attribute on the facesContext (but is cleared once the facesContext is released at the end of the request). A new map is then created in subsequent requests. 

      As for RC3, FlowScopeContext is now the "implict object manager (equivalent o FlowScopeImplicitObject) " of the flow map. (also see FlowScopeExtension for registration details).

      The problem lies in RC3 is with FlowScopeContext#get(Contextual<T> bean)  and FlowScopeContext#get(Contextual<T> bean, CreationalContext<T> creationalContext)

      They look at all activeFlowMapKeys when they should look at only the current flow (as in RC2):

       

              List<String> activeFlowMapKeys = getStorageHolder(facesContext).getActiveFlowMapKeys(facesContext);
              for (String flowMapKey : activeFlowMapKeys)
              {
                  ContextualStorage storage = getContextualStorage(facesContext, false, flowMapKey);
                  if (storage == null)
                 
      {                 continue;             }
      
                  Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
                  ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
                  if (contextualInstanceInfo == null)
                  {                 continue;             }
                  return (T) contextualInstanceInfo.getContextualInstance();
              }
      

       

              
      Relevant Weld Code: 

      https://github.com/weld/core/blob/be7382b01c4a56c54f92873c1c2ebf0445714bfe/impl/src/main/java/org/jboss/weld/bean/ContextualInstanceStrategy.java#L94-L100 

      FlowScopeContext.get(Contextual<T>) line: 182    
      PassivatingContextWrapper$ContextWrapper(PassivatingContextWrapper$AbstractPassivatingContextWrapper<C>).get(Contextual<T>) line: 78    
      ContextualInstanceStrategy$DefaultContextualInstanceStrategy<T>.get(Bean<T>, BeanManagerImpl, CreationalContext<?>) line: 95    
      ContextualInstance.get(Bean<T>, BeanManagerImpl, CreationalContext<?>) line: 50    
      BeanManagerImpl.getReference(Bean<?>, Type, CreationalContext<?>, boolean) line: 680    
      WeldELResolver(AbstractWeldELResolver).lookup(BeanManagerImpl, ELContext, String) line: 107    
      WeldELResolver(AbstractWeldELResolver).getValue(ELContext, Object, Object) line: 90    

      Note if get(bean) returns null then get(bean, creationalContext) is called.  Then the FlowScopeMap object is actually created with this call: storage.createContextualInstance(bean, creationalContext); 

      bean argument in this case is "ForwardingBean flowScope for org.apache.myfaces.cdi.FacesArtifactFlowMapProducer@23deee9" (contains the create(e -> FacesContext.getCurrentInstance().getApplication().getFlowHandler().getCurrentFlowScope())

       

      Attachments

        1. JSF22FacesFlows.war
          28 kB
          Volodymyr Siedlecki

        Issue Links

          Activity

            People

              volosied Volodymyr Siedlecki
              volosied Volodymyr Siedlecki
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: