Skip to content

JSF2, JPA, and PostgreSQL

October 9, 2010

Lets have a quick tutorial about JSF2 and JPA with PostgreSQL database. I am using Glassfish 3 so you will not need to configure JSF.

Introduction to JSF

JSF is an MVC based web application development framework in which you can create html forms, validate their values, invoking business logic, and displaying results. JSF provides many prebuilt HTML based GUI controls to which you can define server side action handlers. JSF can be used to generate graphics in format other than HTML and using protocol other than HTTP. It means JSF controls are device independent and can be rendered in a browser, mobile, etc. JSF2 also brings very good support of AJAX.

How JSF Application Works?

Generally JSF applications are made up of following components:

  • Managed Bean / Controllers
  • Model
  • Facelet Pages

Lets briefly talk about each one:

Managed Beans

Managed beans are like other java beans you might have write many times in your development. We call java beans as managed beans because JSF manages their life cycle. JSF runtime intialize the bean references in your facelet, control its life cycle, call its setter and getter methods, call action handlers.

You can define managed bean wtih @ManagedBean annotation. Every managed bean has an scope to which that bean instance would be alive. Different bean scopes in JSF2 are request, view, session, and application, each of these have their associated annotation. Default scope of a managed bean is request. JSF initialize a request scope bean two times for each form, 1) when the form is displayed 2) when form is submitted.

You can use your managed beans to define your form properties, action handlers, and controller to manage the flow of your application. However, the example given below i have used managed beans as controller only.

Model Classes

You can define business logic in your model classes and delegate the action calls from controller to your model classes as given in the CRUD book example in this article. JSF doesn’t inforce you to use the model classes but its a good design architecture to use model classes to encapsulate the business logic and data.

Facelet Pages

Facelets are the primary view technology in JSF 2 instead of JSPs. All the facelet pages are defined in *.xhtml pages and referred as *.jsf from the browser. You define FacesServlet in web.xml which receive every call made for *.jsf (if you have defined FacesServlet mapping as *.jsf) to corresponding *.xhtml page.

Book CRUD Example

Its easy to understand any technology by doing some practical work. Lets start with a CRUD example using JSF2 and JPA. We will create a simple Book object with few properties to play with our crud example. Following are the primary classes used in this example:

  • Book, This is a POJO class to hold the book information and it is persisted into the database using JPA.
  • BookController, This is the managed bean of book example, it defines event handlers for list, create, update and delete.
  • BookModel, This is used to define the business logic and it talks to the DAO layer to perform CRUD operations.
  • BookDAO, This is the DAO layer class and perform all JPA operations

Lets create our jsftest database. You can use following query to create the database:

CREATE ROLE jsfuser LOGIN
  PASSWORD 'jsfuser'
  SUPERUSER INHERIT CREATEDB CREATEROLE;

CREATE DATABASE jsftest
  WITH OWNER = jsfuser
       ENCODING = 'UTF8'
       LC_COLLATE = 'C'
       LC_CTYPE = 'C'
       CONNECTION LIMIT = -1;

Now create the book table and sequence that will be use in Book entity:

CREATE TABLE book
(
  id integer NOT NULL DEFAULT nextval('book_seq'::regclass),
  title character varying(100),
  author character varying(50),
  publisher character varying(50),
  CONSTRAINT book_pk PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE book OWNER TO jsfuser;

CREATE SEQUENCE book_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 4
  CACHE 1;
ALTER TABLE book_seq OWNER TO jsfuser;

Following is the JPA entity that we will use to save our Book data:

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;

/**
 */
@Entity
public class Book implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -3397263129495350023L;

	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_seq_gen")
	@SequenceGenerator(name = "book_seq_gen", sequenceName = "book_seq", allocationSize = 1)
	private Integer id;

	@Column
	private String title;

	@Column
	private String author;

	@Column
	private String publisher;

	
	/**
	 * @return the id
	 */
	public Integer getId() {
		return this.id;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(final Integer id) {
		this.id = id;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}


	public String getPublisher() {
		return publisher;
	}

	public void setPublisher(String publisher) {
		this.publisher = publisher;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}
}

Book class above is very straight forward java class. The only point to discuss in this class is the use of sequence. As i am using PostgreSQL that’s why I’ve used the sequence to get the unique ids for the book instances.

	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_seq_gen")
	@SequenceGenerator(name = "book_seq_gen", sequenceName = "book_seq", allocationSize = 1)
	private Integer id;

@Id annotation is used to specify the unique id column. When you use @Id annotation you need to specify how the unique keys will be generated for your entity. You use @GeneratedValue annotation to specify the unique id generation strategy. In case of sequence you need to use another annotation named @SequenceGenerator. @SequenceGenerator has different attributes to control the values of your sequence, I’ve used three of them 1) name: It is used to mention the name of the sequence generator. The value that you will give to this attribute will also be used in the generator attribute of @GeneratedValue. In above example the generator name is “book_seq_gen”. 2) Second attribute used in @SequenceGenerator is the name of the sequence you would have created in your database, and 3) allocationSize: is used to set the initial value of your sequence.

Lets talk a look at our BookController that is a managed bean for Book.

import java.io.Serializable;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

/**
 */
@ManagedBean
@SessionScoped
public class BookController implements Serializable {

    /**
	 * 
	 */
	private static final long serialVersionUID = -6557818468188090120L;

	@ManagedProperty("#{bookModel}")
    private BookModel bookModel;

    private final static String EDIT_BOOK = "editBook.xhtml";
    private final static String LIST_BOOKS = "books.xhtml";
    
    private Book currentBook;
    private int bookId;

    /**
     * @return the bookModel
     */
    public BookModel getbookModel() {
        return this.bookModel;
    }

    /**
     * @param bookModel the bookModel to set
     */
    public void setbookModel(final BookModel bookModel) {
        this.bookModel = bookModel;
    }

    public List<Book> getBooks() {
        return this.bookModel.getBooks();
    }

    public String create() {
    	currentBook = new Book();
        return EDIT_BOOK;
    }
    
    public String edit() {
        currentBook = this.bookModel.find(getBookId());
        return EDIT_BOOK;
    }

    public String save() {
    	bookModel.save(currentBook);
        return LIST_BOOKS;
    }
    
    public String delete() {
        bookModel.delete(getBookId());
        return LIST_BOOKS;
    }

	public Book getCurrentBook() {
		return currentBook;
	}

	public void setCurrentBook(Book currentBook) {
		this.currentBook = currentBook;
	}

	public int getBookId() {
		return bookId;
	}

	public void setBookId(int bookId) {
		this.bookId = bookId;
	}

}

BookController has three parts 1) properties 2) action handlers and 3) placeholder property “currentBook”. BookController is a session scoped bean and it is using a managed property using @ManagedProperty. BookController uses @ManagedProperty to ingect the BookModel class and delegate all the actions to the model class for business operations. BookController support following operations:

  • Listing of all books: This operation is implemented by getBooks and it is used in books.xhtml jsf facelet.
  • Create and Edit: These operations are implemented by create and edit and they forward editBook.xhtml
  • Save: This operation is implemented by save and it returns to books listing page, books.xhtml
  • Delete: This operation is implemented by delete and it returns to books listing page, books.xhtml

Lets have a look at BookModel. We have implemented book model as another managed bean but it can also be implemented as an EJB as well.


import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class BookModel implements Serializable{

    /**
	 * 
	 */
	private static final long serialVersionUID = -3104501356925971373L;
	
	private List<Book> Books;

	public BookModel() {
		Books = new ArrayList<Book>();
		reload();
	}
	
    private void reload() {
        this.setBooks(BookDAO.Factory.getInstance().findAll());
	}

	/**
     * @return the Books
     */
    public List<Book> getBooks() {
        return this.Books;
    }

    /**
     * @param Books the Books to set
     */
    public void setBooks(final List<Book> Books) {
        this.Books = Books;
    }
    
    public void save(Book p) {
    	BookDAO.Factory.getInstance().save(p);
        reload();
    }
    
    public Book find(Integer id) {
		return BookDAO.Factory.getInstance().findById(id);
	}

    public void delete(Integer bookId) {
    	BookDAO.Factory.getInstance().delete(bookId);
        reload();
    }
    
}

Book model is a very simple model bean and it just forward calls to dao layer to perform the CRUD operations. You can implement different business logic in your model beans.

Following are the DAO layer classes:

import java.util.List;

public class BookDAO extends BaseDAO {

	private BookDAO() {
	}

	public boolean delete(Integer id) {
		return delete(id, Book.class);
	}

	public Book findById(Integer id) {
		return (Book) findById(id, Book.class);
	}

	public List<Book> findAll() {
		return findAll("FROM Book");
	}

	public static class Factory {

		private final static BookDAO INSTANCE = new BookDAO();

		public static BookDAO getInstance() {
			return INSTANCE;
		}
	}

}

/**
 * 
 */

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.spi.PersistenceProviderResolverHolder;

import org.apache.log4j.Logger;

/**
 */
public abstract class BaseDAO implements DAO {

	private final static Logger logger = Logger.getLogger(BaseDAO.class);

	protected final static EntityManagerFactory EMF;

	static {
		logger.info("Initializing EntityManagerFactory...");
		logger.info("providers:"
				+ PersistenceProviderResolverHolder
						.getPersistenceProviderResolver()
						.getPersistenceProviders());
		EMF = Persistence.createEntityManagerFactory("default");
	}

	public EntityManager getEntityManager() {
		return EMF.createEntityManager();
	}

	public boolean delete(Integer id, Class clazz) {
		EntityManager e = getEntityManager();
		EntityTransaction t = null;
		try {
			t = e.getTransaction();
			t.begin();
			Book b = e.find(clazz, id);
			e.remove(b);
			t.commit();
			return true;
		} catch (Exception ex) {
			if (t != null && t.isActive())
				t.rollback();
			logger.error(ex.getMessage(), ex);
			return false;
		} finally {
			e.close();
		}
	}

	public boolean save(Object object) {
		EntityManager e = getEntityManager();
		EntityTransaction t = null;
		try {
			t = e.getTransaction();
			t.begin();
			e.merge(object);
			t.commit();
			return true;
		} catch (Exception ex) {
			if (t != null && t.isActive())
				t.rollback();
			ex.printStackTrace(System.out);
			return false;
		} finally {
			e.close();
		}
	}

	public Object findById(Integer id, Class clazz) {
		return getEntityManager().find(clazz, id);
	}

	public List findAll(String query) {
		return getEntityManager().createQuery(query).getResultList();
	}

}

import java.util.List;

public interface DAO {

	public boolean save(Object dao);

	public boolean delete(Integer id, Class clazz);

	public Object findById(Integer id, Class clazz);
	
	public List findAll(String query);
	
}

Following facelet is used to display books:

<?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:fn="http://java.sun.com/jsp/jstl/functions"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core" >

  <h:head>
    <meta name="keywords" content="" />
    <meta name="description" content="" />
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta name="copyright" content="ingresssolutions" />
    <meta http-equiv="Expire" content="0" />
    <meta http-equiv="Pragma" content="no-cache" />
  </h:head>

  <h:body>

  <h1>Books</h1>
  <h:form>
  <table>
	<tr>
		<td colspan="2" align="right">
			<h:commandButton id="add" action="#{bookController.create}"
					value="Add Book" />

		
		</td>
	</tr>

  <tr>
  <th>Id</th>
  <th>Title</th>
  <th>Author</th>
  <th>Publisher</th>
  </tr>


  <ui:repeat value="#{bookController.books}" var="book" varStatus="s">
    <tr>
    <td>#{book.id}</td>
    <td>#{book.title}</td>
    <td>#{book.author}</td>
    <td>#{book.publisher}</td>
    <td>
    <h:commandLink action="#{bookController.edit}" value="Edit">
      <f:setPropertyActionListener target="#{bookController.bookId}" value="#{book.id}"/>
    </h:commandLink>
    </td>
    <td>
    <h:commandLink action="#{bookController.delete}" value="Delete">
      <f:setPropertyActionListener target="#{bookController.bookId}" value="#{book.id}"/>
    </h:commandLink>
    </td>
    </tr>
  </ui:repeat>

  </table>
</h:form>
  </h:body>
</html>

In the above facelet we have used head, body, form, commandButton, repeat, and commandLink tags. commandButton and commandLink are tied with server side action handlers. setPropertyActionListener is used to pass the book id to the controller to specify the book on which operation has to be performed. JSF creates a link and pass this id when that link is clicked.

Now, lets have a look at the editBook.xhtml which is used to create new book and edit existing books.

<?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:fn="http://java.sun.com/jsp/jstl/functions"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">

<h:head>
	<meta name="keywords" content="" />
	<meta name="description" content="" />
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<meta name="copyright" content="ingresssolutions" />
	<meta http-equiv="Expire" content="0" />
	<meta http-equiv="Pragma" content="no-cache" />
</h:head>

<h:body>

	<h1>Create New Book</h1>
	<h:form>
	<table>
		<tr>
			<td>Title</td>
			<td><h:inputText id="name" value="#{bookController.currentBook.title}" /></td>
		</tr>
		<tr>
			<td>Author</td>
			<td><h:inputText id="author" value="#{bookController.currentBook.author}" /></td>
		</tr>
		<tr>
			<td>Publisher</td>
			<td><h:inputText id="publisher" value="#{bookController.currentBook.publisher}" /></td>
		</tr>
		<tr>
			<td><h:commandButton action="#{bookController.save}"
				value="Save"/>
			</td>
		</tr>

	</table>
	</h:form>
</h:body>
</html>

When you click on Add Book or Edit links from books.jsf, a request is send to BookController which initialize a new book instance or retrieve book instance from database and forward the call to editBook.xhtml which displays a form to fillup book information or update information of an existing book.

editBook.xhtml uses #{bookController.currentBook.title} and other properties to display book information. When JSF runtime sees this information it look for a bean named bookController and create an instance of it, call its property currentBook and its property title to display book title information.

Conclusion

JSF2 is a good framework through which you can easily create web forms in java, validate them, perform server side event handlers, and utilize ajax features. The example present in this article is very simple but fully demonstrate the flow of JSF2 along with JPA. I will try to write other articles on same topic with more advanced features of JSF2 and JPA.

Advertisements

From → Java, Programming

4 Comments
  1. aristotel permalink

    Good article. But it is unclear what in what file should be ((. And how to get it to work in the instance of Eclipse.

    • skhanzada permalink

      In eclipse, setup glassfish version 3.1 and you will not need to make much configuration. For java classes you will use the same filename as the classname and for .xhtml pages you can use any name you like.

  2. Carlos permalink

    Thank you for this interest article it help me a lot, I have only a comment about your architecture, I implemented a simple CRUD Service and I use it directly from mi controller something like:

    Entity

    @ManagedBean(name=”usuario”)
    public class Usuario implements Serializable{
    /all getters and setters and fields
    }

    Controller
    @ManagedBean(name=”usuarioController”)
    public class UsuarioController {
    @ManagedProperty(value=”#{usuario}”)
    private Usuario usuario;
    private CrudService crudService=CrudService.getCrudService();
    //all stuff
    public void create() throws Exception{
    crudService.create(getUsuario());
    }
    }

    //Crud Service
    public class CrudService{
    //all stuff
    public T create(T t) throws Exception{
    EntityManager e=this.getEntityManager();
    EntityTransaction transaction=null;
    try{
    transaction=e.getTransaction();
    transaction.begin();
    e.persist(t);
    e.flush();
    e.refresh(t);
    transaction.commit();
    return t;
    }catch(Exception ex){
    if(transaction!=null && transaction.isActive()){
    transaction.rollback();
    }
    throw new Exception();
    }finally{
    e.close();
    }
    }
    }

    I’m not an expert so I would like to know what do you think about it 🙂

    • skhanzada permalink

      Service classes are generally used to define public API in your design and should not have the persistence responsibilities which is the prime concern of the DAO layer. So, if you are implementing persistence logic in CrudService you should better name it CrudDAO and write another class CrudService which will be the facade between your dao layer and your jsf beans layer. After that your beans will know the api expose by your CrudService and if any change happen in your dao layer you will not need to change your beans because service layer public methods will be unchanged.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: