jsr372-experts@javaserverfaces-spec-public.java.net

[jsr372-experts] Re: Potential issue with hierarchical variable mapper in Facelets

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Thu, 8 Jan 2015 15:00:14 +0100

Hi,

On Thu, Jan 8, 2015 at 2:26 PM, Edward Burns <edward.burns_at_oracle.com> wrote:
>>>>>> On Thu, 8 Jan 2015 12:38:23 +0100, arjan tijms <arjan.tijms_at_gmail.com> said:
> Ah, welcome to an instance of the biggest challenge we face in evolving
> JSF. While this may not be correct, it is established behavior, and
> rather fundamental behavior at that.

Indeed, it goes rather deep and there's perhaps no telling how much
code (implicitly or explicitly) relies on this.

One additional thing to note though is that a Facelets tag file has
the conditional shared/not shared variable mapper, while a Facelets
include never shares. E.g. in
com.sun.faces.facelets.tag.ui.IncludeHandler.apply(FaceletContext,
UIComponent) we see:

  public void apply(FaceletContext ctx, UIComponent parent) throws IOException {
        String path = this.src.getValue(ctx);
        if (path == null || path.length() == 0) {
            return;
        }
        VariableMapper orig = ctx.getVariableMapper();
        ctx.setVariableMapper(new VariableMapperWrapper(orig));


> I'm leery of changing this established behavior.

If a change turns out to be infeasible (it indeed may well be) then a
far less invasive path to take could be the introduction of some API
that third party libraries can use to provide a workaround for this.

E.g.

* A simple boolean that indicates if a Facelet got a shared variable
mapper or not
* A hook "somewhere" so the process of creating a FaceletContext or
perhaps even a Facelet itself can be intercepted (so e.g. a
FaceletContext and/or a Facelet can be wrapped)

In OmniFaces I just worked around this by letting each tagfile "mark'
the variable mapper and then do some behaviour tests; if it's possible
for a nested tag to remove the outer marker, we know the variable
mapper must be shared. It's a bit weird to have behaviour probing code
in place, and it requires every facelet tag file in an application to
contain an "o:tagAttribute" tag, but it does work it seems.

See https://github.com/omnifaces/omnifaces/blob/master/src/main/java/org/omnifaces/taghandler/TagAttribute.java#L96

Kind regards,
Arjan Tijms