Performance tuning of Seam, JSF, Richfaces for webapps

Apart from following best practices while coding an application, we often come across the need to tune it up just a bit further to get that peek performance going.
On a recent project we faced some challenges in trying to increase the performance of our web application. We finally ended up optimizing the app and got very promising results. Here I put together some of the information used by us in one location, which is scattered over the web.

The frameworks used were, Seam 2.2 and JSF 1.2 with Richfaces 3.2 and also Spring 2.5. Now without further delay here you go..

Some pointers on using JSF beans mapped in your view layer (JSP/XHTML when using facelets).

  1. Don’t put code in a getter (accessor method) of a managed bean
    The getters are invoked frequently to get the data. You could use some other method to fetch data and simply update the property.
    But if you did end up with few getters which hit the database for data loading, then consider putting a condition around that code to load data only if required.
    Example: Change code like the below;

    private List aList;
    public List getList() {
    aList = getServiceObject().loadListFromDB();
    return aList;
    }
    

    To load data conditionally as given below;

    private List aList;
    public List getList() {
    if( null == aList || aList.isEmpty() ) {
    //Load from DB only if list is empty
    aList = getServiceObject().loadListFromDB();
    }
    return aList;
    }
    
  2. Check scope of your beans. Seam provides a Conversation Scope use it instead of Session Scope if practical enough for your requirement.
  3. Richfaces does provide a huge set of components which are Ajax based.
    But many of those components also add to the processing overhead. Use them judiciously or it can affect your page load time pretty badly.
    Consider these points when trying to optimize a JSF/Richfaces application.

    • Avoid using rich:dataGrid or rich:dataTable whenever you can. The h:dataTable of JSF usually provides good enough options.
    • Do not use rich:tooltip inside a data table or grid. It’s very expensive and can lead to very slow rendering especially on IE.
      Also avoid nesting too many rich:xxx components inside a dataTable.
    • Use ajaxSingle=true attribute and a4j:region tag whenever possible. Also consider using limitToList attribute when reRendering.
    • Do not use multiple rich:modalPanel components for each view consider using one single rich:modalPanel with dynamic view.You could use a4j:include or ui:include (facelets) to change the view inside a modal panel.

Apart from following the above practices here are some goodies which will speed up your JSF with Richfaces webapp.
Add the below snippets to your web.xml

  • Use a global queue. (This is not strictly required if you are already using queuing of ajax requests)
    <context-param>
    <param-name>
     org.richfaces.queue.global.enabled
    </param-name>
    <param-value>true</param-value>
    </context-param>
    
  • Use NEKO parser instead of the default. This will speed up things.
    <context-param>
     <param-name>
      org.ajax4jsf.xmlparser.ORDER
     </param-name>
     <param-value>
      NONE,NEKO,TIDY
     </param-value>
    </context-param>
    
    <context-param>
    <param-name>org.ajax4jsf.xmlparser.NEKO</param-name>
    <param-value>.*\..*</param-value>
    </context-param>
    
  • Change the way css and java script files are loaded.
    If you view the source of your page you will notice that by default richfaces will add some includes of css and scripts which lead to multiple calls to load.
    For example with our web app we had like 8 css files and 23 js scripts getting loaded separately.
    and with the below setting our pages had just 1 css include and 2 script includes.

    <context-param>
    <param-name>
    org.richfaces.LoadStyleStrategy
    </param-name>
    <param-value>ALL</param-value>
    </context-param>
    
    <context-param>
    <param-name>
    org.richfaces.LoadScriptStrategy
    </param-name>
    <param-value>ALL</param-value>
    </context-param>
    
    <!--  If you use LoadScriptStrategy ALL, turn the compression off  -->
    <context-param>
    <param-name>
    org.ajax4jsf.COMPRESS_SCRIPT
    </param-name>
    <param-value>false</param-value>
    </context-param>
    

    Using the above settings we had reduced the css and js files to be loaded:

    <link rel='stylesheet' class='component' type='text/css'
            href='/excel/a4j_3_2_1-SNAPSHOTorg/richfaces/skin-ext-classes.xcss/DATB/eAELXT5DOhSIAQ.sA18_'
    />
    <script type='text/javascript'
            src='/excel/a4j_3_2_1-SNAPSHOT/org/ajax4jsf/framework.pack.js'></script>
    <script type='text/javascript'
            src='/excel/a4j_3_2_1-SNAPSHOT/org/richfaces/ui.pack.js'></script>
    
  • For Facelets and JSF RI from Sun you can use the below settings:
    <!--  Facelets tuning -->
    <context-param>
    <param-name>
    facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE
    </param-name>
    <param-value>false</param-value>
    </context-param>
    
    <context-param>
    <param-name>
    facelets.BUILD_BEFORE_RESTORE
    </param-name>
    <param-value>false</param-value>
    </context-param>
    
    <context-param>
    <param-name>facelets.DEVELOPMENT</param-name>
    <param-value>false</param-value>
    </context-param>
    
    <context-param>
    <param-name>facelets.REFRESH_PERIOD</param-name>
    <param-value>-1</param-value>
    </context-param>
    
    <!--  JSF RI Performance tuning -->
    <context-param>
    <param-name>com.sun.faces.responseBufferSize</param-name>
    <param-value>500000</param-value>
    </context-param>
    
    <context-param>
    <param-name>com.sun.faces.verifyObjects</param-name>
    <param-value>false</param-value>
    </context-param>
    
    <!-- Allows the JavaScript to be cached -->
    <context-param>
    <param-name>
    com.sun.faces.externalizeJavaScript
    </param-name>
    <param-value>true</param-value>
    </context-param>
    

    Only if you are running under JBoss AS

    <context-param>
    <param-name>
    com.sun.faces.serializationProvider
    </param-name>
    <param-value>
    org.jboss.web.jsf.integration.serialization.JBossSerializationProvider
    </param-value>
    </context-param>
    

When tuning your seam application you can use the components.xml file to tweak some settings.

  • Cache images and style globally.
    <web:cache-control-filter name="imageCacheControlFilter"
    regex-url-pattern=".*(\.gif|\.png|\.jpg|\.jpeg)"
    value="max-age=86400"/>
    
    <web:cache-control-filter name="textCacheControlFilter"
    regex-url-pattern=".*(\.css|\.js)"
    value="max-age=1400"/>
    
  • Also if you are using richfaces with Seam you could configure the richfaces filter  in components.xml itself
    without needing to declare the filter in web.xml
    Disable the forceparser and turn on caching.

    <web:ajax4jsf-filter force-parser="false"
    enable-cache="true"
    url-pattern="*.jsf"/>
    

So in the end after optimizing the webapp by using framework provided settings, you can expect a lot better performance from your app. In the end you get happy visitors. Hope this bit of information helps you guys.

Advertisements
Post a comment or leave a trackback: Trackback URL.

Comments

  • Carl  On September 1, 2010 at 5:18 pm

    Hello,

    thanks for sharing! It helped me a lot!

    Regards,

    Carl

  • Sam Allan  On September 21, 2010 at 1:51 pm

    Thanks. It helps a lot!!

  • Fourat  On October 3, 2010 at 6:58 am

    What if am not using richfaces at all ? i only use a4j, how can i disable the css files from richfaces ?

    • javaspecialist  On October 3, 2010 at 8:46 pm

      @Fourat
      At present the Ajax4jsf and RichFaces are combined under the name RichFaces (Since JBoss and Exadel decided to combine them)
      If you are using only Ajax4jsf library and do not include any rich components (<rich:XXXX ) in your pages,
      then you could disable the integrated style sheet (css) by using the below setting in web.xml:

       
      <context-param>
           <param-name>org.richfaces.LoadStyleStrategy</param-name>
           <param-value>NONE</param-value>
      </context-param>
      

      As per RichFaces documentation
      “Possible values are: ALL, DEFAULT, NONE. For more information see “Scripts and Styles Load Strategy”.”

    • Nick  On November 27, 2010 at 1:19 am

      @Fourat,

      Also you can set org.richfaces.CONTROL_SKINNING_CLASSES=disable in web.xml

  • Javier  On October 7, 2010 at 12:27 pm

    Hi, this article is really interesting but i have a doubt, why you use this:

    facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE

    false

    facelets.BUILD_BEFORE_RESTORE

    false

    facelets.DEVELOPMENT
    false

    facelets.REFRESH_PERIOD
    1

    Thanks in advance!

    • javaspecialist  On October 9, 2010 at 10:39 am

      @Javier
      Although some of these params are false by default, I have explicitly stated them for clarity.

      facelets.REFRESH_PERIOD/-1 (Corrected my post it should be -1 not 1)
      This will disable reloading of the templates, since we don’t want this check to happen in production.

      facelets.DEVELOPMENT/false
      Facelets library running in development mode stores additional info about components and beans.
      It is advisable to disable this in production.

      facelets.BUILD_BEFORE_RESTORE/false
      Setting it to true, Facelets can build view before request processing instead of state saving. But this will cause some other issues.

      facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE/false
      In JSF 1.2 with Facelets, you can reduce the memory overhead by not saving the ValueExpressions.
      But for this you also need to set the BUILD_BEFORE_RESTORE to true, which can cause unpredictable behaviour for the components.
      Hence I have explicitly turned both BUILD_BE… and RECREATE… to false.
      Hope this clarifies your query.

  • Rômulo  On October 22, 2010 at 4:30 pm

    Thanks a lot for this post, but I still have a doubt:

    “But for this you also need to set the BUILD_BEFORE_RESTORE to true, which can cause unpredictable behaviour for the components.”

    So… do you know how can I use this parameter with RichFaces without problems?

    Thanks in advance!

    • javaspecialist  On October 23, 2010 at 7:35 pm

      This param from facelets is notorious for breaking some of the Ajax components.
      Seen with Richfaces Ajax4jsf. There isn’t any documented work around for this.

      But the idea behind using buildBeforeRestore is to restore the view even if the
      associated session has expired and thereby avoiding the ViewExpiredException.
      Alternatively you could use the following seam configuration in pages.xml
      to gracefully handle ViewExpiredException.

      <exception class="javax.faces.application.ViewExpiredException">
        <redirect view-id="/home.xhtml">
      	<message severity="warn">Your session expired. Please try again.</message>	
      </redirect>
      </exception>
      
  • Rômulo  On October 22, 2010 at 7:02 pm

    In response to this:

    “But for this you also need to set the BUILD_BEFORE_RESTORE to true, which can cause unpredictable behaviour for the components.”

    I created a new ViewHandler, base on FaceletViewHandler, that overrides the “createView” method adding this code:

    UIViewRoot viewRoot = this.parent.restoreView(context, viewId);
    		
    if (viewRoot == null) {
    	viewRoot = super.createView(context, viewId);
    }
    return viewRoot;
    
    • Juan  On February 11, 2012 at 9:02 pm

      Romulo,
      Does this work for richfaces without causing issues? It could be very important because memory saving it’s important when turning on facelets.BUILD_BEFORE_RESTORE and facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE.

  • Hari  On June 6, 2012 at 4:06 pm

    Hi,
    You have mentioned that try to avoid rich:tooltip in datatable, is there any alternate component because in my project we have to use tool tip inside a data table.

    Thanks,
    Hari

    • javaspecialist  On June 30, 2012 at 10:13 am

      @Hari, if you are still looking for an answer :),

      The performance issues with tooltips seemed to be addressed in the 3.3.3 Final release.
      https://issues.jboss.org/browse/RF-8425?_sscc=t

      But tooltips on mouse over should really be done away with, especially considering the outburst of tablets.
      Sites should take into consideration design practices that help tablet browsing too.

  • Mark  On June 30, 2012 at 12:24 am

    Hi Prashant,
    Great post! I have a question on the ajax4jsf-filter’s force-parser attribute, though: When setting it to “false,” I’m still seeing the A4J renderkit invoked during profiling, even for non-AJAX requests. My understanding is that setting force-parser to “false” is supposed to prevent it from getting involved in those requests types.

    Have you encountered a similar problem? Am I even understanding it correctly? 🙂

    Thanks,
    Mark

  • Eskimoquinn  On October 23, 2012 at 8:44 am

    Can you explain more why developers should not use rich:datatable? Is there something inherently wrong with this component?

  • Sundararajan Mani  On June 4, 2013 at 12:14 pm

    Thanks for this nice tips. Currently we are using jboss-seam-2.0.1.GA, can you suggest which version of seam having good performance?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: