[jbossseam-issues] [JBoss JIRA] Commented: (JBSEAM-3008) Page fragment caching impossible with coarse-grained rendered attribute evaluation in JSF

Sebastian Hennebrueder (JIRA) jira-events at lists.jboss.org
Wed Jul 30 12:33:26 EDT 2008


    [ https://jira.jboss.org/jira/browse/JBSEAM-3008?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12423081#action_12423081 ] 

Sebastian Hennebrueder commented on JBSEAM-3008:
------------------------------------------------

// copy of the post to the dev list

Hello,

far away from being a guru of anything but I looked through the code.

Related to thie JBSEAM-3008 and the posting on http://seamframework.org/Documentation/TuningTheSeamWebsite

I evaluted JSF reference implementation 1.2.04

A component extending from UIComponentBase has a number of JSF phase handler.
processRestoreState
processDecodes
processValidators
processUpdates
processSaveState

a get request is only calling processSaveState but a post request is calling everything

The implementations are more or less iterating through the childs and calling the child handlers

Three methods (
processDecodes
processValidators
processUpdates
) are calling isRendered which in turn leads to an EL resolution.

In totally isRendered is called at least 5 times before an element is rendered. Calls are not cached and the EL is evaluated every time.
Calling methods are encodeChild,encodeBegin/encodeEnd/encodeChildren and a super class + 3 if the request is a post and the component extends UIComponentBase

There are two consequences: one for a proper cache implementation and one for performance

1) cache
To have a proper cache implementation our cache component needs to overwrite at least phase listener
processDecodes
processValidators
processUpdates
with an empty implementation. This will block all following updates as JSF is always running through the object tree. As a consequence the cached fragment should not be a form. The content will not be updated, even if it is not yet cached. processSaveState and processRestoreState should not be overwritten. It might be slightly inefficient but these methods fill the component tree we need to cache.

Actually, I wanted to create a patch but where is the source for HtmlCache. It seams not to be in seam-trunk. Anyway, just overwrite the three methods and don't delegate to the parent class but leave it empty.


2) performance
This is not related to the cache but a general JSF problem.
In the class org.jboss.seam.ui.util.cdk.RendererBase add two lines to evaluate the rendered expression
and call setRendered and set the result of the evaluation. This will reduce the calls for all components using this renderer to one call.

It would reduce the rendered EL calls by 80 % . The question is, if we will see any side effects.  If no components are doing funny things, it should work. I would propose that we carefully test this in different applications.

public void renderChildren(FacesContext facesContext, UIComponent component) throws IOException {
   if (component.getChildCount() > 0) {
     for (Iterator it = component.getChildren().iterator(); it.hasNext();) {
       UIComponent child = (UIComponent) it.next();
// here the two lines
       boolean rendered = child.isRendered();
       child.setRendered(rendered);
       renderChild(facesContext, child);
     }
   }


Best Regards

Sebastian Hennebrueder
----
www.laliluna.de
Training, Tutorials and Java Development



> Page fragment caching impossible with coarse-grained rendered attribute evaluation in JSF
> -----------------------------------------------------------------------------------------
>
>                 Key: JBSEAM-3008
>                 URL: https://jira.jboss.org/jira/browse/JBSEAM-3008
>             Project: Seam
>          Issue Type: Task
>          Components: JSF Controls, JSF Integration
>            Reporter: Christian Bauer
>
> The evaluation of the JSF rendered="true|false" attribute conflicts with the Seam page fragment cache.
>  <s:cache region="test" key="foo123">
>     <h:outputText value="FOO" rendered="#{foo.bar}"/>
> </s:cache>
> The rendered attribute of the child components is ALWAYS evaluated, in potentially any JSF phase (especially APPLY REQUEST VALUES and RENDER RESPONSE of course).  No switch or combination of JSF component settings and renderers is able to stop that evaluation; you can not say "Do not call isRendered() on any child component of <s:cache>". 
> So any rendered-attribute expression that is costly (e.g. rendered="#{not empty myBackingBean.resultList}") will not be cached. This also means that there is a disconnect between what is finally rendered by s:cache (some HTML from the cache) and what the evaluation of the rendered attribute might produce. This is extremely difficult to work around. One approach is to only use lightweight rendered="#{foo}" expressions that can be evaluated many times without much cost.
> I don't see any way to fix this unless the JSF specification is changed and a more sane model of rendering/non-rendering switches is introduced. The rendered attribute is used for all kinds of purposes inside the JSF engine, most of them have nothing to do with rendering (e.g. it is used in APPLY REQUEST VALUES to detect which bindings need to be evaluated back onto the model).

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the seam-issues mailing list