myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Leonardo Uribe (JIRA)" <>
Subject [jira] [Commented] (MYFACES-3711) Add alwaysRecompile mode for EL Expression Cache Mode
Date Sat, 20 Apr 2013 15:37:15 GMT


Leonardo Uribe commented on MYFACES-3711:

If no objections, I'll commit the proposed code soon (in 2.1.x and 2.2.x branches)
> Add alwaysRecompile mode for EL Expression Cache Mode
> -----------------------------------------------------
>                 Key: MYFACES-3711
>                 URL:
>             Project: MyFaces Core
>          Issue Type: New Feature
>          Components: JSR-314
>            Reporter: Leonardo Uribe
>            Assignee: Leonardo Uribe
>         Attachments: MYFACES-3711-1-alwaysRecompile.patch
> In MYFACES-3160, EL Expression Cache Mode was introduced but soon it was seen a
> problem found on MYFACES-3169 (ui:param and c:set implementations does not 
> work as expected).
> There are two problems that limit the scope where EL Expression Cache can 
> be used:
> 1. Facelets user tags cannot cache EL Expressions.
> 2. Inclusions using ui:param must always contains the same number of 
> parameters.
> To understand the reasons it is worth to remember this example:
> a.xhtml
> <ui:composition template="c.xhtml">
>     <ui:param name="var1" value="value1"/>
> </ui:composition>
> b.xhtml
> <ui:composition template="c.xhtml">
>     <ui:param name="var1" value="value1"/>
>     <ui:param name="var2" value="value2"/>
> </ui:composition>
> c.xhtml
> <ui:composition>
>    <h:outputText value="#{var1}/>
>    <h:outputText value="#{var2}/>
> </ui:composition>
> When facelet c.xhtml is constructed from a.xhtml, "var2" is not recognized as
> a parameter so all EL expressions inside c.xhtml holding refereces to "var2"
> will be cached. Later, facelet c.xhtml is reused from b.xhtml but since 
> some EL expressions are cached the passed value in "var2" is not taken into 
> account and the error arise.
> In this point it is good to remember that ui:include or ui:decorate or user 
> tags are build view time tags, so they are executed only when the view is
> built. Parameters or attributes passed by ui:param or as user tag attributes
> follows the same principle, they are calculated on build view time through
> VariableMapper and the evaluation is stored inside the EL Expression. This
> means all EL Expressions holding references to these variables cannot be
> cached and needs to be generated each time the view is built.
> There is no way to know beforehand which references are affected, because
> in a template or an user tag there is no declaration of the parameters or
> attributes. But from user point of view that's good, because in this context
> a declaration of the parameters is just not necessary.
> The problem is ui:param and user tags are very useful features, widely used.
> A solution to this problem will improve performance in those cases.
> I have been thinking for a long time how to solve this, trying different 
> strategies. Use some kind of concurrency algorithm inside TagAttributeImpl
> does not work because it is too expensive, or use a central storage for 
> cache the expressions by the cost involved in the comparisons.
> The objective of cache EL expressions inside facelets abstract syntax tree 
> (AST) is minimize the calculations required to get a valid expression. EL
> implementations has already an internal map that cache that information,
> but that code usually has synchronized blocks or similar things. In that
> sense, the idea is rely on that storage in those EL expressions where 
> there is no choice and they need to be recreated.
> After doing many experiments in this part, I came up with a solution, which
> involves the following points:
> 1. Associate to a facelet, the parameters that were considered as passed 
> through ui:param or as a user tag attribute. If in some point of time
> we know for example c.xhtml uses var1, just consider it as c.xhtml(var1).
> 2. Use DefaultVariableMapper to track the parameters that are passed through
> ui:param or as a user tag attribute. When the EL expression is created, if
> it uses at least one parameter, mark the expression as not cacheable.
> 3. Override FaceletCache implementation and force a recompilation of a 
> facelet if a new parameter is detected that was not considered the first 
> time the template was created.
> 4. A facelet stored in the cache can be used if and only if all the 
> parameters used for the template where considered when it was compiled at
> first time.
> In the example proposed, when facelet c.xhtml is constructed from a.xhtml,
> we say that c.xhtml was built with var1 as a known parameter, or 
> c.xhtml(var1). when we try to reuse facelet c.xhtml from b.xhtml, we discover
> that var2 is also a parameter, but since the cached facelet is c.xhtml(var1),
> the algorithm discard the facelet and create a new one, but taking into
> account var2 too, so the new facelet becomes c.xhtml(var1,var2). If there
> is a call to c.xhtml with no params, it is considered that c.xhtml(var1,var2)
> can be used in that case.
> The final effect is just some extra compilations of the same facelet at
> startup but in the medium/long term, the information we need is calculated 
> and associated with the facelet url. Nice!. Facelet is very fast doing those
> extra compilation steps, and the final effect over performance really pays 
> off. We could even set this mode as default.
> The only disadvantage of this strategy is the current contract of FaceletCache
> is insuficient. As it has been described in MYFACES-3705, there are 
> implementation details inside MyFaces Core and in our facelets implementation,
> that needs to be exposed in a proper way. We need to create a custom
> AbstractFaceletCache and specify how to implement it.

This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see:

View raw message