JSF (JavaServer Faces) - Tutorial

JavaServer Faces with Eclipse. This article describes how to develop JavaServer Faces web applications with Eclipse WTP JSF tooling. It demonstrates managed beans, validators, external resource bundles and the JSF navigation concept. This tutorial was developed with Java 1.6, JavaServerFaces 1.2, the Apache MyFaces JSF implementation, Tomcat 6.0 and Eclipse'3.6.

1. JavaServer Faces - JSF

1.1. What is JSF

JavaServer Faces (JSF) is a UI component based Java Web application framework. JSF is serverbased, e.g. the JSF UI components and their state are represented on the server with a defined life cycle of the UI components. JSF is part of the Java EE standard.

A JSF application run in a standard web container, for example Tomcat or Jetty.

This articles provides an introduction to JSF using only standard JSF features. For the usage of special Apache Trinidad features please see Apache Myfaces Trinidad with Eclipse - Tutorial.

1.2. A JSF application

A JSF application consists of web pages with JSF UI components. A JSF application requires also some configuration files ("faces-config.xml" and web.xml ).

The faces-config.xml defines:

Managed beans are simple Java objects (POJO’s) which are declared in "faces-config.xml" and can be used in an JSF application. For example you can define a Java object "Person". Once you define the object in faces-config.xml you can use the attributes of Person in your JSF UI components, e.g. by binding the value "firstName" of this object to an JSF input field.

JSF uses the Unified Expression Language (EL) to bind UI components to object attributes or methods.

1.3. Value and Method Binding

In JSF you can access the values of a managed bean via value binding. For value binding the universal Expression Language (EL) is used (to access bean and / or methods). In JSF you do not need to specify the get() or set() method but just the variable name. Method binding can be used to bind a JSF component, e.g. a button to an method of a Java class.

Expression Language statements either start with "$". JSP EL expressions are using the $ syntax. These EL expressions are immediately evaluated. JSF EL expressions are of the type #. These are only evaluated when needed (and otherwise stored as strings).

1.4. Prerequisites to use JSF

To use JSF you need:

1.5. JSF Main features

JSP has the following main features:

1.6. JSP and JSF

In this tutorial the JSF application will be build based on JavaServer Pages (JSP’s). JSTL tags are used to include JSF UI components into the JSP. This is standard in JSF 1.2. The JSF 2.0 version is using Facelets.

2. JSF configuration files

2.1. Overview

JSF is based on the following configuration files:

2.2. web.xml

JSF requires the central configuration list web.xml in the directory WEB-INF of the application. This is similar to other web-applications which are based on servlets.

You must specify in web.xml that a "FacesServlet" is responsible for handling JSF applications. "FacesServlet" is the central controller for the JSF application.

"FacesServlet" receives all requests for the JSF application and initializes the JSF components before the JSP is displayed.

2.3. faces-config.xml

"faces-config.xml" allows to configure the application, managed beans, convertors, validators, and navigation.

3. Installation

3.1. Eclipse

For JSP development you need the Eclipse WTP and an installed Tomcat. See Installation of Eclipse WTP and Tomcat.

3.2. JSF library

A JSF library is required. We will later use Eclipse to download and install the Apache MyFaces JSF implementation during project creation.

3.3. JSLT library

4. Your first JSF project

Our first JSF example will be a celsius to fahrenheit convertor.

4.1. Create JSF Project

Create a new Dynamic Web Project "de.vogella.jsf.first". Under "Configuration" select "JavaServer Faces v1.2".

Press next until you see the following screen.

The first time you create a JSF project you need to install / download a JSF implementation. Press the Download library…​ button and select the Apache Library and install it.

Press Manage libraries and create a library for JSTL.

Click Finish. Your project has been created.

4.2. Review the generated project

Review the web.xml file. It has an entry for the Faces Servlet and for the servlet mapping. Also the file "faces-config.xml" has been created.

To add the JSF settings to an existing dynamic web project, right-click on your project, select Project Properties Project Facets and add then JSF facet to your project.

4.3. Domain Model

Create a package "de.vogella.jsf.first.model" and the class "TemperatureConvertor".

package de.vogella.jsf.first.model; public class TemperatureConvertor  private double celsius; private double fahrenheit; private boolean initial= true; public double getCelsius()  return celsius; > public void setCelsius(double celsius)  this.celsius = celsius; > public double getFahrenheit()  return fahrenheit; > public boolean getInitial() return initial; > public String reset () initial = true; fahrenheit =0; celsius = 0; return "reset"; > public String celsiusToFahrenheit() initial = false; fahrenheit = (celsius *9 / 5) +32; return "calculated"; > >

4.4. Define managed bean

Double-click on faces-config.xml in the WEB-INF directory and select the tab "ManagedBeans".

Press add and maintain your class.

The result should look like the following:

4.5. Create JSP

Select your project, right-click on it, select New → JSP. Create the JSP page "Convertor.jsp". Use the "New JavaServer Faces (JSF) Page (html)" template.

Change the code to the following.

 language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>  prefix="f" uri="http://java.sun.com/jsf/core"%>  prefix="h" uri="http://java.sun.com/jsf/html"%>    http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Celsius to Fahrenheit Convertor     columns="2">  value="Celsius">  value="#">   action="#" value="Calculate">  action="#" value="Reset">  layout="table">   rendered="#"> Result  value="Fahrenheit ">  value="#">    
All JSF tag must be always be enclosed in a tag.

4.6. Run your webapplication

Select Convertor.jsp, right mouse-click- >run as → run on server.

Congratulations. You should be able to use your JSF application.

4.7. Layout via css

JFP applications can get styled via css files. To load a style sheet include the following in your JSP page in the header section. This is related to the mystyle.css file under your folder WebContent/css..

/css/mystyle.css" rel="stylesheet" type="text/css">

5. Your second JSF application

This second JSF application will add validation, resource bundles and navigation as additional functionality.

5.1. Create JSF Project

Create a new Dynamic Web Project "de.vogella.jsf.starter".

5.2. Domain model

Create a new package de.vogella.jsf.starter.model and the following class.

package de.vogella.jsf.starter.model; public class User  private String name; private String password; public String getName()  return name; > public void setName(String name)  this.name = name; > public String getPassword()  return password; > public void setPassword(String password)  this.password = password; > public String login() // Image here a database access to validate the users if (name.equalsIgnoreCase("tester") && password.equalsIgnoreCase("tester")) return "success"; > else  return "failed"; > > >
Please note that we are hard-coding that only user tester with password tester can login.

Create the following class.

package de.vogella.jsf.starter.model; import java.util.Random; public class Card  private int left; private int right; private int result = 0; public Card()  Random random = new Random(); int i = 0; int j = 0; do  i = random.nextInt(10); > while (i  4); do  j = random.nextInt(100); > while (j  20); left = i; right = j; > public int getLeft()  return left; > public void setLeft(int left)  this.left = left; > public int getRight()  return right; > public void setRight(int right)  this.right = right; > // Controller public String show()  result = left * right; return "success"; > public String clear()  result = 0; return "clear"; > public int getResult()  return result; > public void setResult(int result)  this.result = result; > >
The class Card contains currently some controller code. The next chapter will demonstrate how to keep your model code clean and how to use controllers directly.

5.3. Register your managed beans

Double-click on faces-config.xml and select the tab "ManagedBeans". Register your User.java and Card.java as managed beans.

5.4. Validators

JSP allows to define validators which allows to check certain values which are placed in the UI. Create therefore the following class.

package de.vogella.jsf.starter.validator; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.validator.Validator; import javax.faces.validator.ValidatorException; public class LoginValidator implements Validator  public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException  String user = (String) value; if (!user.equalsIgnoreCase("tester"))  FacesMessage message = new FacesMessage(); message.setDetail("User " + user + " does not exists"); message.setSummary("Login Incorrect"); message.setSeverity(FacesMessage.SEVERITY_ERROR); throw new ValidatorException(message); > > >

Select your faces-config.xml and select the tab Component. Select Validators and press Add.

5.5. Resource bundle for messages

With JSP it is easy to use resource bundles for the static text in your JSP application. Create the following file "messages.properties" in your source folder under the package "de.vogella.jsf.starter".

user=User password=Password login=Login hello=Moin left=Left Side right=Right Side result= Result show= Show Result next= New Test reset= Reset

5.6. JavaServer Page with JSF components

Create a new JSP page "LoginView.jsp" and change the code to the following:

 language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>  prefix="f" uri="http://java.sun.com/jsf/core"%>  prefix="h" uri="http://java.sun.com/jsf/html"%>    http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Login    basename="de.vogella.jsf.starter.messages" var="msg" />  columns="2">  value="#">  value="#">  validatorId="de.vogella.jsf.starter.validator.LoginValidator" />   value="#">  value="#">    action="#" value="#">  layout="table">    

Lets explain a few fields.

Makes the core and html tags available in the page

Indicates that the following will use JSF components.

load the resource / message bundle which is then available in the application under the name msg

Defines a label which used the text user define in the resource bundle

Define a input field which used the managed bean user and maps to field name

Masked input files, mapped to the managed bean user and field password

The button is mapped to the method user.login

Create another JSP "Trainer.jsp" with the following code.

 language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>  prefix="f" uri="http://java.sun.com/jsf/core"%>  prefix="h" uri="http://java.sun.com/jsf/html"%>    http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here    basename="de.vogella.jsf.starter.messages" var="msg" />  columns="3">  value="#">  id="left" value="#">  for="left">  value="#">  id="right" value="#">   for="right">   action="#" value="#">  action="#" value="#" immediate="true">  layout="table">   rendered="#" columns="3">  value="#">  id="result" value="#">   for="result">    

Create another JSP FailedLogin.jsp with the following code.

       Insert title here   

Failed Login.

5.7. Navigation Rule

Select your faces-config.xml and select the tab "Navigation Rule". Make the palette available if necessary.

Select Page and click in the workarea. Add LoginView and Trainer to the workspace.

Click on Link, then on LoginView and then on Trainer. You should have now an arrow which indicates a navigation rule.

Click in the Palette on Select. Select then the arrow and the properities view. Input "success" in the From – Outcome

The user bean return the String success. In the navigation rule you now defined that if we receive "success" then we should be going to the next page.

Add a navigation rule so that in the case the user does not use the right user / password you send him to the failure page.

5.8. Run your webapplication

To run your webapplication, select LoginView.jsp, right mouse-click- >run as → run on server.

Remember that we are hard-coding that only user "tester" with password "tester" can login. Try another user this should not work.

You should be able to login with the right user and move to the next page.

6. JSF application with a controller

We will now extend the example from the previous chapter to a math trainer. The system will propose two number and the user must multiply both values and input the result. This JSF application will use a controller which handles the JSF logic. This will allow you to create a domain model without application logic.

In general it is considered as a good design practice to keep the model independently from the application logic.

This example will also demonstrate the usage of dependency injection in JSF.

6.1. Create JSF Project

Create a new Dynamic Web Project "de.vogella.jsf.card".

6.2. Domain model

Create a new package de.vogella.jsf.card.model and the following class.

package de.vogella.jsf.card.model; import java.util.Random; public class Card  private int left; private int right; public Card()  Random random = new Random(); int i = 0; int j = 0; do  i = random.nextInt(10); > while (i  4); do  j = random.nextInt(100); > while (j  20); left = i; right = j; > public int getLeft()  return left; > public void setLeft(int left)  this.left = left; > public int getRight()  return right; > public void setRight(int right)  this.right = right; > >

6.3. Controller

Create the following class CardController.

package de.vogella.jsf.card.controller; import javax.faces.application.FacesMessage; import javax.faces.component.UIPanel; import javax.faces.context.FacesContext; import de.vogella.jsf.card.model.Card; public class CardController  private Card card; private UIPanel resultPanel; private int result; public CardController()  > public String checkResult()  FacesContext context = FacesContext.getCurrentInstance(); resultPanel.setRendered(true); if (checkOperation())  context.addMessage(null, new FacesMessage( FacesMessage.SEVERITY_INFO, "Correct", null)); > else  context.addMessage(null, new FacesMessage( FacesMessage.SEVERITY_INFO, "Incorrect", null)); > return null; > private boolean checkOperation()  return (card.getLeft() * card.getRight() == result); > public UIPanel getResultPanel()  return resultPanel; > public void setResultPanel(UIPanel resultPanel)  this.resultPanel = resultPanel; > public int getResult()  return result; > public void setResult(int result)  this.result = result; > public String next()  FacesContext context = FacesContext.getCurrentInstance(); if (checkOperation()) resultPanel.setRendered(false); card = new Card(); return null; > else  context.addMessage(null, new FacesMessage( FacesMessage.SEVERITY_INFO, "Incorrect", null)); > return null; > public Card getCard()  return card; > public void setCard(Card card)  this.card = card; > >

This class has a field resultPanel. This field will later get connected to a UIComponent (panel) from the JSP.

6.4. Register your managed beans- Dependency injection

Double-click on faces-config.xml and select the tab "ManagedBeans". Register the classes "CardController" and "Card" as managed beans. The scope of card will be set to none as it will be inserted into the ControllerCard via dependency injection. In the initialization tab maintain the data as displayed in the screenshot. The value # refers to the managed bean "card".

The generated XML code should look like the following (you see this if you select the tab "Source").

 cardController de.vogella.jsf.card.controller.CardController session card de.vogella.jsf.card.model.Card #  card de.vogella.jsf.card.model.Card none 

6.5. Resource bundle for messages

Create the following file "messages.properties" in your source folder under the package "de.vogella.jsf.card".

left=Left Side right=Right Side result=Result show= Check next= Next

6.6. JavaServer Page with JSF components

Create a new JSP page "Trainer.jsp" and change the code to the following:

       Insert title here   

Train your Brain

Please calculate the result

From the previously examples you should be able to read most of the fields. What is new is that is use now the binding. Binding allows to bind certain UIControls to a managed bean. This way be bind the panel for the result to the controller. The controller can then set the rendered attribute of this UIControl depending on the user settings.

6.7. Run your webapplication

To run your webapplication, select Trainer.jsp, right mouse-click- >run as → run on server.

7. A Todo JSF application

Lets now create a JSF application for maintaining a Todo list. The main new thing we will cover is the handling of tables in JSF. These tables will be created based on a Java collection from the managed bean.

7.1. Create JSF Project

Create a new Dynamic Web Project "de.vogella.jsf.todo".

7.2. Domain model

Create a new package de.vogella.jsf.todo.model and the following class.

package de.vogella.jsf.todo.model; import java.util.Calendar; public class Todo  private String id; private String title; private String description; private int priority; private Calendar dueDate; public Todo(String title, String description, int priority)  this.title = title; this.description = description; this.priority = priority; > public String getId()  return id; > public void setId(String id)  this.id = id; > public String getTitle()  return title; > public void setTitle(String title)  this.title = title; > public String getDescription()  return description; > public void setDescription(String description)  this.description = description; > public int getPriority()  return priority; > public void setPriority(int priority)  this.priority = priority; > public Calendar getDueDate()  return dueDate; > public void setDueDate(Calendar dueDate)  this.dueDate = dueDate; > >

7.3. Controller

Create the package de.vogella.jsf.todo.controller and the following class TodoController.

package de.vogella.jsf.todo.controller; import java.util.ArrayList; import java.util.List; import javax.faces.component.UICommand; import javax.faces.component.UIForm; import javax.faces.event.ActionEvent; import javax.faces.model.SelectItem; import de.vogella.jsf.todo.model.Todo; public class TodoController  // domain model related variables private ListTodo> todos; private Todo todo; // JavaServerFaces related variables private UIForm form; private UIForm tableForm; private UICommand addCommand; public TodoController()  todos = new ArrayListTodo>(); todos.add(new Todo("Learn JFS", "Finish this article", 1)); todos.add(new Todo("Stop drinking to much coffee", "Coffee is evil!", 3)); > public String addNew()  todo = new Todo("", "", 3); form.setRendered(true); addCommand.setRendered(false); return null; > public String save()  todos.add(todo); form.setRendered(false); addCommand.setRendered(true); return null; > public String cancel()  todo = null; form.setRendered(false); addCommand.setRendered(true); return null; > public String delete()  todos.remove(todo); return null; > public void displayTable(ActionEvent event)  if (event.getComponent().getId().equalsIgnoreCase("hide"))  tableForm.setRendered(false); > else  tableForm.setRendered(true); > > public ListSelectItem> getPriorities()  ListSelectItem> list = new ArrayListSelectItem>(); list.add(new SelectItem(1, "High")); list.add(new SelectItem(2, "Medium")); list.add(new SelectItem(3, "Low")); return list; > public ListTodo> getTodos()  return todos; > public void setTodos(ListTodo> todos)  this.todos = todos; > public Todo getTodo()  return todo; > public void setTodo(Todo todo)  this.todo = todo; > public UIForm getForm()  return form; > public void setForm(UIForm form)  this.form = form; > public UICommand getAddCommand()  return addCommand; > public void setAddCommand(UICommand addCommand)  this.addCommand = addCommand; > public UIForm getTableForm()  return tableForm; > public void setTableForm(UIForm tableForm)  this.tableForm = tableForm; > >

7.4. Register your managed beans

Double-click on faces-config.xml and select the tab "ManagedBeans". Register the TodoController.