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.