You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Roger Keays <ro...@ninthavenue.com.au> on 2007/03/23 03:04:32 UTC

A simple alternative to the ExtensionFilter

Hi guys,

For those people who've had problems with the MyFaces ExtensionFilter, 
I've blogged about a simple alternative that you might find useful:

http://www.ninthavenue.com.au/blog/myfaces_filter

It's not exactly rocket science - basically just hand coding the 
resources in your <head> section.

Roger

-- 
----------------------------------------
Ninth Avenue Software
p: +61 7 3137 1351 (UTC +10)
f: +61 7 3102 9141
w: http://www.ninthavenue.com.au
e: info@ninthavenue.com.au
----------------------------------------


Re: A simple alternative to the ExtensionFilter

Posted by Roger Keays <ro...@ninthavenue.com.au>.
Simon Kitching wrote:
> Mike Kienenberger wrote:
>> Roger blogged,
>>> With separate build and render phases, you could have a <h:head> 
>>> component which
>>> other components could add resources to as they are created during 
>>> the tree build.
>>
>> Hmm.   I wonder if we could implement this for facelets/branch 1.2.
> 
> Probably not.
> 
> The point is that components don't know at the time they are *created* 
> whether they want to insert stuff into the head or not; they only know 
> that at *render* time. And by then the head tag has already rendered 
> itself. Well, unless we allow every component in the page to output its 
> required resources regardless of whether it is later rendered or not.

That's a good point. I'd probably still elect to render resources which 
aren't actually required than to use a filter though.

A possible solution might be to have the resources component (which is 
added the head component) inherit the 'required' attribute of the main 
component. This behaviour could possibly be overridden by a 
'resourcesRequired' attribute on the main component.

It wouldn't be too hard to come up with use cases where this wouldn't 
work perfectly, but I reckon it'd cover the most common scenarios.

Roger

> 
> A head tag could be useful though; currently the ReducedHTMLParser is 
> needed to parse the page and find the <head> tag. It's not simply a 
> matter of looking for that string due to things like
>   <!-- the <head> is not here -->
>   <script>
>     var s = "<head>";
>   </script>
> etc. However a head tag could output a unique marker like
>   <!--HEAD12345567890-->
> which could more easily be scanned for by the ExtensionsFilter. This 
> marker approach is already used for figuring out where to insert 
> serialized client state etc.
> 
> 
> Items 1,2 and 3 of the blog are all issues that could be pretty easily 
> fixed in the ExtensionsFilter. Not that I'm claiming it's a great 
> solution, but a fixed ExtensionsFilter would be better than hand-coding 
> resources in the head section.
> 
> Cheers,
> 
> Simon
> 


-- 
----------------------------------------
Ninth Avenue Software
p: +61 7 3137 1351 (UTC +10)
f: +61 7 3102 9141
w: http://www.ninthavenue.com.au
e: info@ninthavenue.com.au
----------------------------------------


Re: A simple alternative to the ExtensionFilter

Posted by Jeff Bischoff <jb...@klkurz.com>.
Simon Kitching wrote:
> 
> You're right though that people shouldn't *rely* on this. However I'm 
> definitely guilty of having used the rendered property of a 
> <t:inputHidden> or similar to trigger bean initialisation, and assumed 
> it occurs before EL expressions on other tags are invoked, ie that the 
> rendering does a normal depth-first traversal. I might even have assumed 
> that it happens only once during the render phase..

Bad Simon! No supper for you tonight!




Re: A simple alternative to the ExtensionFilter

Posted by noah <ia...@gmail.com>.
On 3/22/07, Simon Kitching <si...@rhe.co.nz> wrote:
> As you say, an alternative is to walk the entire tree when the head tag
> is rendered (not just the children of the head) looking for components.
> In that case, when rendered is false for a particular node then its
> children can be skipped. It does feel rather odd for a component to go
> looking at components other than its children when rendering.

Not to run this discussion into the dirt but, it could wrap the entire
body, something like:

<html>
<h:head>
<f:facet name="otherStuffThatGoesInHead">
<h:panelGroup>
<title>Look Ma, no filter!</title>
<link ... />
</h:panelGroup>
</f:facet>

...page body...

</h:head>
</html>

But, I don't think there is an effective difference between the two,
just semantics. The second semantics would conflict with components
that want to do something similar, like Trinidad's tr:document.  Or is
it the depth of the looking that is odd?

Re: A simple alternative to the ExtensionFilter

Posted by Simon Kitching <si...@rhe.co.nz>.
noah wrote:
> On 3/22/07, Simon Kitching <si...@rhe.co.nz> wrote:

>> The rendered state of a component depends upon the rendered state of all
>> its parent components, so the rendered property of many components in
>> the page would need to be evaluated.
> 
> But if you determine that the parent is not rendered, you can skip the
> rest of that branch, right?

Yes, if you're walking the tree from the top down.

I was thinking about the approach where each component on creation finds 
the ancestor HEAD component and adds itself to a list on that object so 
that the HEAD component can easily find components to check when it 
renders. In that case, for each component it would be necessary to walk 
up the ancestor tree to the UIViewRoot, then walk back down that chain 
again evaluating the rendered attribute on each node (giving up if any 
is false). Doable, but seems odd - and potentially inefficient unless 
some kind of map is kept of what nodes have already been evaluated to 
avoid calling rendered multiple times.

As you say, an alternative is to walk the entire tree when the head tag 
is rendered (not just the children of the head) looking for components. 
In that case, when rendered is false for a particular node then its 
children can be skipped. It does feel rather odd for a component to go 
looking at components other than its children when rendering.

> 
>> And in some cases evaluating a
>> rendered EL expression can have side-effects; yes it is poor style to do
>> so but it's not uncommon.
> 
> Really? I'm fairly certain I've seen (in my logs, debugging, etc.)
> most of the EL expressions in a page get evaluated multiple times.
> Does the spec not say anything about EL being consistent?  Relying on
> EL being evaluated only once seems like it has to violate some aspect
> of the spec. I always assumed that my expression would be evaluated
> multiple times and cached appropriately (i.e. when it involved a DB
> hit or whatever) for this very reason.  Most of my experience is with
> Facelets, does JSP do it differently?
> 
> At the very least, if the spec doesn't say that the EL for rendered
> must not be evaluated more than once, relying on that behavior seems
> like it might not be a good idea. But I can't find the relevant
> portion of the spec right now.

I can't remember anything in the spec that explicitly states it, but I 
would expect rendered should be evaluated:
  * once before processDecodes
  * once before processValidators
  * once before processUpdates
  * once before encodeBegin

In particular, the "once before encodeBegin" should really be true; 
there doesn't seem to be a good reason to call it multiple times during 
the render phase.

You're right though that people shouldn't *rely* on this. However I'm 
definitely guilty of having used the rendered property of a 
<t:inputHidden> or similar to trigger bean initialisation, and assumed 
it occurs before EL expressions on other tags are invoked, ie that the 
rendering does a normal depth-first traversal. I might even have assumed 
that it happens only once during the render phase..

Cheers,

Simon

Re: A simple alternative to the ExtensionFilter

Posted by noah <ia...@gmail.com>.
On 3/22/07, Simon Kitching <si...@rhe.co.nz> wrote:
> First, please read:
>    http://www.nabble.com/How-to-reply-to-emails-tf3182877.html#a8833555
Sorry. Good rule.
> The rendered state of a component depends upon the rendered state of all
> its parent components, so the rendered property of many components in
> the page would need to be evaluated.

But if you determine that the parent is not rendered, you can skip the
rest of that branch, right?

> And in some cases evaluating a
> rendered EL expression can have side-effects; yes it is poor style to do
> so but it's not uncommon.

Really? I'm fairly certain I've seen (in my logs, debugging, etc.)
most of the EL expressions in a page get evaluated multiple times.
Does the spec not say anything about EL being consistent?  Relying on
EL being evaluated only once seems like it has to violate some aspect
of the spec. I always assumed that my expression would be evaluated
multiple times and cached appropriately (i.e. when it involved a DB
hit or whatever) for this very reason.  Most of my experience is with
Facelets, does JSP do it differently?

At the very least, if the spec doesn't say that the EL for rendered
must not be evaluated more than once, relying on that behavior seems
like it might not be a good idea. But I can't find the relevant
portion of the spec right now.

Re: A simple alternative to the ExtensionFilter

Posted by Simon Kitching <si...@rhe.co.nz>.
First, please read:
   http://www.nabble.com/How-to-reply-to-emails-tf3182877.html#a8833555

With separate create/render phases, finding all components that *might* 
output data into the head is not difficult; they could simply register 
themselves on create, or a tree-walk could be done as you describe.

The problem is that at the time the head component is rendered it is not 
obvious which of the components that *might* output data into the head 
are actually rendered.

The rendered state of a component depends upon the rendered state of all 
its parent components, so the rendered property of many components in 
the page would need to be evaluated. And in some cases evaluating a 
rendered EL expression can have side-effects; yes it is poor style to do 
so but it's not uncommon.

Cheers,

Simon

noah wrote:
> Why couldn't all the components that need resources implement some
> interface and then have the h:head component walk the component tree
> looking for components implementing the interface?
> 
> On 3/22/07, Simon Kitching <si...@rhe.co.nz> wrote:
>> Mike Kienenberger wrote:
>> > Roger blogged,
>> >> With separate build and render phases, you could have a <h:head>
>> >> component which
>> >> other components could add resources to as they are created during the
>> >> tree build.
>> >
>> > Hmm.   I wonder if we could implement this for facelets/branch 1.2.
>>
>> Probably not.
>>
>> The point is that components don't know at the time they are *created*
>> whether they want to insert stuff into the head or not; they only know
>> that at *render* time. And by then the head tag has already rendered
>> itself. Well, unless we allow every component in the page to output its
>> required resources regardless of whether it is later rendered or not.
>>
>> A head tag could be useful though; currently the ReducedHTMLParser is
>> needed to parse the page and find the <head> tag. It's not simply a
>> matter of looking for that string due to things like
>>    <!-- the <head> is not here -->
>>    <script>
>>      var s = "<head>";
>>    </script>
>> etc. However a head tag could output a unique marker like
>>    <!--HEAD12345567890-->
>> which could more easily be scanned for by the ExtensionsFilter. This
>> marker approach is already used for figuring out where to insert
>> serialized client state etc.
>>
>>
>> Items 1,2 and 3 of the blog are all issues that could be pretty easily
>> fixed in the ExtensionsFilter. Not that I'm claiming it's a great
>> solution, but a fixed ExtensionsFilter would be better than hand-coding
>> resources in the head section.
>>
>> Cheers,
>>
>> Simon
>>


Re: A simple alternative to the ExtensionFilter

Posted by noah <ia...@gmail.com>.
Why couldn't all the components that need resources implement some
interface and then have the h:head component walk the component tree
looking for components implementing the interface?

On 3/22/07, Simon Kitching <si...@rhe.co.nz> wrote:
> Mike Kienenberger wrote:
> > Roger blogged,
> >> With separate build and render phases, you could have a <h:head>
> >> component which
> >> other components could add resources to as they are created during the
> >> tree build.
> >
> > Hmm.   I wonder if we could implement this for facelets/branch 1.2.
>
> Probably not.
>
> The point is that components don't know at the time they are *created*
> whether they want to insert stuff into the head or not; they only know
> that at *render* time. And by then the head tag has already rendered
> itself. Well, unless we allow every component in the page to output its
> required resources regardless of whether it is later rendered or not.
>
> A head tag could be useful though; currently the ReducedHTMLParser is
> needed to parse the page and find the <head> tag. It's not simply a
> matter of looking for that string due to things like
>    <!-- the <head> is not here -->
>    <script>
>      var s = "<head>";
>    </script>
> etc. However a head tag could output a unique marker like
>    <!--HEAD12345567890-->
> which could more easily be scanned for by the ExtensionsFilter. This
> marker approach is already used for figuring out where to insert
> serialized client state etc.
>
>
> Items 1,2 and 3 of the blog are all issues that could be pretty easily
> fixed in the ExtensionsFilter. Not that I'm claiming it's a great
> solution, but a fixed ExtensionsFilter would be better than hand-coding
> resources in the head section.
>
> Cheers,
>
> Simon
>

Re: A simple alternative to the ExtensionFilter

Posted by Simon Kitching <si...@rhe.co.nz>.
Mike Kienenberger wrote:
> Roger blogged,
>> With separate build and render phases, you could have a <h:head> 
>> component which
>> other components could add resources to as they are created during the 
>> tree build.
> 
> Hmm.   I wonder if we could implement this for facelets/branch 1.2.

Probably not.

The point is that components don't know at the time they are *created* 
whether they want to insert stuff into the head or not; they only know 
that at *render* time. And by then the head tag has already rendered 
itself. Well, unless we allow every component in the page to output its 
required resources regardless of whether it is later rendered or not.

A head tag could be useful though; currently the ReducedHTMLParser is 
needed to parse the page and find the <head> tag. It's not simply a 
matter of looking for that string due to things like
   <!-- the <head> is not here -->
   <script>
     var s = "<head>";
   </script>
etc. However a head tag could output a unique marker like
   <!--HEAD12345567890-->
which could more easily be scanned for by the ExtensionsFilter. This 
marker approach is already used for figuring out where to insert 
serialized client state etc.


Items 1,2 and 3 of the blog are all issues that could be pretty easily 
fixed in the ExtensionsFilter. Not that I'm claiming it's a great 
solution, but a fixed ExtensionsFilter would be better than hand-coding 
resources in the head section.

Cheers,

Simon

Re: A simple alternative to the ExtensionFilter

Posted by Mike Kienenberger <mk...@gmail.com>.
Roger blogged,
> With separate build and render phases, you could have a <h:head> component which
> other components could add resources to as they are created during the tree build.

Hmm.   I wonder if we could implement this for facelets/branch 1.2.

On 3/22/07, Roger Keays <ro...@ninthavenue.com.au> wrote:
> Hi guys,
>
> For those people who've had problems with the MyFaces ExtensionFilter,
> I've blogged about a simple alternative that you might find useful:
>
> http://www.ninthavenue.com.au/blog/myfaces_filter
>
> It's not exactly rocket science - basically just hand coding the
> resources in your <head> section.
>
> Roger
>
> --
> ----------------------------------------
> Ninth Avenue Software
> p: +61 7 3137 1351 (UTC +10)
> f: +61 7 3102 9141
> w: http://www.ninthavenue.com.au
> e: info@ninthavenue.com.au
> ----------------------------------------
>
>