10. Version 5 - PAM Web / JSF Application
10.1. Application Architecture
The architecture of the PAM web application will be as follows:
![]() |
In this version, the GlassFish server will host all layers of the application:
- the [web] layer is hosted by the server’s servlet container (1 below)
- the other layers [business logic, DAO, JPA] are hosted by the server’s EJB3 container (2 below)
![]() |
The [business logic, DAO] components of the application running in the EJB3 container have already been implemented in the client/server application discussed in Section 7.1, which had the following architecture:
![]() |
The [business logic, DAO] layers ran in the GlassFish server’s EJB3 container, and the [UI] layer ran in a console or Swing application on another machine:
![]() |
In the architecture of the new application:
![]() |
only the [web / jsf] layer needs to be written. The other layers [business, DAO, JPA] are already in place.
In document [ref3], it is shown that a web application where the web layer is implemented with Java Server Faces has an architecture similar to the following:
![]() |
This architecture implements the MVC (Model, View, Controller) design pattern. The processing of a client request proceeds as follows:
If the request is made using a GET, the following two steps are executed:
- request - the client browser sends a request to the controller [Faces Servlet]. The controller handles all client requests. It is the application’s entry point. It is the C in MVC.
- response - the C controller instructs the selected JSF page to render. This is the view, the V in MVC. The JSF page uses an M model to initialize the dynamic parts of the response it must send to the client. This model is a Java class that can call upon the [business] layer [4a] to provide the V view with the data it needs.
If the request is made via a POST, two additional steps occur between the request and the response:
- request - the browser client makes a request to the [Faces Servlet] controller.
- processing - the C controller processes this request. Indeed, a POST request is accompanied by data that must be processed. To do this, the controller is assisted by event handlers specific to the application [2a]. These handlers may require the business layer [2b]. The event handler may need to update certain M models [2c]. Once the client’s request has been processed, it may trigger various responses. A classic example is:
- an error page if the request could not be processed correctly
- a confirmation page otherwise
The event handler returns a string-type result called a navigation key to the controller [Faces Servlet].
- navigation - the controller selects the JSF page (= view) to send to the client. This selection is based on the navigation key returned by the event handler.
- response - the selected JSF page sends the response to the client. It uses its M model to initialize its dynamic parts. This model can also call upon the [business] layer [4a] to provide the JSF page with the data it needs.
In a JSF project:
- the controller C is the [javax.faces.webapp.FacesServlet] servlet. This is found in the [jsf-api.jar] library.
- The V views are implemented by JSF pages.
- The M models and event handlers are implemented by Java classes often called "backing beans".
- In JSF 1.x versions, bean definitions and the rules for navigating from one page to another are defined in the [faces-config.xml] file. It contains the list of views and the rules for transitioning from one to another. Starting with JSF version 2, bean definitions can be made using annotations, and page transitions can be hard-coded directly in the bean code.
10.2. How the application works
When the application is requested for the first time, the following page appears:
![]() |
You then fill out the form and request the salary:
![]() |
The following result is displayed:
![]() |
This version calculates a fictitious salary. Do not pay attention to the page’s content, but rather to its layout. When you click the [Reset] button, you return to page [A].
Incorrect entries are flagged, as shown in the following example:
![]() |
10.3. The NetBeans Project
We will build an initial version of the application where the [business] layer will be simulated. We will have the following architecture:
![]() |
When event handlers or models request data from the [business] layer [2b, 4a], it will provide them with fictitious data. The goal is to obtain a web layer that responds correctly to user requests. Once this is achieved, all that remains is to install the server layer developed in Section 7.1:
![]() |
This will be version 2 of the web version of our PAM application.
The NetBeans project for version 1 is the following Maven project:
![]() |
- in [1], the configuration files
- in [2], the XHTML pages and the stylesheet
- in [3], the [web] layer classes
- in [4], the objects exchanged between the [web] layer and the [business] layer, and the [business] layer itself
- in [5], the message file for the application's internationalization
- in [6], the application dependencies
We will review some of these elements.
10.3.1. Configuration files
The [web.xml] file is the one generated by default by NetBeans, along with the configuration for an exception page:
- line 30: [index.html] is the application's home page
- lines 32–39: configuration of the exception page
The [exception.html] page is taken from [ref3]. Its code is as follows:
Any exception not explicitly handled by the web application code will cause a page similar to the one below to be displayed:
![]() |
The [faces-config.xml] file will be as follows:
Note the following points:
- Lines 9–14: The [messages.properties] file will be used for page internationalization. It will be accessible in XHTML pages via the msg key.
- line 15: defines the [messages.properties] file as the priority source for error messages displayed by the <h:messages> and <h:message> tags. This allows you to override certain default JSF error messages. This feature is not used here.
10.3.2. The style sheet
The [styles.css] file is as follows:
.libelle{
background-color: #ccffff;
font-family: 'Times New Roman',Times,serif;
font-size: 14px;
font-weight: bold
}
body{
background-color: #ffccff
}
.error{
color: #ff3333
}
.info{
background-color: #99cc00
}
.titleInfo{
background-color: #ffcc00
}
Here are some examples of JSF code using these styles:
| ![]() |
| ![]() |
| ![]() |
10.3.3. The message file
The message file [messages_fr.properties] is as follows:
form.title=Payroll
form.comboEmployees.label=Employee
form.hoursWorked.label=Hours worked
form.daysWorked.label=Days worked
form.hoursWorked.required=Enter the number of hours worked
form.hoursWorked.validation=Invalid data
form.daysWorked.required=Enter the number of days worked
form.daysWorked.validation=Invalid data
form.btnSalary.label=Salary
form.btnClear.label=Clear
exception.header=The following exception occurred
exception.httpCode=HTTP error code
exception.message=Exception message
exception.requestUri=URL requested when the error occurred
exception.servletName=Name of the servlet requested when the error occurred
form.employeeInfo=Employee Information
form.employee.lastName=Last Name
form.employee.last_name=Last name
form.employee.address=Address
form.employee.city=City
form.employe.zipCode=Zip Code
form.employee.index=Index
form.contributions.info=Social Security Contributions Information
form.contributions.csgrds=CSGRDS
form.contributions.csgd=CSGD
form.contributions.pension=Pension
form.contributions.social-security=Social Security
form.infos.indemnites=Compensation Information
form.benefits.hourlyWage=Hourly Wage
form.maintenance.allowance.day = Maintenance / Day
form.meal.allowancesDay=Meals / Day
form.allowances.paid\u00e9 leave=Paid leave
form.salary.info=Salary Information
form.salary.base=Base Salary
form.salary.socialContributions=Social Contributions
form.salary.maintenance=Maintenance Allowances
form.salary.meal=Meal Allowances
form.salary.net=Net Salary
These messages are all used in the [index.xhtml] page, except for those in lines 11–15, which are used in the [exception.xhtml] page.
10.3.4. The scope of beans
The [web.forms.Form] bean will have a request scope:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class Form implements Serializable {
The [web.utils.ChangeLocale] bean will have application scope:
package web.utils;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class ChangeLocale implements Serializable{
// page locale
private String locale = "fr";
public ChangeLocale() {
}
public String setFrenchLocale(){
locale = "fr";
return null;
}
public String setEnglishLocale(){
locale = "en";
return null;
}
public String getLocale() {
return locale;
}
public void setLocale(String locale) {
this.locale = locale;
}
}
10.3.5. The [business] layer
The [business] layer implements the following IMetierLocal interface:
package business;
import java.util.List;
import javax.ejb.Local;
import jpa.Employee;
@Local
public interface ILocalJob {
// Get the pay stub
PayStub calculatePayStub(String SS, double hoursWorked, int daysWorked);
// list of employees
List<Employee> findAllEmployees();
}
This interface is the one used in the server-side of the client/server application described in Section 7.1.
The Business class that we will use to test the [web] layer implements this interface as follows:
package business;
...
public class Metier implements IMetierLocal {
// employee dictionary indexed by social security number
private Map<String, Employee> hashEmployees = new HashMap<String, Employee>();
// list of employees
private List<Employee> employeeList;
// Get the pay stub
public PayrollCalculatePayroll(String SS,
double hoursWorked, int daysWorked) {
// retrieve the employee with SS number
Employee e = hashEmployees.get(SS);
// return a sample pay stub
return new PayStub(e, new Contribution(3.49, 6.15, 9.39, 7.88), new PayElements(100, 100, 100, 100, 100));
}
// list of employees
public List<Employee> findAllEmployees() {
if(employeesList == null){
// create a list of two employees
employeeList = new ArrayList<Employee>();
listEmployees.add(new Employee("254104940426058", "Jouveinal", "Marie", "5 Rue des Oiseaux", "St. Corentin", "49203", new Compensation(2, 2.1, 2.1, 3.1, 15)));
listEmployees.add(new Employee("260124402111742", "Laverti", "Justine", "La brûlerie", "St Marcel", "49014", new Compensation(1, 1.93, 2, 3, 12)));
// employee dictionary indexed by social security number
for (Employee e : listEmployees) {
hashEmployees.put(e.getSS(), e);
}
}
// Return the list of employees
return employeesList;
}
}
We leave it to the reader to decipher this code. Note the method used: to avoid having to implement the EJB part of the application, we simulate the [business] layer. Once the [web] layer is verified as correct, we can then replace it with the actual [business] layer.
10.4. The [index.xhtml] form and its template [Form.java]
We will now build the form’s XHTML page and its model.
Recommended reading in [ref3]:
- Example #3 (mv-jsf2-03) for the list of tags that can be used in a form
- Example #4 (mv-jsf2-04) for drop-down lists populated by the model
- Example #6 (mv-jsf2-06) for input validation
- Example #7 (mv-jsf2-07) for handling the [Clear] button
10.4.1. Step 1
Question: Build the [index.xhtml] form and its [Form.java] model needed to display the following page:
![]() |
The input components are as follows:
id | JSF type | model | role | |
comboEmployees | <h:selectOneMenu> | String comboEmployeesValue List<Employee> getEmployees() | contains the list of employees in the format "first name last name". | |
hoursWorked | <h:inputText> | String hoursWorked | number of hours worked - real number | |
daysWorked | <h:inputText> | String daysWorked | number of days worked - integer | |
btnSalary | <h:commandButton> | starts the salary calculation | ||
btnReset | <h:commandButton> | resets the form to its initial state |
- The getEmployees method will return a list of employees retrieved from the [business] layer. The objects displayed by the combo box will have the itemValue attribute set to the employee's social security number and the itemLabel attribute set to a string consisting of the employee's first and last name.
- The [Salary] and [Clear] buttons will not be linked to event handlers for the time being.
- Input validity will be checked.

Test this version. In particular, verify that input errors are properly flagged.
Note: It is important that the ID attributes of the page components do not contain accented characters. With Glassfish 3.1.2, this causes the application to crash.
10.4.2. Step 2
Question: Complete the [index.xhtml] form and its [Form.java] template to display the following page once the [Salary] button has been clicked:
![]() |
The [Salary] button will be connected to the model’s calculateSalary event handler. This method will use the calculatePaystub method from the [business] layer. This paystub will be generated for the employee selected in [1].
In the model, the pay stub will be represented by the following private field:
private PayrollSheet payrollSheet;
which has get and set methods.
To retrieve the information contained in this object, you can write expressions like the following in the JSF page:
<h:outputText value="#{form.payrollSheet.employee.name}"/>
The expression in the value attribute will be evaluated as follows:
[form].getPayrollSheet().getEmployee().getName() where [form] represents an instance of the [Form.java] class. The reader can verify that the get methods used here do indeed exist in the [Form], [PayrollSheet], and [Employee] classes, respectively. If this were not the case, an exception would be thrown when evaluating the expression.
Test this new version.
10.4.3. Step 3
Question: Complete the [index.xhtml] form and its template [Form.java] to obtain the following additional information:
![]() |
We will follow the same approach as before. There is an issue with the euro currency symbol found in [1], for example. In an internationalized application, it would be preferable to use the display format and currency symbol of the selected locale (en, de, fr, ...). This can be achieved as follows:
<h:outputFormat value="{0,number,currency}">
<f:param value="#{form.payrollSheet.employee.dailyMaintenanceAllowance}"/>
</h:outputFormat>
We could have written:
<h:outputText value="#{form.payroll.employee.dailyMaintenanceAllowance} є">
but with the en_GB locale (British English), the amount would still be displayed in euros when it should be in pounds (£). The <h:outputFormat> tag allows information to be displayed based on the locale of the displayed JSF page:
- line 1: displays the {0} parameter, which is a number representing a monetary amount
- line 2: the <f:param> tag assigns a value to the {0} parameter. A second <f:param> tag would assign a value to the parameter labeled {1}, and so on.
10.4.4. Step 4
Recommended reading: Example #7 (mv-jsf2-07) in [ref3].
Question: Complete the form [index.xhtml] and its template [Form.java] to handle the [Reset] button.
The [Reset] button restores the form to the state it was in when it was first requested via a GET request. There are several challenges here. Some have been explained in [ref3].
The form returned by the [Raz] button is not the entire form but only the entered portion of it:

This result can be achieved using an <f:subview> tag as follows:
<f:subview id="viewInfos" rendered="#{form.viewInfosIsRendered}">
... the part of the form that you want to be able to hide
</f:subview>
The <f:subview> tag encloses the entire portion of the form that can be displayed or hidden. Any component can be displayed or hidden using the rendered attribute. If rendered="true", the component is displayed; if rendered="false", it is not. If the rendered attribute takes its value from the model, then the display of the component can be controlled programmatically.
In the example above, we will control the display of the viewInfos view using the following field:
private boolean viewInfosIsRendered;
along with its get and set methods. The methods handling clicks on the [Salary] and [Clear] buttons will update this boolean depending on whether the viewInfos view should be displayed or not.



















