Ajax ReRendering – How to reRender part of your page in Myfaces using Richfaces

If you read this post I assume you have a general knowledge about what Ajax is, and what capabilities lies within. As a web-developer, there might be times where you would like to not do a full submit of your page, but you would actually like to just update a small part of the page. An application that achieves this gives the user a more “desktop-application”-like experience, and it will mostly also be a saver when it comes to performance, as you only load a part of the page – as well as the data going to be displayed in it.

For Myfaces, both 1.1 and 1.2 specification, there is a component library named RichFaces. The components there are nice to use for adding ajax-features to your application, and there are also possibilities of adding those capabilities to non-ajax components in myFaces or Tomahawk libraries.

You can download the libraries from here: RichFaces. Depending on the version of Myfaces you use, you need to get different RichFaces version. For MyFaces 1.1 core you need the RichFaces 3.1.X libraries, for Myfaces 1.2 core you can get the 3.2.X libaries. The 3.2.X libraries does NOT support Myfaces version 1.1

Then, to make use of the new library you need to add the following to your web.xml:

    <filter>
        <display-name>RichFaces Filter</display-name>
        <filter-name>richfaces</filter-name>
        <filter-class>org.ajax4jsf.Filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>richfaces</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>

On the top of your jsps you need to include the taglibraries by inserting these lines:
<%@ taglib uri=”http://richfaces.org/rich&#8221; prefix=”rich”%>
<%@ taglib uri=”https://ajax4jsf.dev.java.net/ajax&#8221; prefix=”a4j”%>

So, when it comes to the actual reRendering of components or part of your page, there are several different ways of doing this.

In its simplest form, you can use the a4j:support to add ajax capabilities to ordinary myfaces components. In this example we use it on an inputText. You set the event property (javascript events), give the id of the component(s) you want to reRender, and then you go. Everytime a user releases a key, the reRender will be called, and getting the outText component again:

<h:inputText id="myInput" value="#{myBean.myProperty}">
    <a4j:support event="onkeyup" reRender="outText"></a4j:support>
</h:inputText>

<h:outputText id="outText" value="#{myBean.myProperty}"></h:outputText>

If you use componentBindings, and create those components programmatically, you need to do your custom modification of that component in the setter-method of this component to let the reRendering work. Let’s say you have a panelGrid, and you create it java-side and add two outPutTexts to it. If the value of those outputTexts change, and you want to reRender the panelGrid to display this, then the setter of this component is invoked as long as the getter returns null. So you should do like this:

Jsp:

<h:inputText id="myInput" value="#{myBean.myProperty}">
    <a4j:support event="onkeyup" reRender="outPanel"></a4j:support>
</h:inputText>

<t:panelGrid id="outPanel" binding="#{myBean.htmlPanelGrid}"/>

Java:

public HtmlPanelGrid getHtmlPanelGrid()
{
    return htmlPanelGrid;
}

public void setHtmlPanelGrid(HtmlPanelGrid htmlPanelGrid)
{
    //Clean exisiting children
    htmlPanelGrid.getChildren().clear();

    //Add your modifications
    htmlPanelGrid.getChildren().add(createOutputText("out1","#{myBean.myProperty1}"));
    htmlPanelGrid.getChildren().add(createOutputText("out2","#{myBean.myProperty2}"));

    this.htmlPanelGrid = htmlPanelGrid;
}

private UIComponent createOutputText(String id, String valueBinding)
{
    HtmlOutputText out = new HtmlOutputText();
    out.setId(id);
    ValueBinding vb = FacesContext.getCurrentInstance().getApplication().createValueBinding(
    valueBinding);
    out.setValueBinding("value", vb);

    return out;
}

It is also possible to create the a4j:support programmatically, like this:

HtmlAjaxSupport ajaxSupport = new HtmlAjaxSupport();
ajaxSupport.setEvent("onchange");
ajaxSupport.setId("ajaxSupport");
ajaxSupport.setFocus("myForm:theIdOfComponentIWantToFocusOnAfterAjaxSubmit");
ajaxSupport.setReRender("myForm:idOFComponentIWantToReRender"); 

myUiComponent.getChildren().add(ajaxSupport);

There is also a component that creates a javascript-function for you which you can use to pass properties to your bean, execute actions and finally reRender components. It’s called a4j:jsFunction. Let’s say I have a h:commandButton, and when I click it I want to set a value to a property in my bean, I want to run an action, and then display the results. I could have done this with an t:updateActionListener, but then I would have been forced to do a full submit of the whole page. Instead, I can do it like this:


    //Define javascriptFunction with parameter
    <a4j:form>
        <a4j:jsFunction name="setParameterAndRerender" action="#{myBean.action}" reRender="outPanel" >
             <a4j:actionparam name="param1" assignTo="#{myBean.myProperty1}"  />
         </a4j:jsFunction>
    </a4j:form>

    <t:panelGrid id="outPanel" binding="#{myBean.htmlPanelGrid}"/>

    <h:commandButton value="Click me" onclick="setParameterAndRerender('MyValue');return false;"></h:commandButton>

Notice that I set return false in the onclick of the commandButton to avoid it from submitting. I’ll let ajax handle that.

If you create the a4j:support-object progammatically, I’ve experienced that it doesn’t always find the id of the component you have specified to reRender. To solve this, you can use a combination of this one and the javascript function just described:

HtmlAjaxSupport ajaxSupport = new HtmlAjaxSupport();
ajaxSupport.setEvent("onchange");
ajaxSupport.setId("ajaxSupport");
ajaxSupport.setFocus("myForm:theIdOfComponentIWantToFocusOnAfterAjaxSubmit");

//We don't specify reRender id here, but set a javascript function to run when completed
//ajaxSupport.setReRender("myForm:idOFComponentIWantToReRender");
ajaxSupport.setOncomplete("setParameterAndRerender('MyValue');");

myUiComponent.getChildren().add(ajaxSupport);

So, what about the RichFaces library? In all components the ajax capabilities are included, you don’t have to use a4j:support. When using one of the components the submit will always be an ajax submit, so you can just specify which components to reRender. As a short example, instead of using a h:commandButton you can use a4j:commandButton, like this:

    <a4j:commandButton value="Click me" action="#{myBean.action}"  reRender="outPanel"/>
    <t:panelGrid id="outPanel" binding="#{myBean.htmlPanelGrid}"/>

Also, if you have a part of a page that always should be ajaxRendered, and you are tired of of writing Ids to reRender, simply wrap that part of the page inside an a4j:outputPanel and set the ajaxRendered property to true. In my a4j:commandButton, I don’t have to set the reRender property as this panel is now always reRendered by ajax submits:


    <a4j:commandButton value="Click me" action="#{myBean.action}" />

    <a4j:outputPanel ajaxRendered="true">
        <t:panelGrid id="outPanel" binding="#{myBean.htmlPanelGrid}"/>
    </a4j:outputPanel>

I hope this have given you a brief idea of what is possible to do with ajax/richFaces and also how to do it 🙂

I suggest you to check out the livedemo page to see all the different components that RichFaces give you: Live demo

Migration guide – go from Myfaces 1.1.X to Myfaces 1.2.3

If you are currently using Myfaces 1.1.X and want to start to use Myfaces core 1.2.3, there are certain steps you need to do and to be aware of to be able to make your existing 1.1.X-version application run. JSF 1.2 requires java 1.5 or later, JSP 2.1, JSTL 1.2 and a Java Servlet 2.5 implementation. If you use Jboss, this means that you have to go for jboss version 4.2.2 or higher (supports java5).

  1. First of all you need to download the new Myfaces-1.2 Core libraries, you can do it from here: Myfaces Project
  2. If you have been using Myfaces 1.1.X, you have probably also been using javax.servlet.jar and javax.servlet.jsp.jar. But the 1.2.3 version requires JSP 2.1, JSTL 1.2 and Java Servlet 2.5, so you need to update those libraries. The libraries you want to get are jsp-api-2.1.jar, jstl-1.2.jar and servlet-api-2.5.jar. You can get them from here: Jboss repository.
  3. The libraries are now in place. But you will find out that several classes and methods that existed in Myfaces-1.1.5 are now deprecated. For example, ValueBinding is now ValueExpression, and MethodBinding is MethodExpression. I will give you the different way in creating these programmatically, the way it is with 1.1.5, and the way it should be done in 1.2.3. Note that for ValueExpressions it is necessary to pass the “expected” class as parameter – meaning that if your ValueExpression would be used in the “value” property, the class would probably be java.lang.String. If it was to be used in a “rendered” property, the class should be java.lang.Boolean. If you don’t do this properly you would normally get a class cast exception, or at least some strange results: ValueBinding – 1.1.5
    ValueBinding vb = FacesContext.getCurrentInstance().getApplication().createValueBinding(
                        "#{myBean.myProperty}");
    myComponent.setValueBinding("value", vb);
    

    ValueExpression- 1.2.3

    FacesContext context = FacesContext.getCurrentInstance();
    ValueExpression vex = context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(), "#{myBean.myProperty}", String.class);
    myComponent.setValueExpression("value", vex);
    ValueExpression rex = context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(), "#{myBean.myProperty}", Boolean.class);
    myComponent.setValueExpression("rendered", rex);
    

    MethodBinding – 1.1.5

    MethodBinding methodBinding = FacesContext.getCurrentInstance().getApplication().createMethodBinding(
    			"#{myHandler.action}",null);
    myComponent.setAction( methodBinding );
    

    MethodExpression – 1.2.3

    FacesContext context = FacesContext.getCurrentInstance();
    MethodExpression methodEx = context.getApplication().getExpressionFactory().createMethodExpression(context.getELContext(),
    			"#{myHandler.action}", String.class, new Class[] {});
    myComponent.setActionExpression(methodEx );
    

    ActionListener – 1.1.5

    try
            {    Class[] parameterList = { Class.forName("javax.faces.event.ActionEvent") };
                MethodBinding actionListenerBinding = FacesContext.getCurrentInstance().getApplication().createMethodBinding(
                    "#{myHandler.myListener}",parameterList);
                myComponent.setActionListener(actionListenerBinding );
            }
            catch (Exception e)
           {
                log.error("error setting ActionListener");
            }
    

    ActionListener – 1.2.3

    FacesContext context = FacesContext.getCurrentInstance();
    ELContext elContext = context .getELContext();
    MethodExpression actionListenerExpression = context.getApplication().getExpressionFactory().createMethodExpression(
    elContext,"#{myHandler.myActionListenerMethod}",null,new Class[] {ActionEvent.class});
    
     MethodExpressionActionListener methodExpressionActionListener = new MethodExpressionActionListener(actionListenerExpression);
    
  4. Also rememeber that the tld respects the html 4 specification, so old attribiutes like align, alt, background and color are deprecated. You need to update these and set proper css instead.

Good luck!