Hi,
The issue is not about the visibility of components. It's about dynamic modifications to the component tree.
So, why toggling visibility by using the rendered attribute is not enough? First, the user interface of the application is dynamic.
An example of such interface would be a dashboard. The user can create a customized dashboard by choosing components from a catalog and adding them to the dashboard. The rendered attribute is not enough because the same component can be added multiple times but with different attributes. Also, with the rendered attribute it's impossible to adjust the order of the components. c:if has no use in this particular case either, though. Instead, I generate a custom facelet xml on the fly, and use ui:include. It contains the components that the dashboard should have. The same phenomenon occurs here, although I can't say for sure that the exactly same bug causes it. However, it behaves in the same way. Fortunately, in this particular case, I can workaround the problem by reloading the view after adding the logical component to the dashboard. The dashboard is a somewhat trivial case and unfortunately, view reloading is not generally an option.
Secondly, component trees tend to get rather big. Having 5000 components in a view is pretty normal. In certain conditions, some of the subtrees would never be visible to the user. It's silly to have them hanging around just because in some rare conditions they might have some use. Useless subtrees add significant overhead to ajax requests, for example.
As an alternative to c:if and ui:include I could add dynamic components programmatically, and in fact, it would be more convenient. However, there's an open issue (JAVASERVERFACES-3763) that makes this option practically useless.
So, in summary, the rendered attribute has no use in building truly dynamic views or optimizing colossal component trees.
Regards,
Kari Lavikka
> Lenny Primak <lprimak_at_hope.nyc.ny.us> kirjoitti 1.4.2016 kello 13.29:
>
> I have had numerous issues with mixing <c:if> with JSF Facelet markup.
> I would suggest using <xxx rendered=“”> everywhere instead of <c:if>
>
>> On Apr 1, 2016, at 3:23 PM, Kari Lavikka <kari.lavikka_at_bdb.fi> wrote:
>>
>> Hi!
>>
>> I have been struggling with a bug related to composite components and dynamic tree modification using either c:if or ui:include tags. I submitted the initial issue to JIRA almost a year ago, but it was closed as "Works as designed". Probably my description and reproducer were not explicit enough. There have been two other reports about the same bug after that, and the first of them had the same fate - "Works as designed". The last one is still open, though. In this case, being open is better than being closed as "Works as designed"!
>>
>> Anyway, here's a brand new reproducer I created this week: https://github.com/tuner/mojarra-dynamic-include-reproducer/
>>
>> If new instances of a specific composite component are added to the component tree between restore and render phases, the addition sometimes works and sometimes doesn't. This depends on the order the components are added. If the component is added to the end, everything works just as expected. However, if the component is added to the middle or to the beginning, something goes wrong and the contents of a composite component get duplicated. The duplication doesn't happen in the component that was just added, but in the next component in the component tree. If the composite component contains components that have an explicit id, an exception is thrown: Component ID x:x:x has already been found in the view. Otherwise, the contents just get duplicated.
>>
>> But in the tree, what does the order of the components actually mean? It means the order in which the components are encountered when the tree is traversed in-order. Adding "wrapper" components or defining explicit ids for the composite components or their containers seem to have no effect at all.
>>
>> This behavior makes me think that the components are given an index number in the order they are encountered. And when something is added or removed in the middle, the indexing goes wrong and an existing component that we were looking for can't be found. A new one is created instead and the duplication occurs.
>>
>> Component tree creation seems to be so complicated that I have major difficulties trying to understand how it works. By tracing component creation with a debugger, I might have found some clues to this issue, though.
>>
>> In ComponentTagHandlerDelegateImpl there's:
>> String id = getMarkId(ctx, parent);
>> UIComponent c = findChild(ctx, parent, id);
>>
>> MarkId seems to be some sort of build-time identifier for components (or tags?). Depending on whether something was found or not, a component is reused or a new one is created.
>>
>> This is an example of a mark id: 739245247_2_40b31929_2. The first number is a hashcode for the facelet hierarchy, like /web/index.xhtml,/web/component.xhtml. The second number is some sort of index number which is incremented every time a specific facelet hierarchy is encountered. The third one is a tag id, for which I have absolutely no idea where it comes from. And the last number is an index number for the tag id. It is incremented in the same manner as the facelet hierarchy number.
>>
>> Maybe mark id is not related to this issue at all, but to me, this indexing logic looks compatible with the hypothesis I came up while playing with the reproducer I created.
>>
>> I figured out the exact Mojarra versions where the bug initially appeared, and I'm quite certain that it's related to the fix of issue JAVASERVERFACES-2494. However, mark id was introduced prior to this fix, but maybe it wasn't used for component lookup in a critical place.
>>
>> I think I'm not able to fix this myself - this part of Mojarra is just too complex for me to grasp in a reasonable time. Hopefully, my findings have some use solving the issue.
>>
>> Thanks for reading!
>>
>> Regards,
>> Kari Lavikka
>>
>>
>>