PrimeFaces Beginner's Guide

By K. Siva Prasad Reddy
    Advance your knowledge in tech with a Packt subscription

  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Introduction to PrimeFaces

About this book

PrimeFaces is a lightweight UI component framework for JSF based applications. PrimeFaces is very easy to use because it comes as a single JAR file and requires no mandatory XML configuration. It provides more than 100 UI Components and an in-built AJAX support. It also provides theme support for UI components with more than 30 themes out-of-the-box. With PrimeFaces, developers can create rich user interfaces very easily.

PrimeFaces Beginners Guide is a practical, hands-on guide that provides you with clear step-by-step exercises,that will help you to learn and explore the features of PrimeFaces.

PrimeFaces Beginners Guide starts by showing you how to install PrimeFaces, create sample forms, and perform validations and then looks at various commonly used PrimeFaces utility components. Next, you will look into various basic text input components like form controls, Calendar, AutoComplete, and Rich Text Editor. Then you will learn about advanced UI components such as DataTables, panels, menus,and charts. Throughout the chapters we will be building a sample web application using PrimeFaces progressively that will give you a hands-on experience on using PrimeFaces effectively.

You will learn how to create complex layouts using accordion panels, tab views, sophisticated menu navigations, breadcrumbs and much more. You will also learn how to display data using DataTable with pagination, filters, and lazy loading, and how to export data to Excel or PDF features. You will learn how to represent data in various formats like trees, charts, and TagCloud. You will also learn how to build an application supporting multiple themes.

With this PrimeFaces Beginner’s Guide , you will learn how to use PrimeFaces easily and effectively.

Publication date:
November 2013
Publisher
Packt
Pages
378
ISBN
9781783280698

 

Chapter 1. Introduction to PrimeFaces

Java Server Faces (JSF) is a component-oriented framework for building web application using Java. JSF makes it easy to build web application by automating common tasks such as populating input parameter values into Java Beans by parsing input parameters, performing validations, and rendering or updating views. But building web application with rich User Interfaces (UI) still remains a challenge as Java developers may or may not be good at building fancy UI components using HTML, JavaScript directly. As JSF is a component-based framework, it allows building custom UI components with rich look and feel and can be reusable in any project.

The good news is that there are many open source and proprietary frameworks providing readymade reusable UI components, which can be used in any JSF-based applications. Among the several UI component libraries available today, PrimeFaces is an outstanding UI component library in terms of features and ease of use.

In this chapter, we will cover:

  • Introducing the features of PrimeFaces

  • Installing and configuring PrimeFaces

  • Creating a HelloWorld application using PrimeFaces

  • Creating simple forms using PrimeFaces

  • Performing form validations

  • Performing client-side validations

  • Understanding partial page rendering (PPR)

  • Updating view using AJAX

  • Updating view using AJAX listeners

  • Performing tasks periodically using the poll component

  • Invoking server-side methods from JavaScript using RemoteCommand

In this chapter, we will see what features make PrimeFaces an outstanding library, how to install and configure PrimeFaces and start using some of its basic components.

PrimeFaces is an open source JSF component library with 100+ rich UI components support. It has built-in AJAX support based on standard JSF 2.0 AJAX APIs.

 

Introducing the features of PrimeFaces


PrimeFaces provides the following set of features, which makes it powerful UI component library yet easy to use:

  • More than 100 rich UI components

  • Built-in AJAX support

  • Zero configurations

  • Does not require any third-party library dependencies for most of the components

  • Integrated with ThemeRoller

  • 30+ readily available themes

  • Supports IE8+, Chrome, Firefox, Safari, and Opera browsers

 

Installing and configuring PrimeFaces


The PrimeFaces library comes as a single jar file and doesn't have any mandatory third-party library dependencies. So to use PrimeFaces, it is sufficient to add PrimeFaces jar along with a JSF implementation library such as Oracle's Mojarra or Apache's MyFaces.

However, based on the PrimeFaces features that you want to use, you may need to add some third-party libraries. The following table describes library dependency needed for a particular feature:

Dependency

Type

Version

Description

JSF runtime

2.0, 2.1, or 2.2

Required

Apache MyFaces or Oracle Mojarra

itext

2.1.7

Optional

DataExporter (PDF)

apache poi

3.7

Optional

DataExporter (Excel)

rome

1.0

Optional

FeedReader

commons-fileupload

1.2.1

Optional

FileUpload

commons-io

1.4

Optional

FileUpload

The preceding table contains the third-party library versions, which are tested and known to be working fine with PrimeFaces-4.0 version. Other versions might also work fine but they are not officially tested.

Tip

If you are using a servlet container such as Apache Tomcat, then you need to add JSF implementation library dependencies such as Oracle's Mojarra or Apache MyFaces. If you are using any JavaEE application servers such as, JBoss AS, Glassfish, WebLogic, and so on; then there is no need to add JSF implementation libraries explicitly as they come in-built with application server. Some application servers may not have latest JSF implementation libraries. So, check whether your application server has JSF 2.0 or 2.1 or 2.2 implementation libraries or not. Consult your application server specific documentation to see how to override server libraries with latest versions.

In this book, we will be using PrimeFaces-4.0, which is latest version at the time of writing along with Oracle's Mojarra-2.2.3 JSF implementation.

 

Time for action – installing and configuring PrimeFaces


Perform the following steps to install and configure PrimeFaces to your web application:

  1. Configure JSF FacesServlet in web.xml:

    <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>*.jsf</url-pattern>
    </servlet-mapping>

    Tip

    Downloading the example code

    You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

  2. If you are not using Maven, then you can download PrimeFaces-4.0.jar from http://www.primefaces.org/downloads.html and add it to classpath.

  3. If you are using Maven, then add PrimeFaces maven repository to the repository list, and add PrimeFaces-4.0 dependency in pom.xml.

    <repository>
      <id>prime-repo</id>
      <name>Prime Repo</name>
      <url>http://repository.primefaces.org</url>
    </repository>
    
    <dependency>
      <groupId>org.primefaces</groupId>
      <artifactId>primefaces</artifactId>
      <version>4.0</version>
    </dependency>
    
    <dependency>
      <groupId>com.sun.faces</groupId>
      <artifactId>jsf-api</artifactId>
      <version>2.2.3</version>
    </dependency>
    
    <dependency>
      <groupId>com.sun.faces</groupId>
      <artifactId>jsf-impl</artifactId>
      <version>2.2.3</version>
    </dependency>

What just happened?

We have configured PrimeFaces repository and primefaces-4.0.jar dependency in our maven pom.xml, so that the PrimeFaces library is available to the web application classpath. We have configured FacesServlet and mapped to the URL pattern *.jsf, other popular URL patterns used are /faces/*, *.faces, and *.xhtml.

Tip

The PrimeFaces libraries from 4.0 version will be available in Maven Central, so you need not configure the PrimeFaces repository. But if you want to use snapshot versions, you need to configure the PrimeFaces repository in pom.xml.

 

Creating a HelloWorld application using PrimeFaces


In previous section, we have configured and installed PrimeFaces. To start using PrimeFaces components, all we need to do is adding the namespace xmlns:p=http://primefaces.org/ui to JSF pages.

Let us create a simple JSF page using PrimeFaces to see whether we have successfully installed and configured PrimeFaces.

 

Time for action – creating a HelloWorld program using PrimeFaces


Let us create a helloworld.xhtml file with the PrimeFaces namespace configuration, and use the PrimeFaces editor component to display a rich HTML editor. Perform the following steps:

  1. To start using PrimeFaces components all we need to do is add the namespace xmlns:p=http://primefaces.org/ui in JSF facelets page.

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:p="http://primefaces.org/ui"> 
    <f:view contentType="text/html">
    <h:head>
      <title>First PrimeFaces Page</title>
    </h:head>
    <body>
      <h:form>
        <p:editor value="Hello World, PrimeFaces Rocks!!"/>
      </h:form>
    </body>
    </f:view>
    </html>
  2. Run the application and point your browser to http://localhost:8080/chapter01/helloworld.jsf. We can see the rich text editor as follows:

What just happened?

We have tested PrimeFaces configuration by using PrimeFaces editor component <p:editor/>. As we have configured PrimeFaces properly, we are able to see rich HTML editor.

  • Make sure you have the <h:head> tag in your facelets page to avoid "PrimeFaces not found" JavaScript error.

  • To make PrimeFaces work properly on webkit layout engine-based browsers such as, Chrome/Safari, enforce contentType to text/html using <f:view contentType="text/html">.

 

Creating simple forms using PrimeFaces


PrimeFaces provides various input elements such as inputText, password, inputTextarea, commandButton, commandLink, and so on, which are extensions to the standard JSF components providing additional features and theming support.

To get a feel of how to use PrimeFaces components, let us create a simple user registration form using PrimeFaces components.

 

Time for action – creating a user registration form


Let's start using PrimeFaces components by creating a simple user registration form, steps for the same are as follows:

  1. Create a User.java POJO (Plain Old Java Object):

    public class User 
    {
      private Integer id;
      private String userName;
      private String password;
      private String firstName;
      private String lastName;
      private String email;
      private String phone;        
      //setters & getters  
    }
  2. Create a JSF managed bean UserController.java, using the following code:

    @ManagedBean
    @RequestScoped
    public class UserController 
    {
      private User registrationUser;
     
      public UserController() {
        this.registrationUser = new User();
      }
    
      public User getRegistrationUser() {
        return registrationUser;
      }
      public void setRegistrationUser(User registrationUser) {
        this.registrationUser = registrationUser;
      }
        
      public String register() 
      {
        System.out.println("Register User :"+ this.registrationUser);
        String msg = "User Registered Successfully";
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg));
        FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true);
        return "registration.jsf?faces-redirect=true";  
      }
    
    }
  3. Create a registration.xhtml page to build the user registration form using PrimeFaces components as follows:

    <!DOCTYPE html> 
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:p="http://primefaces.org/ui"> 
    
    <h:head>
      <title>Registration</title>
    </h:head> 
    <body> 
      <h:form id="registrationForm">
        <p:panel header="Registration Form" style="width: 500px;">
    <p:messages/>
        <h:panelGrid columns="2">
          <p:outputLabel value="UserName:"/>
          <p:inputText id="userName" value="#{userController.registrationUser.userName}" label="UserName" />      
                
          <p:outputLabel value="Password:"/>
          <p:password id="password" value="#{userController.registrationUser.password}" label="Password"/>
          
          <p:outputLabel value="FirstName:"/>
          <p:inputText id="firstName" value="#{userController.registrationUser.firstName}" label="FirstName"/>
          
          <p:outputLabel value="LastName:"/>
          <p:inputText id="lastName" value="#{userController.registrationUser.lastName}"/>
                
          <p:outputLabel value="Email:"/>
          <p:inputText id="email" value="#{userController.registrationUser.email}"/>
    
          <p:outputLabel value=""/>
          <p:commandButton action="#{userController.register}" value="Register" update="registrationForm"/>
          
        </h:panelGrid>
        </p:panel>
      </h:form>
    </body> 
    </html>
  4. Run the application and point your browser to http://localhost:8080/chapter01/registration.jsf. Then you can see the following screenshot, Registration Form:

What just happened?

We have created a sample user registration form using PrimeFaces UI components <p:inputText/>, <p:password/>, <p:commandButton/>, and so on. We are looking for input components with rich look and feel because we used PrimeFaces components, which are extensions to the standard JSF UI components with theming support.

 

Performing form validations


Validating user submitted data is very common and a crucial part of any web application. JSF itself provides support for UI component validation and PrimeFaces enhances it with additional features.

In the previous section, we have created a sample user registration form but we did not validate the form for any mandatory fields. Let us enhance the registration form with the validations for mandatory fields.

Assume we have the following validation rules for the registration form:

  • UserName should not be blank.

  • Password should not be blank and should be at least four characters.

  • FirstName should not be blank.

 

Time for action – validating the user registration form


We can use JSF validations for performing the earlier mentioned validations on the registration form. We can also perform validations using PrimeFaces AJAX-based validations by hooking up with JavaScript events, for this perform the following steps:

  1. Update registrationWithVal.xhtml to build a user registration form along with validation support using the following code:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:p="http://primefaces.org/ui">
    
    <h:head>
      <title>Registration</title>
    </h:head>
    <body> 
      <h:form id="registrationForm">
        <p:panel header="Registration Form" style="width: 800px;">
        <p:messages />
        <h:panelGrid columns="3">
          <p:outputLabel value="UserName:*"/>
          <p:inputText id="userName" value="#{userController.registrationUser.userName}"
              required="true" label="UserName" >
            <p:ajax event="keyup"  update="userNameMsg"/>
          </p:inputText>
          <p:message id="userNameMsg" for="userName"/>
          
          <p:outputLabel value="Password:*"/>
          <p:password id="password" value="#{userController.registrationUser.password}"
                required="true" label="Password">
            <f:validateLength minimum="4"/>
            <p:ajax update="passwordMsg" event="keyup"/>
          </p:password>
          <p:message id="passwordMsg" for="password"/>
          
          <p:outputLabel value="FirstName:*"/>
          <p:inputText id="firstName" value="#{userController.registrationUser.firstName}"
                 required="true" label="FirstName">
          
          </p:inputText>
          <p:message id="firstNameMsg" for="firstName"/>
          
          <p:outputLabel value="LastName:"/>
          <p:inputText id="lastName" value="#{userController.registrationUser.lastName}"/>
          <p:message id="lastNameMsg" for="lastName"/>
          
          <p:outputLabel value="Email:"/>
          <p:inputText id="email" value="#{userController.registrationUser.email}"/>
          <p:message id="emailMsg" for="email"/>
          
          <p:outputLabel value=""/>
          <p:commandButton action="#{userController.register}" value="Register" update="registrationForm"/>
          <p:outputLabel value=""/>
          
            
        </h:panelGrid>
        </p:panel>
      </h:form>
    </body>
    </html>
  2. Run the application and point your browser to http://localhost:8080/chapter1/registrationWithVal.jsf. Leave UserName and FirstName blank and enter password with less than four characters and submit the form. Then Registration Form will be redisplayed with errors as shown in the following screenshot:

What just happened?

We have used input validations such as required, minimum length, and so on. We have used PrimeFaces AJAX-based validations using <p:ajax> on the keyup JavaScript event. So as you type in the password, it will get validated and update the validation message immediately. You can also use <p:ajax> with other JavaScript events such as keydown, keypress, mouseover, and so on.

Tip

Beware of registering AJAX event listeners for JavaScript events such as keyup, keydown, and so on; as it may increase processing overhead and degrade performance. So use this feature cautiously.

 

Performing client-side validations


PrimeFaces also supports hooking up client-side JavaScript event handlers (onclick, onblur, onchange, and so on) for many of its UI Components. We can use this feature to perform client-side validations and reduce the server validation roundtrips.

 

Time for action – client-side e-mail validation


In our Registration Form, we can do some basic e-mail format validation on client side itself thereby reducing the server roundtrip. We can create a JavaScript function to validate e-mail using Regex, and then hook it up with the onchange event on e-mail input field. Perform the following steps for the same:

  1. Write a JavaScript function to validate e-mail address:

    function validateEmail()
    {
      var emailReg = /^([\w-\.][email protected]([\w-]+\.)+[\w-]{2,4})?$/;
      var email = $.trim($("#userForm\\:email").val());
      if(email ==''){
        $("#userForm\\:emailMsg").text("");
        $("#userForm\\:emailMsg").attr("class", "");
        return;
      }
      if( emailReg.test( email ) ) {
        $("#userForm\\:emailMsg").text("Valid Email");    
        $("#userForm\\:emailMsg").attr("class", "ui-messages-info ui-widget ui-corner-all ui-messages-info-summary");       
      } else {
        $("#userForm\\:emailMsg").text("Invalid Email");
        $("#userForm\\:emailMsg").attr("class", "ui-message-error ui-widget ui-corner-all ui-message-error-detail");
       }
    }
  2. Add the validateEmail() function as an event handler for the onchange event on the e-mail input field:

    <h:form id="userForm">
        <p:outputLabel value="Email:"/>
      <p:inputText id="email" value="#{userController.user.email}" onchange="validateEmail();" />
      <p:message id="emailMsg" for="email"/>    
    
    </h:form>

What just happened?

We have created a JavaScript function to validate e-mail using Regex. Using the jQuery API we have added an info/error message notifying us whether the e-mail is valid or invalid. We have hooked up this function to the onchange event of the e-mail inputText element. So validateEmail() gets invoked as soon as the e-mail value is changed and shows the message.

We got the e-mail field using $("#userForm\\:email"), where userForm is the ID of the form and email is the ID of the e-mail inputText field. JSF generates the IDs with colon (:) separator, but jQuery has a special meaning for colon .So we have replaced the colon (:) with \\:

Instead of replacing the colon by yourself, you can use the PrimeFaces.escapeClientId() utility function as follows:

function validateEmail() 
{
  var emailReg = /^([\w-\.][email protected]([\w-]+\.)+[\w-]{2,4})?$/;
  var email = $.trim($(PrimeFaces.escapeClientId("userForm:email")).val());
  if(email ==''){
    $(PrimeFaces.escapeClientId("userForm:emailMsg")).text("");
    $(PrimeFaces.escapeClientId("userForm:emailMsg")).attr("class", "");
    return;
  }
  if( emailReg.test( email ) ) {
    $(PrimeFaces.escapeClientId("userForm:emailMsg")).text("Valid Email");    
    $(PrimeFaces.escapeClientId("userForm:emailMsg")).attr("class", "ui-messages-info ui-widget ui-corner-all ui-messages-info-summary");       
  } else {
    $(PrimeFaces.escapeClientId("userForm:emailMsg")).text("Invalid Email");
    $(PrimeFaces.escapeClientId("userForm:emailMsg")).attr("class", "ui-message-error ui-widget ui-corner-all ui-message-error-detail");
   }
}

Tip

Since JSF2.x, we can also change the JSF ID separator character using the following <context-param> configuration in web.xml:

<context-param>
    <param-name>javax.faces.SEPARATOR_CHAR</param-name>
    <param-value>-</param-value>
</context-param>

The preceding client-side validation process involves performing manual validations using JavaScript/jQuery. PrimeFaces-4.0 introduced the Client Side Validation (CSV) framework with more powerful features, which we will discuss in Chapter 4, Introducing the PrimeFaces Client Side Validation Framework.

 

Understanding partial page rendering (PPR)


PrimeFaces provides a generic partial page rendering (PPR) mechanism to update specific JSF components with AJAX.

PrimeFaces provides process, update attributes to indicate which view components need to be processed or updated. Partial processing also provides some keywords which has some special meaning.

Keyword

Description

@this

Component that triggers the PPR is processed.

@parent

Parent of the PPR trigger is processed.

@form

Encapsulating form of the PPR trigger is processed.

@namingcontainer

Encapsulating naming container.

@none

No component is processed, useful to revert changes to form.

@all

Whole component tree is processed just like a regular request.

Sometimes, we may need to process the form partially based on the action triggered on the form. A very common scenario is, there can be multiple submit buttons in a form and you need to perform validations based on the action performed and ignore other field validations that are irrelevant to the action invoked.

For example, assume we are viewing a User Detail Form and we can update the user details or delete the user record using Update and Delete submit buttons. For updating, the user fields, userId, userName, and firstName are mandatory where as for deleting, only userId is required. So, when the Update button is clicked, validations should be performed on userId, userName, and firstName fields. But when the Delete button is clicked, validations on userName and firstName should be skipped.

 

Time for action – partial processing on the user details form


In this section, we will demonstrate how to process only a subset of components based on the action performed.

  1. Create userDetails.xhtml with the User Details Form containing update and delete actions:

    <h:form id="userDetailsForm">
    <p:panel header="User Details Form" style="width: 800px;">
      <p:messages/>
      <h:panelGrid columns="3">
        
        <p:outputLabel value="UserId:*"/>
        <p:inputText id="userId" value="#{userController.loginUser.id}" required="true" label="UserId" />
        <p:message id="userIdMsg" for="userId"/>
          
        <p:outputLabel value="UserName:*"/>
        <p:inputText id="userName" value="#{userController.loginUser.userName}" required="true" label="UserName" />      
        <p:message id="userNameMsg" for="userName"/>
          
        <p:outputLabel value="Password:*"/>
        <p:password id="password" value="#{userController.loginUser.password}" required="true" label="Password"/>
        <p:message id="passwordMsg" for="password"/>
          
        <p:outputLabel value="FirstName:*"/>
        <p:inputText id="firstName" value="#{userController.loginUser.firstName}" required="true"   label="FirstName"/>
        <p:message id="firstNameMsg" for="firstName"/>
          
        <p:commandButton value="Update" action="#{userController.updateUser()}" update="userDetailsForm"/>    
        <p:commandButton value="Delete" action="#{userController.deleteUser()}" update="userDetailsForm"/>
                
      </h:panelGrid>
    </p:panel>
    </h:form>
  2. Create a managed bean UserController.java to perform update and delete actions:

    @ManagedBean
    @RequestScoped
    public class UserController 
    {
      private User loginUser;
        
      public UserController() 
      {
        this.loginUser = new User();    
      }
    
      public User getLoginUser() 
      {
        return loginUser;
      }
    
      public void setLoginUser(User loginUser) 
      {
        this.loginUser = loginUser;
      }
    
      public String  updateUser() {
        System.out.println("Updating User Id: "+this.loginUser.getId());
        String msg = "User updated Successfully";
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg));
        return "userDetails.jsf";
      }
      
      public String  deleteUser() {
        System.out.println("deleting User Id: "+this.loginUser.getId());
        String msg = "User deleted Successfully";
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg));
        return "userDetails.jsf";
      }
    }
  3. Run the application and point your browser to http://localhost:8080/chapter01/userDetails.jsf.

When you click on the Delete button, the whole form will be processed, and displays a form with error messages if any required fields are blank. To resolve this issue, we can use the process attribute to specify only the UserId field to be processed and invoke the deleteUser() method:

<p:commandButton value="Delete"action="#{userController.deleteUser()}" 
process="@this,userId"  update="userDetailsForm"/>

What just happened?

We have used the process attribute to specify which components to be processed so that we can bypass the other fields' validations, which are irrelevant to the invoked action. Also note that <p:commandButton> issues an AJAX request by default. So if you want to redirect to a different page after action logic is executed make it a non-AJAX request by setting ajax="false".

Submitting partial data to the server

Both JSF AJAX implementation and PrimeFaces serializes the whole form data, and post it to server even for AJAX requests that will process only partial components. In the case of forms with more number of input components, we will be sending huge payload even though only few specific components will be processed on server side. This process unnecessarily consumes server resources.

PrimeFaces provides partialSubmit feature, which enables to serialize and send only the components data that will be processed on server side. By default partialSubmit feature is disabled, and we can enable this feature globally by configuring the following context parameter in web.xml:

<context-param>
  <param-name>primefaces.SUBMIT</param-name>
  <param-value>partial</param-value>
</context-param>

The preceding configuration enables partialSubmit feature globally. We can override this partialSubmit behavior for specific command components or AJAX events as follows:

<p:commandButton value="Delete" action="#{userController.deleteUser()}" process="@this,userId" partialSubmit="true"  update="userDetailsForm"/>
<p:inputText id="userName" value="#{userController.registrationUser.userName}" required="true" label="UserName">
  <p:ajax event="keyup" 
  listener="#{userController.checkUserNamesExists()}" 
  update="userNameMsg" partialSubmit="true"/>
</p:inputText>

You can see the difference between payload data sending to server when partialSubmit is enabled and disabled using firebug or chrome developer tools.

 

Updating the view using AJAX


AJAX support became a must for any framework or library used for building rich and interactive web applications. AJAX features make the web application more responsive by updating parts of the page without requiring full page reload.

PrimeFaces has in-built AJAX support and is based on JSFs server-side APIs. On client side, PrimeFaces use the most popular JavaScript library jQuery.

Processing a form submission and updating the portions of view using AJAX is very commonly used feature in web applications. Let us see how we can submit a form and update the view using AJAX.

 

Time for action – updating the view using AJAX


Let us create a Login Form with user name and password. When form is submitted, show the login status using AJAX. Perform the following steps for the same:

  1. Create a login.xhtml page with login form as follows:

    <h:form id="loginForm">
      <p:panel header="Login Form" style="width: 500px;">  
        <h:panelGrid columns="2">
          <p:outputLabel value="UserName"/>
          <p:inputText value="#{userController.loginUser.userName}"/>
          
          <p:outputLabel value="Password"/>
          <p:password value="#{userController.loginUser.password}"/>
          
          <p:commandButton action="#{userController.login}" value="Login" update="loginStatusMsg"/>
          <p:commandButton type="reset" value="Reset"/>
          
          <p:outputLabel value="#{userController.loginStatus}" id="loginStatusMsg"/>
        </h:panelGrid>
      </p:panel>
    </h:form>
  2. Create a UserController.java managed bean as follows:

    @ManagedBean
    @RequestScoped
    public class UserController 
    {
      private User loginUser;
      private String loginStatus;
      
      public UserController() {
        this.loginUser = new User();    
      }
    
      public User getLoginUser() {
        return loginUser;
      }
    
      public void setLoginUser(User loginUser) {
        this.loginUser = loginUser;
      }
    
      public String getLoginStatus() {
        return loginStatus;
      }
      
      public void setLoginStatus(String loginStatus) {
        this.loginStatus = loginStatus;
      }
      
      public String login() {
        boolean validCredentials = "admin".equals(loginUser.getUserName()) && "admin".equals(loginUser.getPassword());
        this.loginStatus  = validCredentials? "Login Successful" : "Login failed";
        return null;
      }    
    }
  3. Point the browser to http://localhost:8080/chapter01/login.jsf.

When you enter UserName and Password and click on the Login button, the login status should be displayed using AJAX. Have a look at the following screenshot:

What just happened?

We have created a Login Form with UserName and Password fields. When we submit the form, the model gets updated and login status will be set based on the provided credentials. As we have specified to update the view component with the ID loginStatusMsg through update="loginStatusMsg", when you click on the Login button, the login status will be displayed without complete page refresh.

 

Updating the view using AJAX listeners


Sometimes we may need instant feedback to be shown as and so user fills the form, instead of showing error messages after form submission. For example, in user Registration Form, we may want to check whether the UserName is already in use and show an error message immediately.

PrimeFaces provides AJAX listener support to invoke method on JSF managed bean. We can use this feature to check whether the entered UserName is already in use or not, and update the view to show error message using AJAX, even before submitting the entire form.

 

Time for action – validate the UserName using AJAX listeners


Let's add AJAX event listener keyup event to the UserName input field so that as you type, it will check if the username entered is already in use or not.

  1. Create viewAjaxListener.xhtml with registration form to validate the UserName using AJAX Listener as follows:

    <h:form id="registrationForm">
      <p:panel header="Registration Form" style="width: 800px;">
      <h:panelGrid columns="3">
        <p:outputLabel value="UserName:*"/>
        <p:inputText id="userName" value="#{userController.registrationUser.userName}" required="true" label="UserName">
          <p:ajax event="keyup" listener="#{userController.checkUserNamesExists()}" update="userNameMsg"/>
        </p:inputText>
        <p:message id="userNameMsg" for="userName"/>
        
        <p:outputLabel value="Password:*"/>
        <p:password id="password" value="#{userController.registrationUser.password}" required="true" label="Password"/>        
        <p:message id="passwordMsg" for="password"/>
        
        <p:outputLabel value="FirstName:*"/>
        <p:inputText id="firstName" value="#{userController.registrationUser.firstName}" required="true" label="FirstName"/>
        <p:message id="firstNameMsg" for="firstName"/>    
        
        <p:commandButton action="#{userController.register}" value="Register" update="registrationForm"/>    
        
      </h:panelGrid>
      </p:panel>
    </h:form>
  2. Create a UserController.java managed bean with the checkUserNamesExists() method to check whether the entered UserName is already in use or not and add the error message accordingly:

    public void checkUserNamesExists()
    {
      String userName = this.registrationUser.getUserName();
      if("admin".equals(userName) || "test".equals(userName))
      {
        String msg = "UserName ["+userName+"] already in use.";
        FacesContext.getCurrentInstance().addMessage("registrationForm:userName", 
            new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg));
      }
    }
  3. Point your browser to http://localhost:8080/chapter01/viewAjaxListener.jsf.

Enter admin or test in the UserName field then you should see the error message displayed immediately as in the following screenshot:

What just happened?

We have used AJAX listener in conjunction with keyup event on the UserName input field. So for each keyup event the callback method checkUserNamesExists() will be invoked to check whether the entered UserName value is admin or test, and adds error message if it is. As we are updating the view component with ID userNameMsg using update="userNameMsg", the error message is displayed immediately using the AJAX update.

 

Performing tasks periodically using a poll component


PrimeFaces provides poll component, which can be used to perform actions via JSF managed bean methods, periodically on regular intervals.

Suppose we want to display current time on web pages. We can do it by using poll component. We can update the currentTime view component using <p:poll> component to display current time for every second without reloading the entire page.

 

Time for action – using the poll component to display the current time


Let's display live time by polling server time for every second and display it using the poll component.

  1. Create poll.xhtml with a poll component to display currentTime as follows:

    <h:form>
      <p:outputLabel value="Current Time:" /> <p:outputLabel id="currentTime" value="#{serverTimeBean.time}"/>
      <p:poll interval="1" listener="#{serverTimeBean.updateTime()}" update="currentTime"/>
    </h:form>
  2. Create ServerTimeBean.java managed bean with the updateTime() method to set the currentTime value as follows:

    @ManagedBean
    @RequestScoped
    public class ServerTimeBean 
    {
      private String time;
      public void setTime(String time) {
        this.time = time;
      }
      public String getTime() {
        return time;
      }
      public void updateTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        this.time = sdf.format(new Date());
      }
      
    }

What just happened?

We have used the <p:poll> component to call listener method updateTime() on ServerTimeBean for every second by specifying interval="1", and updated the view to display current time using AJAX.

The poll component provides the following attributes, which provides additional control on its behavior:

AttributeName

Description

onstart

JavaScript handler to execute before AJAX request begins.

oncomplete

JavaScript handler to execute when AJAX request is completed.

onsuccess

JavaScript handler to execute when AJAX request succeeds.

onerror

JavaScript handler to execute when AJAX request fails.

autoStart

In autoStart mode, polling starts automatically on page load, to start polling on demand set it to false.

stop

Stops polling when true.

Controlling the polling process using external triggers

Sometimes, we may want to have control on when to start/stop the polling process, stop polling based on some criteria, and so on. The PrimeFaces poll component provides these features with additional attributes giving you full control on polling process.

For example, we want to start polling when the Start button is clicked, and stop polling when the Stop button is clicked.

 

Time for action – manually start and stop polling


We will now demonstrate how to start and stop polling using external triggers such as start and stop buttons using following steps:

  1. Create a form with a poll component and start/stop buttons to start and stop polling using following code:

    <h:form>
      <p:outputLabel value="Current Time:" /> <p:outputLabel id="currentTime" value="#{serverTimeBean.time}"/>
      <p:poll interval="1"  listener="#{serverTimeBean.updateTime()}" update="currentTime" widgetVar="currentTimePoller" autoStart="false"/> <br/>
      <p:button value="Start" onclick="currentTimePoller.start()" href="#" />
      <p:button value="Stop" onclick="currentTimePoller.stop()" href="#"/><br/>
    </h:form>

What just happened?

We have set the autoStart attribute to false, so that polling does not start automatically on page load. We have given a name for the poll component using widgetVar ="currentTimePoller" so that we can invoke start() and stop() methods on the poll component. We have associated the start() and stop() methods to the button's onclick events. So when we click on the Start button, polling will start and when we click on the Stop button, polling will be stopped.

Tip

PrimeFaces provides PrimeFaces push, which is better suitable for asynchronous processing. Prefer using PrimeFaces push over <p:poll> component. For more information see http://www.primefaces.org/showcase/push/index.jsf.

 

Invoking server-side methods from JavaScript using RemoteCommand


RemoteCommand component provides an option to invoke server-side methods, say JSF managed bean methods, from JavaScript client-side code directly. This feature comes in handy when some task needs some client-side action and server-side logic. When you declare a RemoteCommand component to invoke a JSF managed bean method, then you can call it like a JavaScript function, with the remoteCommand name from the JavaScript code.

Suppose in our user Registration Form, we want to validate e-mail format first on client side using Regex and if it is in valid e-mail format, then we want to check whether the e-mail is already in use or not using server-side logic. We can do this by using the RemoteCommand component.

 

Time for action – validate e-mail using RemoteCommand


We will now take a look at how to invoke server-side logic from JavaScript code using RemoteCommand. First we will check the e-mail format on client side using JavaScript, and then invoke server-side logic to check if the user provided e-mail already in use or not. Perform the following steps:

  1. Create a method using following code in the UserController managed bean to check whether the given e-mail is already in use or not:

    @ManagedBean
    @RequestScoped
    public class UserController 
    {
      
      public void checkEmailExists()
      {
        String email = this.registrationUser.getEmail();
        if("[email protected]".equals(email) || "[email protected]".equals(email))
        {
          String msg = "Email ["+email+"] already in use.";
          FacesContext.getCurrentInstance().addMessage("registrationForm:email", 
              new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg));
        }
      }
    }
  2. On the user registration page, create validateEmail() JavaScript function for checking e-mail format, and use a remoteCommand component to invoke the checkEmailExists() actionListener method to check whether the given e-mail is already in use or not:

    <!DOCTYPE html> 
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:p="http://primefaces.org/ui"> 
    
    <h:head>
      <title>Home</title>
      <script>
      function validateEmail() 
      {
        var emailReg = /^([\w-\.][email protected]([\w-]+\.)+[\w-]{2,4})?$/;
        var email = $.trim($(PrimeFaces.escapeClientId("registrationForm:email")).val());
        if(email ==''){
          $(PrimeFaces.escapeClientId("registrationForm:emailMsg")).text("");
          $(PrimeFaces.escapeClientId("registrationForm:emailMsg")).attr("class", "");
          return;
        }
        if( emailReg.test( email ) ) {
          checkDuplicateEmail();       
        } else {
          $(PrimeFaces.escapeClientId("registrationForm:emailMsg")).text("Invalid Email");
          $(PrimeFaces.escapeClientId("registrationForm:emailMsg")).attr("class", "ui-message-error ui-widget ui-corner-all ui-message-error-detail");
         }
      }
      </script>
    </h:head> 
    <body> 
        
      <h:form id="registrationForm">
        <p:panel header="Registration Form" style="width: 800px;">    
          <h:panelGrid columns="3">
          
            <p:outputLabel value="Email:"/>
            <p:inputText id="email" value="#{userController.registrationUser.email}" onblur="validateEmail();" />
            <p:message id="emailMsg" for="email"/>
            
            <p:commandButton action="#{userController.register}" value="Register" update="registrationForm"/>  
            
          </h:panelGrid>
        </p:panel>
        <p:remoteCommand name="checkDuplicateEmail" actionListener="#{userController.checkEmailExists()}" update="emailMsg"/>    
      </h:form>    
    </body> 
    </html>

What just happened?

We have created a validateEmail() JavaScript function to check the e-mail format using Regex and will be called on onblur event on e-mail input element. In the validateEmail() function, if the e-mail format is invalid we are showing the error message as "Invalid email!!", otherwise we are invoking the remoteCommand checkDuplicateEmail as JavaScript function, which invokes the UserController.checkemailExists() method and add error message if the e-mail is already in use.

 

Summary


You have now been introduced to the PrimeFaces component library and did hands-on with some cool PrimeFaces features, but this is just the beginning. There are plenty more powerful yet easy to use Rich UI components, which we will be looking in further chapters. In this chapter, we took a glance at the PrimeFaces features and learned how to install and configure PrimeFaces. We have started by creating a simple HelloWorld application and learned performing validations and various AJAX features. We also learned how to use PrimeFaces PPR feature. Lastly, we have learned about polling and RemoteCommand components, which come very handy at times.

In the next chapter, we will take a look into the sample application TechBuzz that we will be building incrementally throughout the book. We will also discuss the application's domain model, creating the project structure and some sample screenshots of the application.

About the Author

  • K. Siva Prasad Reddy

    K. Siva Prasad Reddy is a Senior Software Engineer living in Hyderabad, India, and having more than seven years of experience in developing enterprise applications with Java and JavaEE technologies. Siva is a Sun Certified Java Programmer and has a lot of experience in server-side technologies such as Java, JavaEE, Spring, Hibernate, MyBatis, JSF, PrimeFaces, and WebServices (SOAP/REST). Siva is also the author of Java Persistence with MyBatis 3, Packt Publishing. Siva normally shares the knowledge he has acquired on his blog at www.sivalabs.in. If you want to find out more about his work, you can follow him on Twitter (@sivalabs) and GitHub (https://github.com/sivaprasadreddy).

    Browse publications by this author
PrimeFaces Beginner's Guide
Unlock this book and the full library for $5 a month*
Start now