Creating a JSF Form and handling form submission with a controller

We are going to create a JSF Form and add some validation to it.This tutorial will demonstrate interacting with JSF Controllers.

.Prerequisites

-JAVA JDK

-Netbeans IDE

-Java EE Container

 Creating the project.

We are going to use Netbeans IDE(version 12.2).

1.File|New Project|Java With Ant|Java Enterprise|Enterprise Application

2.Click Next.

3.On next window,type JSFForm as project name under Project Name and Choose appropriate Project Location on your local file system

4.Also click to check the checkbox ‘Use Dedicated Folder for Storing Libraries’ and clicke Next

5.Choose the Server(Java EE  application container) on which you application will run on.If you don’t have one,please check tutorial on setting up a local Java EE  Container on your machine.

6.Click Finish to create the Project

 

Running the Project

1.Right Click the JSFForm application  from your Projects tab.

2.Click Run

3.The Java EE Container will start(if not already running) and run the application

4.The default webpage will be displayed as below

 

 

web.xml

This file contains configurations on how our web applications runs.

1.Let’s create it by right clicking on the web application(JSFForm-war)|New.

2.Under Categories,choose Web,on the right under File Types,choose Standard Deployment Descriptor(web.xml)

3.Click Next then Finish

 

The file web.xml is created under the web application folder structure with minimal settings

Creating the form

We will create a form for capturing student data,validating the data and saving it to a datastore

1.Right Click Web Pages |New

2.From the list choose JSF Page.If it’s not in the list of options,click Other |Choose JavaServer Faces under Categories and JSF Page from File Types then Next

3.Type student-form under File Name and click Finish

4.The file student-form.xhtml is created under Web Pages

 

default page-the landing page

-First we need to make sure the Faces Servlet which runs the web application can load .xhtml pages

-To do this,let’s make the below changes to the web.xml file

Let’s add  <url-pattern>*.xhtml</url-pattern> to the section

<servlet-mapping>

        <servlet-name>Faces Servlet</servlet-name>

        <url-pattern>/faces/*</url-pattern>

        <url-pattern>*.xhtml</url-pattern>

    </servlet-mapping>

We then change the default landing page from index.html to student-form.xhtml  as follows

<welcome-file-list>

        <welcome-file>student-form.xhtml</welcome-file>

    </welcome-file-list>

We are now loading the student-form.xhtml page as the default page.Netbeans reloads the web application automatically we save our changes and these can be refected on the web pages immediately

Lets edit the student-form .xhtml page to see this in play

Change the body section to as below and save the file.

<h:body>

        Hello from Student-Form Page

    </h:body>

Check the browser and you will see the changes immediately as below

 

 

Lets add a form-code below

<?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://xmlns.jcp.org/jsf/html">

    <h:head>

        <title>Facelet Title</title>

    </h:head>

    <h:body>

        Student onboarding form

        <h:form prependId="false">

            <label for="firstname" >First name:</label>

             <h:inputText value="" id="firstname"  />

             <br></br>

             <label for="lastname" >Last name:</label>

             <h:inputText value="" id="lastname"  />

             <br></br>

             <label for="dob" >Date of birth:</label>

             <h:inputText value="" id="dob"  />

             <br></br>

             <h:commandButton value="Submit" ></h:commandButton>

        </h:form>

    </h:body>

</html>

On our browser,our form will now appear as follows.

 

 

Linking our form to a controller

1.On the JSFForm-war web project,right click Source Packages option and choose New | New Package.Name the package as com.example.jsfform and click Finish.

2.While on the com.example.jsfform right click and choose New|JSF CDI Bean.

3.Enter Class Name as AdmissionController and choose Scope as View (see more discussion on scopes),leave the other options as default then click Finish.

The class AdmissionController.java file has below code

 

package com.example.jsfform;

import javax.inject.Named;

import javax.faces.view.ViewScoped;

 

 

@Named(value = "admissionController")

@ViewScoped

public class AdmissionController {

 

    /**

     * Creates a new instance of AdmissionController

     */

    public AdmissionController() {

    }

   

}

 

Let’s add code to the AdmissionController.class

 

package com.example.jsfform;

import java.io.Serializable;

import java.util.Date;

import javax.faces.application.FacesMessage;

import javax.faces.context.FacesContext;

import javax.inject.Named;

import javax.faces.view.ViewScoped;

 

/**

 *

 * @author hp

 */

@Named(value = "admissionController")

@ViewScoped

public class AdmissionController implements Serializable {

 

    private static final long serialVersionUID = 1L;

    private String firstName;

    private String lastName;

    private Date dateOfBirth;

 

    /**

     * Creates a new instance of AdmissionController

     */

    public AdmissionController() {

    }

 

    public void processForm() {

        FacesContext ctx = FacesContext.getCurrentInstance();

        try {

            ctx.addMessage(null, new FacesMessage("Student admitted"));

        } catch (Exception ex) {

            ctx.addMessage(null, new FacesMessage(ex.getMessage()));

        }

    }

 

    /**

     * @return the firstName

     */

    public String getFirstName() {

        return firstName;

    }

 

    /**

     * @param firstName the firstName to set

     */

    public void setFirstName(String firstName) {

        this.firstName = firstName;

    }

 

    /**

     * @return the lastName

     */

    public String getLastName() {

        return lastName;

    }

 

    /**

     * @param lastName the lastName to set

     */

    public void setLastName(String lastName) {

        this.lastName = lastName;

    }

 

    /**

     * @return the dateOfBirth

     */

    public Date getDateOfBirth() {

        return dateOfBirth;

    }

 

    /**

     * @param dateOfBirth the dateOfBirth to set

     */

    public void setDateOfBirth(Date dateOfBirth) {

        this.dateOfBirth = dateOfBirth;

    }

}

 

Explanation

We have fields firstName, lastName and dateOfBirth.These hold the data submitted from the form.

We have also generated getters and setters for the fields.

We also have an action controller method processForm.In this method,the form processing logic is handled.The logic can be simple like inserting to a list,persisting to a database of file storage,making a network call to an external/internal webservice/api or any other complex processing we can envision.

Inside the processForm method,we declare an instance of FacesContext from where we can write success/error messages when processing the form.The message we write in the FacesContent will apply on the form during the RenderResponse phase/More on JSF life cycle phases can be found here.

 

We also make some modification on our student-form.xhtml file as follows.

 

<?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://xmlns.jcp.org/jsf/html"

      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"

      xmlns:f="http://xmlns.jcp.org/jsf/core">

    <h:head>

        <title>Facelet Title</title>

    </h:head>

    <h:body>

        Student onboarding form

        <h:form prependId="false">

            <ui:fragment rendered="#{not empty facesContext.messageList}">

                 <h:messages  />

            </ui:fragment>

            <br></br>

            <label for="firstname" >First name:</label>

            <h:inputText value="#{admissionController.firstName}" id="firstname"  />

             <br></br>

             <label for="lastname" >Last name:</label>

             <h:inputText value="#{admissionController.lastName}" id="lastname"  />

             <br></br>

             <label for="dob" >Date of birth:</label>

             <h:inputText value="#{admissionController.dateOfBirth}" id="dob>

                <f:convertDateTime pattern="MM/dd/yyyy" />

             </h:inputText>

             <br></br>

             <h:commandButton action="#{admissionController.processForm()}" value="Submit" ></h:commandButton>

        </h:form>

    </h:body>

</html>

The f: convertDateTime is a validator tag that converts our string input into a Date object before we process it on our controller method.

 

We have also hooked our submit button to the controller method as below

<h:commandButton action="#{admissionController.processForm()}" value="Submit" ></h:commandButton>

A successful submission will be as show below.

 

About the Author - John Kyalo Mbindyo(Bsc Computer Science) is a Senior Application Developer currently working at NCBA Bank Group,Nairobi- Kenya.He is passionate about making programming tutorials and sharing his knowledge with other software engineers across the globe. You can learn more about him and follow him on  Github.