myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Nick Belaevski (JIRA)" <>
Subject [jira] Commented: (MYFACES-2638) Fix PostAddToViewEvent and PreRemoveFromViewEvent publishing conditions
Date Fri, 11 Jun 2010 21:32:15 GMT


Nick Belaevski commented on MYFACES-2638:


Thank you for the fix :)

> Fix PostAddToViewEvent and PreRemoveFromViewEvent publishing conditions
> -----------------------------------------------------------------------
>                 Key: MYFACES-2638
>                 URL:
>             Project: MyFaces Core
>          Issue Type: Bug
>          Components: JSR-314
>    Affects Versions: 2.0.0-beta-3
>            Reporter: Leonardo Uribe
>            Assignee: Leonardo Uribe
>         Attachments: MYFACES-2638-3.patch, MYFACES-2638-4.patch, MYFACES-2638-6.patch,
MYFACES-2638-6_1.patch, MYFACES-2638-6_5.patch, MYFACES-2638-6_8.patch, MYFACES-2638-6_9_fix_facets.patch,
> From a discussion of jsr-314-open mailing list:
> Actually the event publishing conditions of PostAddToViewEvent/PreRemoveFromViewEvent
are not very clear. These conditions depends if partial state saving is used or not and if
facelets updates the view or  not. The problem is this fact is not very intuitive, so for
write code correctly the user needs to be aware of that, in other words this should be documented
somewhere. Also, there are some technical questions that could be of interest on this mailing
list and myfaces dev list too.
> In theory, PostAddToViewEvent is used in this cases:
> - h:outputScript and h:outputStylesheet renderers uses it to relocate component resources
to UIViewRoot facet "head" or "body" target (h:outputStylesheet by default to "head"). Note
"head" and "body" facets are transient.
> - cc:insertChildren and cc:insertFacet, to relocate components to some place inside cc:implementation.
The reason why we do that through a listener attached to PostAddToViewEvent is we need to
take into account the case of nested composite components using cc:insertFacet/cc:insertChildren.
Note when the component tree is built the first time, PostAddToViewEvent is propagated from
root to nodes.
> - When Partial State Saving is enabled, it is necessary to attach a listener to PostAddToViewEvent/PreRemoveFromViewEvent,
so if some user add/remove a component, we can keep track of those changes and save/restore
the component tree properly, in other words, support component addition or removal programatically.
> Now, the instants of time where PostAddToViewEvent is published are:
> - With Partial State Saving enabled
>    * When the view is build at first time.
>    * In a postback when the view is build but before the state of the component is restored.
> - With Partial State Saving disabled
>    * When the view is build at first time.
>    * In a postback when the view is "refreshed", because all component nodes are detached
and attached to the tree. In other words, on render response phase, vdl.buildView is called
and in this case facelets algorithm add all transient components (usually all html markup
not saved), and to do that, it detach and attach all components to be in right order. This
also has some other implications, like c:if tag depends on this to work correctly.
> A developer that is not aware of this fact could think that PostAddToViewEvent is called
when the view is build.
> This is true with PSS is enabled, but is not true when PSS is disabled. On this topic:
> [jsr-314-open] add component resources depending on the owner component state
> It was described why PostAddToViewEvent cannot be used in that case. But let's change
a litte bit the problem. We have a custom component that creates some other on PostAddToViewEvent
and add it as a children. It should work but in fact it only works when PSS is enabled, with
PSS disabled that code will cause a duplicate id exception. Of course, the developer can solve
it with some effort but the point is we are not consider the element of least surprise.
> But this fact this is only the tip of the iceberg. In mojarra (this was already fixed
on myfaces), components relocated by cc:insertChildren or cc:insertFacet does not have state
when PSS is disabled, because when the view is "refreshed" the components are created again,
but facelets algorithm remove all components with no bound to a facelet tag handler, and then
the listeners attached to PostAddToViewEvent relocates the new ones, so this effect is not
notice at first view.
> Do you remember PostAddToViewEvent propagation ordering is important by cc:insertChildren/cc:insertFacet?
well, with PSS disabled, the ordering now is from nodes to root, because all nodes are detached
and attached from nodes to root, so in myfaces we did something like this (I removed some
non relevant code to be more clear):
>         try
>         {
>             if (refreshTransientBuild)
>             {
>                 context.setProcessingEvents(false);
>             }
>             // populate UIViewRoot
>             _getFacelet(renderedViewId).apply(context, view);
>         }
>         finally
>         {
>             if (refreshTransientBuild)
>             {
>                 context.setProcessingEvents(true);
>                     // When the facelet is applied, all components are removed and added
from view,
>                     // but the difference resides in the ordering. Since the view is
>                     // being refreshed, if we don't do this manually, some tags like
>                     // cc:insertChildren or cc:insertFacet will not work correctly, because
>                     // we expect PostAddToViewEvent will be propagated from parent to
child, and
>                     // facelets refreshing algorithm do the opposite.
>                     FaceletViewDeclarationLanguage._publishPreRemoveFromViewEvent(context,
>                     FaceletViewDeclarationLanguage._publishPostAddToViewEvent(context,
>             }
>        }
> In few words, disable event processing, and fire PostAddToViewEvent and PreRemoveFromViewEvent
in the expected order to build the tree correctly. If we don't do this, h:outputScript and
h:outputStylesheet will not work correctly (remember that UIViewRoot "head" and "body" facets
are transient, so if these components are relocated, are in fact transient too). Also, care
must be taken to prevent the listener of programatic component addition/removal register components
on this time.
> The conclusion based on this reasoning, it is clear the need of new event that be specific
for relocate components (keep it simple for christ sake!). This event should be propagated
for all components in the tree after the view is build from root to nodes. It could be good
to have some clearification about the real intention of PostAddToViewEvent/PreRemoveFromViewEvent.
Really, better names for those events are PostAddToComponentTreeEvent/PreRemoveFromComponentTreeEvent.
> I'll attach a proposal to fix this one soon.

This message is automatically generated by JIRA.
You can reply to this email to add a comment to the issue online.

View raw message