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.