On 5/22/10 9:36 PM, Leonardo Uribe wrote:
Hi
After some attempts I was able to make it work ( see
MYFACES-2638-6_5.patch ).
Great!
I think I'll delay a little bit myfaces core 2.0.1 release,
because
this solution has enought importance to be included. Definitively, the
way to go is use TemplateClient stuff here.
Agreed. Should have much cleaner results than the current system event
approach to insertion.
In the long term, it is necessary to think how to create a good api
for TemplateClient stuff. Right now, DefaultFaceletContext /
DefaultFacelet classes do too many things (generate facelets ids to
isolate id generation between templates, template client api stuff,
handle facelet inclusion ......). On myfaces, the position about
change those classes is do not modify the code there too much, so in
the future if a new API is published (jsf 2.1?) we could change the
code without much effort.
Sure, I think this would be worth exploring in 2.1. We should also try
to understand how the AST proposal impacts all of this.
In the next days I'll check this patch and document it better.
About mojarra issue 1684 (thanks for the hint), doing the patch it was
clear what the intention of the current design:
1) What is the purpose of extendClient() and why just having
pushClient() was
not enough?
2) Why does CompositionHandler call extendClient(), while
DecorateHandler calls
pushClient()?
On DefaultFaceletContext, there is a List<TemplateManager> that holds
the current templates (clients) that are used to resolve a "spot"
identified by a name.
The basic idea is when FaceletContext.includeDefinition(UIComponent
parent, String name) is called, the algorithm try to resolve the
"spot" from top to bottom.
<ui:composition> and <ui:insert> are added at last, using
extendClient(), but <ui:decorate> or user tag handlers create from
xhtml use pushClient(). The idea is resolve in this order:
- ui:decorate spots defined by ui:define and user tag handlers created
from xhtml (again defined by ui:define).
- ui:composition spots defined by ui:define.
- ui:insert spots.
Sure, this is how things are currently implemented, but this the
reasoning behind this approach is still not clear.
According to the old Facelets doc:
https://facelets.dev.java.net/nonav/docs/dev/docbook.html#templating-deco...
The only difference between ui:composition and ui:decoration is that
ui:composition strips surrounding content whereas ui:composition will not:
The decorate tag acts the same as a composition tag, but it will not
trim everything outside of it.
Given that ui:decorate is a non-trimming ui:composition, why would these
behave differently with respect to interaction with the TemplateClient?
I would think that both of these handlers should be calling pushClient().
Also, the multi-level search strategy seems somewhat questionable to
me. A template exposes a certain number of of names into which content
could be inserted. The consumer of the template leverages that contract
and specifies content to be inserted into some subset of those names.
When attempting to locate content to insert, why should the template
look any further up the stack than the nearest consumer (ie. the most
recently pushed TemplateClient)?
Seems like this should have been implemented as a simple stack solution
where the most recent TemplateClient is always used to resolve insertions.
Of course, there may be perfectly fine reasons for why Facelets supports
extendClient() and performs multi-level searches to locate content to
insert. Just not clear what these reasons are.
Note that for composite components, we should not follow the Facelets
precedent here. If a composite component exposes a facet for
insertion, we should only look to immediate consumer of the composite
component for matches - ie. we should not be walking up the entire
ancestor stack.
3) Why does InsertHandler call extendClient()() and why does it
implement
TemplateClient?
Because ui:insert could expose a spot too, and it is resolved to there
if no ui:define (exposed by ui:composition) with the name is exposed too.
Right, so I see that InsertHandler is implemented this way, but... why?
Seems silly to have ui:insert serve two entirely different purposes -
ie. to both identify an insertion point as well as to define content for
included templates. Why should ui:insert act both as a ui:insert *and*
as a ui:define? If a template author wants to pass content through
from an outer page to an inner/nested template, seems like the right way
to accomplish this would be to wrap the ui:insert inside of a ui:define.
Again - don't think composite components should follow the Facelets
precedent here.
Also wonder whether we should be cleaning this up on the Facelets side
for 2.1.
Andy
best regards,
Leonardo Uribe