Missing parameter values ​​in the called method with composite components using ui: repeat

So, after several days of debugging, we were eventually able to reproduce some strange interactions between the constituent components of ui:repeat , p:remoteCommand and partial state persistence in JSF, which we do not understand.

Scenario

A composite component iterates over a list of objects using ui:repeat . During each iteration, one more component is included and arguments are passed.

 <ui:composition (...)> <ui:repeat var="myVar" value="#{cc.attrs.controller.someList}"> <namespace:myRemoteCommand someParam="SomeParam"/> 

The included component has an autorun p:remoteCommand that calls the method using the parameters defined in the component's interface.

 <ui:component (...)> <p:remoteCommand actionListener="#{someBean.someMethod(cc.attrs.someParam)}" autoRun="true" async="true" global="false"> 

However, when setting a breakpoint in someMethod(...) , an empty string is passed. This only happens if partial state retention is set to false .

Decision

We tried several solutions, and the following work (however, we do not understand why and cannot foresee further problems that may arise):

  • We can set the partial state to true .

  • We can change the component template to ui:include .

  • We can remove one or both of the component components and directly include the content.

Question

Why does JSF behave like this? What is the interaction between the composite component, ui:repeat and passing arguments, which varies depending on whether we use ui:include / partial state preservation or not?

We use Primefaces 5.3, Glassfish 4.1, Mojarra 2.2.12, Java 8.

+6
source share
1 answer

Your code is fine. It is just that Mojarra <ui:repeat> broken. You are not the first to encounter a governance problem related to governance, with <ui:repeat> .

The root cause of your problem is that #{cc} nowhere available when <ui:repeat> needs to visit a tree. Effectively, <ui:repeat value> null . The quick work is to explicitly press the #{cc} button in UIRepeat#visitTree() . Given Mojarra 2.2.12, add the lines below line 734 using pushComponentToEL(facesContext, null) .

 UIComponent compositeParent = getCompositeComponentParent(this); if (compositeParent != null) { compositeParent.pushComponentToEL(facesContext, null); } 

And add below the line immediately after line 767 with popComponentFromEL(facesContext) .

 if (compositeParent != null) { compositeParent.popComponentFromEL(facesContext); } 

If you do not create Mojarra from the source, copy the entire source code of UIRepeat into your project, preserving its package structure and apply changes over it. Classes in /WEB-INF/classes have a higher load priority than in /WEB-INF/lib and the /lib server. I at least created question 4162 to solve this problem.

An alternative is replacing Mojarra with MyFaces or replacing <ui:repeat> with a UIData component that has received state control on the right, for example, <h:dataTable> or <p:dataList> .

 <p:dataList type="none" var="myVar" value="#{cc.attrs.controller.someList}"> <namespace:myRemoteCommand someParam="SomeParam" /> </p:dataList> 

You can use CSS only to get rid of the widget's style (borders, etc.), but trivial .

See also:

+4
source

All Articles