Insights into Java Server Faces

2013/01/14

Suppress second execution of buildView() as performane improvement when using Facelets views

Filed under: JSF — Hanspeter @ 21:58

Since JSF 2.0 when using Facelets view definitions the component tree is built twice on postback requests, once in RESTORE_VIEW phase and once in RENDER_RESPONSE phase. The rebuild in the render phase is necessary in case the page author used conditional includes. On big views several hundred component build the component tree – this may take some 100ms per buildView() execution – saving that once will improve the performance.With conditional includes or templates it is possible the include or template changes after RESTORE_VIEW and before RENDER_RESPONSE phase. Conditional include or conditional template is a result of using:

  • <c:if test=”…”> around a <ui:include src=”…”>
  • EL expression in the <ui:include src=”#{expression.to.source}”>
  • EL expression in <ui:composition template=”#{expression.to.template}”>

This gives us an optimization potential if we know we do not use such conditional includes or templates. In that case we can can use a ViewDeclarationLanguageWrapper and override the method <code>public void buildView(FacesContext context, UIViewRoot root)</code> to suppress conditionally in case of a postback request where buildView() was already executed in RESTORE_VIEW phase.

I created a little project on github – https://github.com/dueni/faces-ext/tree/master/suppress-rebuildview, it contains just a few classes and configuration to get this working.

  1. SuppressRebuildViewViewDeclarationLanguageWrapper – the wrapper to suppress buildView(…) call.
  2. SuppressRebuildViewViewDeclarationLanguageFactory – the factory to wrap ViewDeclarationLanguage
  3. META-INF/faces-config.xml to configure the view-declaration-language-factory
  4.  SuppressRebuildViewPhaseListener – mark views that may suppress the second buildView() execution using <f:phaseListener type=”com.csg.jsf.view.SuppressRebuildViewPhaseListener” /> tag on the page or a template used by the page.

Remains one thing to mention – this tweak will work with JSF 2.0 or later. In case you want to use this you might as well get the project from github and build the jar using maven.

Any comments or suggestions on this? Did this help you?

2 Comments »

  1. Could you please mesaure the performance gain with myfaces and mojarra? I can’t believe that the implementations are NOT optimized in that way.

    Comment by Thomas — 2013/05/01 @ 19:06

    • Hi Thomas,

      I only tested this with mojarra (JSF RI), but I’m pretty sure the same optimization would be possible in MyFaces because the requirement for the second buildView() execution is in the specification itself.

      I could imagine to optimize it in the specification, but that will take some time and effort to bring it in. I think on tracking all used ui:include and ui:component/ui:composition/ui:decorated template references and then also check if any ui:include is used inside a c:if – if no include and template sources are using EL expression and no ui:include is used inside a c:if block, the second buildView() in RENDER_RESPONSE phase on POST-back could be omitted automatically. But as you see that are quite some conditions to check.

      Best regards
      Hanspeter

      p.s. one addition: the potential performance gain depends on how complex the view is – for a view consisting of 20-50 components that performance gain might be irrelevant.

      Comment by Hanspeter — 2013/05/02 @ 15:23


RSS feed for comments on this post. TrackBack URI

Leave a comment

Create a free website or blog at WordPress.com.