Return-Path: Delivered-To: apmail-myfaces-dev-archive@www.apache.org Received: (qmail 75900 invoked from network); 18 Mar 2010 01:10:47 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 18 Mar 2010 01:10:47 -0000 Received: (qmail 69264 invoked by uid 500); 18 Mar 2010 01:10:43 -0000 Delivered-To: apmail-myfaces-dev-archive@myfaces.apache.org Received: (qmail 69211 invoked by uid 500); 18 Mar 2010 01:10:43 -0000 Mailing-List: contact dev-help@myfaces.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "MyFaces Development" Delivered-To: mailing list dev@myfaces.apache.org Received: (qmail 69204 invoked by uid 99); 18 Mar 2010 01:10:43 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 18 Mar 2010 01:10:43 +0000 X-ASF-Spam-Status: No, hits=1.5 required=10.0 tests=AWL,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,HTML_MESSAGE,RCVD_IN_DNSWL_NONE,SPF_PASS,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of lu4242@gmail.com designates 209.85.222.204 as permitted sender) Received: from [209.85.222.204] (HELO mail-pz0-f204.google.com) (209.85.222.204) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 18 Mar 2010 01:10:37 +0000 Received: by pzk42 with SMTP id 42so1209640pzk.32 for ; Wed, 17 Mar 2010 18:10:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:date:message-id:subject :from:to:cc:content-type; bh=XDgaEebOTEmtM9Fr8a93SlyYa5gvFcpbPEePWZhodEk=; b=uXiO7b7gxUZYaEI5GOfdPGYuiH/bfUssWrqatzgyKYoLeBs5aWC6KE+PeETAMHC3BB bOrqx032mhQA5zmAkxb3zwWkdQOc4352DEcs7xDUq4vfdFWJzeyA0PbLD5ee+DU6uW2f xk+ZUVoeBjJcBSyfKHNtikHyC+tE5aGsx6Awk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:cc:content-type; b=sQRUYqUIqfYLTWaFHFG5GLV8inAZkQhGjYSI6YJsI05YMOmIrYM+tzp2RTscyOTnqh rebEpFxxz3pdcepK76f+pinWBlpX8yuUXMZDMO1O8/1REHBgeS2NspgHZUGJu/ewwIJv m3Z5Aki1l3F03auyQ08qWoqOSC9jTnm9Qb0hs= MIME-Version: 1.0 Received: by 10.142.248.12 with SMTP id v12mr940939wfh.343.1268874616877; Wed, 17 Mar 2010 18:10:16 -0700 (PDT) Date: Wed, 17 Mar 2010 20:10:16 -0500 Message-ID: Subject: [jsr-314-open] PostAddToViewEvent publishing conditions From: Leonardo Uribe To: jsr-314-open@jcp.org Cc: MyFaces Development Content-Type: multipart/alternative; boundary=00504502c9fecdb45e048208e459 --00504502c9fecdb45e048208e459 Content-Type: text/plain; charset=ISO-8859-1 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, view); FaceletViewDeclarationLanguage._publishPostAddToViewEvent(context, view); } } 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. Suggestions are welcome. regards, Leonardo Uribe --00504502c9fecdb45e048208e459 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Actually the event publishing conditions of PostAddToViewEvent/PreRemoveFro= mViewEvent are not very clear. These conditions depends if partial state sa= ving is used or not and if facelets updates the view or=A0 not. The problem= is this fact is not very intuitive, so for write code correctly the user n= eeds to be aware of that, in other words this should be documented somewher= e. Also, there are some technical questions that could be of interest on th= is mailing list and myfaces dev list too.

In theory, PostAddToViewEvent is used in this cases:

- h:outputS= cript and h:outputStylesheet renderers uses it to relocate component resour= ces to UIViewRoot facet "head" or "body" target (h:outp= utStylesheet by default to "head"). Note "head" and &qu= ot;body" facets are transient.
- cc:insertChildren and cc:insertFacet, to relocate components to some plac= e inside cc:implementation. The reason why we do that through a listener at= tached to PostAddToViewEvent is we need to take into account the case of ne= sted composite components using cc:insertFacet/cc:insertChildren. Note when= the component tree is built the first time, PostAddToViewEvent is propagat= ed from root to nodes.
- When Partial State Saving is enabled, it is necessary to attach a listene= r to PostAddToViewEvent/PreRemoveFromViewEvent, so if some user add/remove = a component, we can keep track of those changes and save/restore the compon= ent tree properly, in other words, support component addition or removal pr= ogramatically.

Now, the instants of time where PostAddToViewEvent is published are:
- With Partial State Saving enabled

=A0=A0 * When the view is b= uild at first time.
=A0=A0 * In a postback when the view is build but be= fore the state of the component is restored.

- With Partial State Saving disabled

=A0=A0 * When the view is b= uild at first time.
=A0=A0 * In a postback when the view is "refres= hed", because all component nodes are detached and attached to the tre= e. In other words, on render response phase, vdl.buildView is called and in= this case facelets algorithm add all transient components (usually all htm= l 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 de= pends on this to work correctly.

A developer that is not aware of this fact could think that PostAddToVi= ewEvent 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-3= 14-open] add component resources depending on the owner component state

It was described why PostAddToViewEvent cannot be used in that case. Bu= t 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 shou= ld work but in fact it only works when PSS is enabled, with PSS disabled th= at code will cause a duplicate id exception. Of course, the developer can s= olve it with some effort but the point is we are not consider the element o= f 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 vie= w is "refreshed" the components are created again, but facelets a= lgorithm remove all components with no bound to a facelet tag handler, and = then the listeners attached to PostAddToViewEvent relocates the new ones, s= o 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 no= w is from nodes to root, because all nodes are detached and attached from n= odes to root, so in myfaces we did something like this (I removed some non = relevant code to be more clear):

=A0=A0=A0=A0=A0=A0=A0 try
=A0=A0=A0=A0=A0=A0=A0 {
=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0 if (refreshTransientBuild)
=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 context.setPro= cessingEvents(false);
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 }
=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0 // populate UIViewRoot
=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 _getFacelet(renderedViewId).apply(context, view);
=A0=A0=A0=A0=A0=A0=A0 }
=A0=A0=A0=A0=A0=A0=A0 finally
=A0=A0=A0=A0=A0= =A0=A0 {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 if (refreshTransientBuild)=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 {
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0 context.setProcessingEvents(true);
=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 // When the facelet is applied, all components are removed and ad= ded from view,
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // but the differ= ence resides in the ordering. Since the view is
=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // being refreshed, if we don't do th= is manually, some tags like
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 // cc:insertChildren or cc:insertFacet will not work correc= tly, because
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // we expect Post= AddToViewEvent will be propagated from parent to child, and
=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // facelets refreshing algori= thm do the opposite.
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 FaceletViewDeclarationLanguage._publishPreRemoveFromViewEvent(contex= t, view);
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 FaceletViewDeclar= ationLanguage._publishPostAddToViewEvent(context, view);
=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0 }
=A0=A0=A0=A0=A0=A0 }

In few words, disable e= vent 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 i= f these components are relocated, are in fact transient too). Also, care mu= st be taken to prevent the listener of programatic component addition/remov= al register components on this time.

The conclusion based on this reasoning, it is clear the need of new eve= nt that be specific for relocate components (keep it simple for christ sake= !). This event should be propagated for all components in the tree after th= e view is build from root to nodes. It could be good to have some clearific= ation about the real intention of PostAddToViewEvent/PreRemoveFromViewEvent= . Really, better names for those events are PostAddToComponentTreeEvent/Pre= RemoveFromComponentTreeEvent.

Suggestions are welcome.

regards,

Leonardo Uribe

--00504502c9fecdb45e048208e459--