Andrew, are you just stating what currently happens or are you saying that there is a *reason* for evaluating "rendered" in encodeBegin, encodeChildren and encodeEnd?

I can't initially see any reason why it would need to be evaluated more than once.

UIComponentBase does indeed call isRendered in encodeBegin, encodeChildren and encodeEnd. It also implements isRendered as an evaluation of the EL expression (myfaces 1.1.3 implementation).

But As Wesley asks, why would it ever make sense for rendered to be true in encodeBegin, but false in encodeEnd? I cannot see any way that would be useful, so why not just compute it once then cache it somewhere for the rest of that render cycle (eg in a "transient" member of the component)? This would be a significant performance boost..

Wesley, your proposed modification which stores the rendered state into _rendered is not good because setting _rendered will permanently override the rendered EL expression, not just for the current render cycle but for the lifetime of that component. What is needed is to figure out when the first call to isRendered is done *during the render cycle* and then cache that until rendering finishes. Note that isRendered is also called during postback processing, and it's perfectly reasonable to change this value between postback and render so caching really should only be done between encodeBegin() and encodeEnd(). So implementing this optimisation is a little tricky - but not impossible I'm sure.

Regards,

Simon

Andrew Robinson wrote:
At the very least rendered is called during encodeBegin,
encodeChildren, and encodeEnd.

On 5/8/07, Wesley Hales <[EMAIL PROTECTED]> wrote:
Hello - Why do we continually call isRendered after encodeBegin()? Once the begin tag is written out, it shouldn't matter what the body and end rendered
states are.

Facelets 1.1.11
 Myfaces 1.1.5 & 1.2

So if I have  <t:div rendered="#{MyBean.alerts > 0}"...
The #{MyBean.alerts method is called 5 times! and it is like this for every EL eval on the page. I do know that EL can only bind to the FaceletsContext
and no other scopes... So are there any other options than what I have
listed below?

1. Tried to modify MyFaces src in UIComponentBase:
public boolean isRendered()
     {
           if(_rendered == null){

           // our modification! Only compute the rendered value once, and
cache for the rest of the lifecycle.
           Boolean rend = getExpressionValue("rendered", _rendered,
DEFAULT_RENDERED);
           _rendered = rend.booleanValue();
           }
         return _rendered;
     }
This didn't work :( - Something happend to A4J and we had no ideas what the
implication would be on all components.

2. Tried using Facelets <ui:param and <c:set to store the EL in a page
scoped variable, then have the variable evaluated in the rendered attribute.
This didn't work either because it is on FacesContext.

So this may just be me not fully understanding  what JSF does behind the
scenes of component rendering, or some people say that the spec is screwed up when it comes to this. I'm sure some of the pros can help me out here :).

Thx,
Wesley Hales

Reply via email to