Hi
2014-04-06 18:53 GMT+02:00 Frank Caputo <frank_at_frankcaputo.de>:
> Hi,
>
> Am 27.03.2014 um 12:45 schrieb Leonardo Uribe <lu4242_at_gmail.com>:
>
>> 2. Use jsf:binding in Mojarra does not work, but it is not in the
>> documentation of jsf:element. But the same is true for id attribute and
>> these attributes comes from UIComponentBase. This is a bug in Mojarra and
>> should be fixed.
>
> binding indeed doesn't work. I think, PassThroughElementComponentHandler should work more like ComponentTagHandlerDelegateImpl. Did you already file a bug?
> id works, though it is not documented.
>
I have not created a bug, since this is implementation specific.
> We should add id, rendered, transient and binding to the documentation.
>
Ok. but do not add "transient", because it is something internal of
the component,
not to be used by the user (but f:view transient="true" is valid)
>> 3. I have explained to Frank that in some cases http://xmlns.jcp.org/jsf
>> put attributes into normal component attribute map but sometimes it is
>> required to use the passthrough attribute map. "id", "binding", "rendered"
>> and "transient" should not be put on passthrough attribute map, but other
>> attributes should.
>
> If you use the jsf namespace on the attributes correctly, you can easily control, into which map the attribute is put. We should not try to implement some magic which fixes user mistakes. No attribute makes it ever into both maps (see com.sun.faces.facelets.tag.DefaultTagDecorator.ElementConverter#convertTagAttribute).
>
Yes, I know but that's the point of all this issue, in MyFaces we have
implemented
the spec exactly the way it says but it doesn't work because there is
something missing in the spec javadoc, that was added in Mojarra to make
it work.
In other words we are in a situation that we can't enforce the spec because that
will be perceived at the end by the users as a bug "... this is
working in Mojarra
but it is not in MyFaces ...". I want to avoid that situation.
>> In conclusion we have these 3 cases:
>>
>> 1. Attributes with jsf namespace that should be put on passthrough
>> attribute map.
>>
>> <div jsf:style="noprint">
>> Hello World!
>> </div>
>
> This doesn't make sense. Why don't you simply use <div style="noprint">...? But your example works in Mojarra, because PassthroughElement handles style and styleClass (which is not documented and so it shouldn't work).
>
It has sense. For example:
<div jsf:style="noprint">
<f:ajax event="click" listener="..."/>
Hello World!
</div>
The point is there are some scenarios when you want that the div works as a JSF
component. This doesn't work:
<div style="noprint">
<f:ajax event="click" listener="..."/>
Hello World!
</div>
because the compiler does not get the div as a component, just as html markup
but we want that by performance reasons.
The key point is attributes marked with jsf namespace has another meaning
which is "... convert this tag into a jsf markup component ..:".
Try with any other attribute from style and you'll see it works in Mojarra,
because internally somehow the attribute is copied in both places, in the normal
attribute map and in the passthrough attribute map. I have already tested by
the way.
>> 2. Attributes with jsf namespace that should be put on normal attribute map.
>>
>> <div jsf:binding="#{boxBean.box1}">
>> Hello World!
>> </div>
>
> See above, this should be fixed. But I still want to stay with the behavior, that EVERY jsf:xxx attribute will be put on the normal attribute map.
>
so do I, but only if the attribute has been defined in the component class,
otherwise put it in the passthrough attribute map.
>> <input jsf:id="input" type="text" jsf:value="#{someBean.someValue}"/>
>
> This works.
>
yes and it should continue working. That's my intention
>> 3. Attributes without any namespace that could overlap attributes in the
>> normal component map that requires special treatement.
>>
>> <div jsf:binding="#{boxBean.box1}" onclick="alert('hello')">
>> <f:ajax event="click" render="renderMe"/>
>> Hello World!
>> </div>
>
> There is a clear rule for overlapping: passtrough attributes take precedence. I like that simple rule without any exceptions.
>
But there is no point to add attributes like onclick and others in
jsf:element if
at the end they will get overriden by the passthrough and f:ajax and other
client behavior destroyed on the way.
>> What should we do? What's the ideal behavior?
>>
>> - First of all we need to recognize that in this case attributes marked with
>> empty namespace and with jsf namespace behave the same. The only special
>> property it has jsf namespace is that its presence in an attribute makes the
>> tag susceptible to be converted.
>>
>> - If the attribute is declared by the component class, it should be added to
>> the component attribute map.
>>
>> - If the attribute is declared by the component class, it should NOT be added
>> to the passthrough attribute map.
>>
>> - If the attribute is NOT declared by the component class, it should be put
>> on the passthrough attribute map.
>>
>> How can we detect if a component class has a property defined? there is no
>> standard way to do that, but each JSF implementation has the code deep inside
>> UIComponentBase implementation, specifically in the normal component
>> attribute map. But that suppose a problem, because in the moment the default
>> TagDecorator is active, there is not a component class yet. But the trick
>> can be done with a new Rule, but it will not be easy.
>
> This is impossible, because users are free to put whatever they want into both attributes maps. The implementation can't decide, if the attribute in the attribute map should be there or it is just a mistake.
>
It is possible, I have already done in myfaces. In fact, facelets do something
like that since 1.1.x. Take a look at ComponentRule implementation. It should
be a line like this:
else if (meta.getWriteMethod(name) == null)
That line do the trick. In my opinion, the user don't care where the
attribute is put
as long as the intention of this feature can be honored. I can't see any problem
doing that, because this component is just a wrapper for html markup.
> From my point of view, we have a really simple rule, saying that every jsf: attribute will be on the component attributes map and any other is on the passthrough attributes map.
>
Unfortunately that's not an option. We need something more elaborated to make
things work.
>> This strategy has the big advantage that the attributes are not duplicated, so
>> the state size is not doubled.
>
> As said before, attributes are not doubled (i can't find it in the implementation).
>
It is there, I have reviewed, with the debugger, but that's the point.
There is no
mention of that in the spec, so it should be an implementation detail in Mojarra
added at some point of the time. MyFaces doesn't have it, because it is a
complete different implementation, so I can't help more.
>> The objective is avoid changes in the spec if
>> possible, so let's see what we can do.
>
> I'll answer your other mail with the proposed changes a bit later (hopefully this week).
>
Ok, thanks for your help with this.
regards,
Leonardo
> Ciao Frank
>
>>
>> regards
>>
>> Leonardo
>>
>> 2014-03-25 2:12 GMT+01:00 Edward Burns <edward.burns_at_oracle.com>:
>>>>>>>> On Mon, 24 Mar 2014 13:39:21 +0100, Leonardo Uribe <lu4242_at_gmail.com> said:
>>>
>>> LU> But the user has reported another more troublesome combination:
>>>
>>> LU> <li jsf:class="toclevel-1 tocsection-2"/>
>>>
>>> LU> According to the spec it should not work. The javadoc of
>>> LU> javax.faces.view.facelets.TagDecorator
>>> LU> says this (already mentioned before):
>>>
>>> LU> "... If the current attribute's namespace is http://xmlns.jcp.org/jsf,
>>> LU> convertedTagAttribute's qualified name must be the current attribute's local
>>> LU> name and convertedTagAttribute's namespace must be the empty string. This
>>> LU> will have the effect of setting the current attribute as a proper property
>>> LU> on the UIComponent instance represented by this markup. ..."
>>>
>>> LU> If the intention of jsf namespace is put the attribute into the
>>> LU> attribute map, why that syntax should work, unless the attribute has
>>> LU> been explicitly declared on jsf:element component.
>>>
>>> I haven't checked the code, but I expect the reason it works is due to
>>> the old attribute/property transparency. First it looks for a
>>> "setClass" method on the UIComponent instance. Failing to find it, it
>>> calls UIComponent.getAttributes().put("class", "toclevel-1 tocsection-2").
>>>
>>> LU> I tried also this
>>> LU> combination:
>>>
>>> LU> <div jsf:style="noprint">
>>> LU> Hello World!
>>> LU> </div>
>>>
>>> LU> It works again, but it shouldn't.
>>>
>>> Again, I expect this causes UIComponent.getAttributes().put("style",
>>> "noprint").
>>>
>>> LU> But it is clear why it is an obvious combination. The same javadoc
>>> LU> of TagDecorator detects any attribute with the namespace "jsf" and
>>> LU> if it is found the tag is binded to a jsf:element component. The
>>> LU> related line says this:
>>>
>>> LU> "... If one or more of the attributes of the tag argument are in the
>>> LU> http://xmlns.jcp.org/jsf namespace, obtain a reference to decoratedTag as
>>> LU> described in the following steps and iterate through the list of TagDecorator
>>> LU> instances as described in the preceding step ..."
>>>
>>> Yes, that text is the catch-all that allows the whole passthru elements
>>> feature to work.
>>>
>>> LU> In practice, it seems an attribute using "jsf" namespace should be
>>> LU> added in both normal attribute map and passthrough attribute map. I
>>> LU> can't detect any problem at the moment, because the logic in the
>>> LU> default ResponseWriter keeps track of the rendered attributes, and
>>> LU> as long as no logical attributes are copied, things will be
>>> LU> fine. Here there is an example of the problem:
>>>
>>> LU> <div jsf:binding="#{boxBean.box1}">
>>> LU> Hello World!
>>> LU> </div>
>>>
>>> LU> In Mojarra this attribute is just ignored, so it doesn't work, but
>>> LU> in MyFaces it works, but if the attributes are copied in both maps,
>>> LU> this one will be a problem. So the algorithm should duplicate the
>>> LU> attributes that are not reserved like "id", "binding", "rendered" or
>>> LU> "transient".
>>>
>>> I would have to step through this in a debugger to authoritatively
>>> comment on what the spec intent is here, and therefore to clearly define
>>> what "in MyFaces it works" means in this case.
>>>
>>> LU> There are a couple of attributes that are implementation specific,
>>> LU> but since they are not declared in the markup, they do not have the
>>> LU> chance to be copied or overriden.
>>>
>>> I'd like to avoid having to do this.
>>>
>>> LU> It is curious this syntax does not work:
>>>
>>> LU> <div pt:style="noprint">
>>> LU> Hello World!
>>> LU> </div>
>>>
>>> LU> The tag is not converted into a jsf:element, so the compiler sees it as
>>> LU> html markup.
>>>
>>> I would need to see to that namespace the pt: attribute prefix is
>>> bound. If it is the xmlns.jcp.org pass through attribute namespace,
>>> then it should work and that is a bug.
>>>
>>> LU> I do not see any other choice than force the copy to the passthrough
>>> LU> attribute map of all attributes declared with jsf namespace. But I have
>>> LU> to warn about a side effect over the state. If the attributes are copied
>>> LU> twice, that means the state of that component is effectively doubled.
>>> LU> If PSS is properly implemented, it will not have a significant effect
>>> LU> over the state, because most of the time that part is not part of the
>>> LU> "delta" state of the component.
>>>
>>> I must understand why the copy is necessary.
>>>
>>> Ed
>>>
>>> --
>>> | edward.burns_at_oracle.com | office: +1 407 458 0017
>>> | 0 Work Days Til JavaLand 2014
>>> | 30 Work Days til JAX 2014
>>
>
>