Gang - I have been spending a lot of time thinking about this topic and reading the doc/looking at the source code. I can now say that I definitely understand the difference between composite:insertFacet and composite:renderFacet. :-) However, I am still confused about why we decided to go with two separate tags and wanted to share my thoughts. FWIW, I realize that it is like a year late to be bringing this up, but thought it was important to discuss even if our options are limited at this point. Let's start by taking a look at composite:insertFacet: <composite:implementation> <h:panelGrid> <composite:insertFacet name="caption"/> </h:panelGrid> </composite:implementation> In the above case, the component specified for the "caption" facet ends up in the facet map of the h:panelGrid component. This has certain implications - eg. the component's parent property will point to the h:panelGrid instead of the composite component. If we happen to insert the facet into a NamingContainer, the client id will reflect this. Currently we provide no way to insert a composite component's facet into one of the composite's implementation components as a plain old (non-facet) child. So, if instead of inserting the "caption" facet as a facet on an h:panelGrid, I wanted to insert it as a (non-facet) child of an h:panelGroup, eg: <composite:implementation> <h:panelGroup> <!-- Insert the facet as a direct child here --> </h:panelGroup> </composite:implementation> I cannot do that. Or, at least, I cannot do that with the same semantics as <composite:insertFacet>, where the component specified via the facet ends up as a child of the containing component (the h:panelGroup). I can, however, use composite:renderFacet: <composite:implementation> <h:panelGroup> <composite:renderFacet name="caption"/> </h:panelGroup> </composite:implementation> This will cause the facet to be rendered as a child of the h:panelGroup, but without being a child of the h:panelGroup. This raises a number of questions. Why do we re-parent the facet component when we want the component to be used by the parent component as a facet, but not when we want the component to be used by the parent as a direct child? Is there a reason why we need to treat the direct child case differently (not re-parent) than the facet case (re-parent)? Is there some benefit to having subtly different behavior between these two cases? My feeling is that the good old Facelets ui:insert tag got this right. Facelets uses a single tag to handle insertion of ui:define'd components into the template, regardless of whether the components are being inserted as facets or directly children. So, for example, assuming I've got a template that allows insertion of a "foo" component, I can do either this: <h:panelGrid> <f:facet name="caption"> <!-- Insert the "foo" component into the "caption" facet --> <ui:insert name="foo"/> </f:facet> </h:panelGrid> Or this: <h:panelGroup> <!-- Insert the "foo" component as a non-facet child --> <ui:insert name="foo"/> </h:panelGroup> While the first case inserts the component as a facet and the second as a direct child, both have the same semantics - ie. in both cases the component that is being inserted ends up as a child of the parent component that the child is being inserted into. Actually, Facelets provides an API that is specifically designed to handle this type of insertion: TemplateClient. The TemplateClient API allows for clean/efficient insertion of included content into templates. I believe that ui:define/ui:insert use this to insert included content directly into the target location, avoiding the need to re-locate the included components from one parent to another. This has benefits when re-applying tags over a restored component tree, since there is no need to repeatedly re-create (or re-locate) these components. After thinking this through, one other question that I am left with is: Is there a reason why we did not follow the ui:insert approach? Yes, I realize that this is a moot point now, and no reason to dwell on this, but I am still curious as to whether there were limitations/problems with the ui:insert mechanism that prevented us from following this precedent. If we had the ability to revisit the design now, my preferred solution would be to: 1. Deprecate/remove composite:renderFacet. 2. Re-spec composite:insertFacet to match the behavior of ui:insert. I prefer this approach because I feel that we should share a single insertion behavior across all of these use cases. The fact that we have 3 subtly different mechanisms is, well... bad. I also think that the ui:insert approach has already been proven, which is in part why I favor that approach. Of course, I don't imagine that we have the ability to make this change given that the JSF 2.0 spec has been final for some time now, and this would be a significant change. I suppose my second choice would be to deprecate both composite:renderFacet/composite:insertFacet in JSF 2.1 and replace both of these with a new composite:insert tag that matches ui:insert behavior. Getting back to our original problem of not having control over the "target" facet name: > If the spec does not yet provide a solution for this, I think that we > could/should solve this in one of two ways: > > 1. Add an attribute to composite:insertFacet that allows a target > facet name to be specified: > > <h:panelGrid> > <composite:insertFacet name="backupCaption" targetName="caption"/> > </h:panelGrid> > > 2. Specify that the target facet name can be picked up from a wrapping > <f:facet> tag: > > <h:panelGrid> > <f:facet name="caption"> > <composite:insertFacet name="backupCaption"/> > </f:facet> > </h:panelGrid> I still prefer #1 as this is closer to ui:insert behavior, but given that I have more fundamental reservations about composite:insertFacet/composite:renderFacet, I don't feel especially strongly about forcing #1 if people prefer #2. Andy Ken Paulsen wrote: > > When / where should this discussion take place? Do we want to have a > call for this? > > In addition to this issue, Alexander raised the issue that > f:insertFacet and f:renderFacet are confusing. Not sure if there's > anything we can do resolve this at this point, but minimally, it would > be worth ensuring the EG members understand the difference (which IMO, > is huge). In hindsight, f:insertFacet probably should have been > f:attachFacet, and of course had an optional "target" attribute for > Andy's case. > > Ken > > Andy Schwartz wrote: >> Thanks Ed - >> >> Ed Burns wrote: >>> >>> I happen to prefer #1, but everyone else favors #2, we'll go with #2. >>> >> >> Seems like some people prefer #2 as well, so perhaps this needs more >> discussion. >> >>> Andy, can you please file a spec issue and share the number with the >>> group? Once you have it, I'll add an entry in the changelog wiki. >>> >>> >> >> Sorry for taking so long to follow up on this. I have logged the >> following spec issue: >> >> https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=631 >> >> >> Andy >> >>
-- Lincoln Baxter, III Co-Founder of OcpSoft Creator of: PrettyFaces: URL rewriting for JSF PrettyTime: Java elapsed timestamp formatting |