Srikanth Technologies

Ajax with JSF 2.0

One of the new features of JSF 2.0 is in-built support for Ajax using <f:ajax> tag. In this blog, I show how to use Ajax using JSF 2.0 to get phone number for the given name. The other new features of JSF 2.0 that I use in this example are - Facelet for view (and not JSP) and @ManagedBean annotation to declare managed bean. There are no entries in faces-config.xml as managed bean is created using annotation @ManagedBean without needing to have any entries in faces-config.xml as it is in JSF 1.2.

Facelet - phonesearch.xhtml

Facelet is an XHTML document that uses custom tags of JSF by registering URI for html and core tags using xmlns. Typically h is prefix for HTML tags and f is the prefix for core tags.


<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core" >
    <h:head>
        <title>Phone Directory Search</title>
    </h:head>
    <h:body>
         <h:form id="directoryForm">
            <h2>Phone Directory Search</h2>
            Enter person name : <h:inputText id="name" value="#{phoneDirectoryBean.name}" />
            <p/>
            <h:commandButton actionListener="#{phoneDirectoryBean.search}" value="Get Phone Number">
                <f:ajax execute="@form"  render="directoryForm:phone"/>
            </h:commandButton>
            <p/>
            <h3><h:outputText value="#{phoneDirectoryBean.phone}" id="phone"/> </h3>
        </h:form>
    </h:body>
</html>

The above Facelet takes name from user using inputText component and copies it into name property of phoneDirectoryBean, which is the name for PhoneDirectoryBean managed bean.

When user clicks on button (action event) then an Ajax request is made to server and search() method is executed in managed bean. We also specified using render attribute that only phone element is to be updated (partial rendering) by Ajax request.

Attribute render takes client id of the component, which is in the form - formid:componentid. If you have multiple components to be updated,
you can provide IDs of multiple components separated by a space.

Attribute execute specifies for which components all phases are to be executed on the server. As we have given @form, it processes all components. However, you can process selective components by giving the list of components separated by space.

Managed Bean - PhoneDirectoryBean

Now let us create managed bean called PhoneDirectoryBean. Annotation @ManagedBean specifies that it is a managed bean. There is no need to have any entry related to it in faces-config.xml as it is in JSF 1.2. We didn't specify scope of the bean as it defaults to request scope.

Scope of the bean can be specified using one of these annotations -  @NoneScoped, @RequestScoped, @ViewScoped, @SessionScoped, @ApplicationScoped, and @CustomScope, where ViewScope and CustomScope are new to JSF 2.0.


import java.util.TreeMap;
import javax.faces.bean.ManagedBean;
import javax.faces.event.ActionEvent;


@ManagedBean  // phoneDirectoryBean is taken as the default name.  Request is the default scope.
public class PhoneDirectoryBean {
    private TreeMap<String,String>  directory = new TreeMap<String,String>();

    private String name,phone;

    public PhoneDirectoryBean() {
         directory.put("Mickey", "9898989898");
         directory.put("Donald","9999999999");
         directory.put("Jerry", "9090909090");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }

    public void search(ActionEvent evt) {
         phone = directory.get(name);
         if ( phone == null) {
              phone = "Sorry! Name not found";
         }
    }
}

web.xml

The following entries in web.xml configure FacesServlet. It is invoked whenever any request with .xhtml is made.


<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>phonesearch.xhtml</welcome-file>
    </welcome-file-list>
</web-app>


Run phonesearch.xhtml from your browser and enter any of the names given in the directory and click on button to get phone number. If you enter a name that is not present in the directory then it places error message in phone property which is displayed in the client.