Building Web Applications with Hibernate

In this topic, we use the NetBeans IDE to create and deploy a web application that displays data from a database. The web application uses the Hibernate framework as the persistence layer for retrieving and storing plain old Java objects (POJOs) to a relational database.

Hibernate is framework that provides tools for object relational mapping (ORM). The present topic demonstrates how to add support for the Hibernate framework to the IDE and create the necessary Hibernate files. After creating the Java objects and configuring the application to use Hibernate, we add a JSF managed bean and JSF 2.0 pages to display the data.

 

Softwares Used

To complete this topic, we will need the following software resources :—

  • NetBeans IDE 8.2
  • Java Development Kit (JDK) 8
  • GlassFish server 4.1.1
  • MySQL 5.0 with Type 4 driver
  • Sakila MySQL Sample Database Plugin

 

Developing Hibernate Application

We follow these steps one-by-one to create web application based on Hibernate.

 

Step 1: Creating the Database

This tutorial uses a MySQL database called sakila, a free sample MySQL database that is available from the MySQL site. The sakila database is not included when we install the IDE so we need to first create the database to follow this tutorial.

To create the sakila database we can download and install the Sakila Sample Database plugin using the Plugins manager. After we install the plugin the sakila database is added to the list of databases in the Create MySQL database dialog box. To get information on configuring the NetBeans IDE to work with MySQL, have a look at the Connecting to a MySQL Database tutorial.

  1. Open the Plugins manager and install the Sakila Sample Database plugin.
  2. After installing the plugin, start the MySQL database by expanding the Databases node in the Services window, right-clicking the MySQL Server node and choosing Start.
  3. Right-click the MySQL Server node and choose Create Database.
  4. Select the Sakila database from the New Database Name drop down list in the Create MySQL Database dialog box. Click OK.
    Screenshot of Create MySQL Database dialog

    When we click OK a Sakila node appears under the MySQL Server node.

  5. Right-click the Sakila node and choose Connect.

When we click Connect a database connection node for the Sakila database (jdbc:mysql://localhost:3306/sakila [root on Default schema]) is listed under the Databases node. When a connection is open we can view the data in the database by expanding the connection node.

 

Step 2: Creating the Web Application Project

In this exercise we will create a web application project and add the Hibernate libraries to the project. When we create the project, we will select Hibernate in the Frameworks panel of the New Project wizard and specify the database.

  1. Choose File > New Project (Ctrl-Shift-N) from the main menu. Select Web Application from the Java Web category and click Next.
  2. Type DVDStore for the project name and set the project location.
  3. Deselect the Use Dedicated Folder option, if selected. Click Next.

    For this tutorial there is little reason to copy project libraries to a dedicated folder because we will not need to share libraries with other users.

  4. Set the server to the GlassFish Server and set the Java EE Version to Java EE 6 Web. Click Next.
  5. Select the JavaServer Faces checkbox and use the default JSF 2.2 libraries.
  6. Select the Hibernate 4.3.1 checkbox in the list of frameworks.
  7. Select the sakila database from the Database Connection drop down list. Click Finish.

Note: If the sakila database is not available as an option in the Frameworks panel in the wizard, check to see if the connection is listed under the Databases node in the Services window. If the connection is not there, we need to create the database connection.

 

 

 

 

 

 

 

 

 

 

 

When we click Finish, the IDE creates the web application project and opens the hibernate.cfg.xml file and index.xhtml in the editor.

If we expand the Libraries node in the Projects window, we can see that the IDE added the Hibernate libraries to the to the project.

 

 

Step 3: Modifying the Hibernate Configuration File

When we create a new project that uses the Hibernate framework, the IDE automatically creates the hibernate.cfg.xml configuration file at the root of the context classpath of the application (in the Files window, src/java). The file is located in the under the Source Packages node in the Projects window. The configuration file contains information about the database connection, resource mappings, and other connection properties. We can edit the file using the multi-view editor, or edit the XML directly in the XML editor.

In this exercise we will edit the default properties specified in hibernate.cfg.xml to enable debug logging for SQL statements and to enable Hibernate’s session context management.

  1. Open hibernate.cfg.xml in the Design tab. We can open the file by expanding the node under Source Packages in the Projects window and double-clicking hibernate.cfg.xml.
  2. In the multi-view XML editor, expand the Configuration Properties node under Optional Properties.
  3. Click Add to open the Add Hibernate Property dialog box.
  4. In the dialog box, select the property named hibernate.show_sql and set the value to true. This enables the debug logging of the SQL statements.
    Add Hibernate Property dialog box the hibernate.show_sql property
  5. Expand the Miscellaneous Properties node and click Add.
  6. In the dialog box, select the property hibernate.current_session_context_class and set the value to thread to enable Hibernate’s automatic session context management.
    Add Hibernate Property dialog box for properties hibernate.current_session_context_class

7. Click Add again under the Miscellaneous Properties node and select hibernate.query.factory_class in the Property Name dropdown list.

8. Select org.hibernate.hql.classic.ClassicQueryTranslatorFactory as the Property Value. Click OK.
Add Hibernate Property dialog box for properties hibernate.query.factory_class

If we click the XML tab in the editor we can see the file in XML view. Our file should look similar to the following (the 3 new properties are bold):

<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/sakila</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">system</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
</session-factory>
</hibernate-configuration>

9.  Save the changes to the file.

We can close the file because we do not need to edit the file again.

 

Step 4: Creating the HibernateUtil.java Helper File

To use Hibernate we need to create a helper class that handles startup and that accesses Hibernate’s SessionFactory to obtain a Session object. The class calls configure() and loads the hibernate.cfg.xml configuration file and then builds the SessionFactory to obtain the Session object.

In this section we use the New File wizard to create the helper class HibernateUtil.java.

  1. Right-click the Source Packages node and select New > Other to open the New File wizard.
  2. Select Hibernate from the Categories list and HibernateUtil.java from the File Types list. Click Next.
  3. Type HibernateUtil for the class name and dvdrental for the package. Click Finish.

Screenshot of HibernateUtil wizard

When we click Finish, HibernateUtil.java opens in the editor. We can close the file because we don’t need to edit the file.

 

Step 5: Generating Hibernate Mapping Files and Java Classes

In this tutorial we use a POJO (plain old Java object) to represent the data in each of the tables in the database that we will use. The Java class specifies the fields for the columns in the tables and uses simple setters and getters to retrieve and write the data. To map the POJOs to the tables we can use a Hibernate mapping file or use annotations in the class.

We can use the Hibernate Mapping Files and POJOs from a Database wizard to create multiple POJOs and mapping files based on database tables. When  using the wizard we select all the tables for which we want POJOs and mapping files and the IDE then generates the files for us based on the database tables and adds the mapping entries to hibernate.cfg.xml. When we use the wizard we can choose the files that we want the IDE to generate (only the POJOs, for example) and select code generation options (generate code that uses EJB 3 annotations, for example).

 
5.1. Creating the Hibernate Reverse Engineering File

If we want to use the Hibernate Mapping Files and POJOs from a Database wizard, we first need to create a hibernate.reveng.xml reverse engineering file. The Hibernate Mapping Files and POJOs from a Database wizard requires hibernate.reveng.xml and hibernate.cfg.xml.

The reverse engineering file enables us to have greater control over the database mapping strategy. The Hibernate Reverse Engineering Wizard creates a reverse engineering file with a default configuration that we can edit in the XML editor.

To create the Hibernate reverse engineering file, perform the following steps.

    1. Right-click the Source Packages node in the Projects window and choose New > Other to open the New File wizard.
    2. Select Hibernate Reverse Engineering Wizard in the Hibernate category. Click Next.
    3. Specify hibernate.reveng as the File Name and src/java for the Folder. Click Next.
    4. Select hibernate.cfg.xml from the Configuration File drop down list, if not selected.
    5. Select the following tables from Available Tables and click Add to add the tables to Selected Tables.
      • actor
      • category
      • film
      • film_actor
      • film_category
      • language

Click Finish.

New Hibernate Reverse Engineering wizard

The wizard generates a hibernate.reveng.xml reverse engineering file and opens the file in the editor. We can close the reverse engineering file because we don’t need to edit the file.

 
5.2. Creating the Hibernate Mapping Files and POJOs

We can use the Hibernate Mapping Files and POJOs from a Database wizard to generate files for we. The wizard can generate a POJO and a corresponding mapping file for each table that we select in the wizard. The mapping files are XML files that contain data about how the columns in the tables are mapped to the fields in the POJOs. We need to have the hibernate.reveng.xml and hibernate.cfg.xml files to use the wizard.

To create the POJOS and mapping files using a wizard, perform the following steps.

    1. Right-click Source Packages node in the Projects window and choose New > Other to open the New File wizard.
    2. Select Hibernate Mapping Files and POJOs from a Database in the Hibernate category. Click Next.
    3. Ensure that the hibernate.cfg.xml and hibernate.reveng.xml files are selected in the drop down lists.
    4. Select JDK 5 Language Features under the “General Settings” options. Don’t choose the EJB 3 annotations here.
    5. Ensure that the Domain Code and Hibernate XML Mappings options under the “Code Generation Settings” are selected.
    6. Select dvdrental for the Package name. Click Finish.
      Generate Hibernate Mapping Files and POJOs wizard

When we click Finish the IDE generates POJOs and Hibernate mapping files with the fields mapped to the columns specified in hibernate.reveng.xml. The IDE also adds mapping entries to this file (shown in bold font).

<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/sakila</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">system</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
<mapping resource="dvdrental/Category.hbm.xml"/>
<mapping resource="dvdrental/FilmActor.hbm.xml"/>
<mapping resource="dvdrental/Film.hbm.xml"/>
<mapping resource="dvdrental/Actor.hbm.xml"/>
<mapping resource="dvdrental/Language.hbm.xml"/>
<mapping resource="dvdrental/FilmCategory.hbm.xml"/>
</session-factory>
</hibernate-configuration>

Note. Confirm that the mapping elements are listed after the property elements in the hibernate.cfg.xml file.

We can expand the dvdrental package to see the files generated by the wizard.

Screenshot of Projects window showing generated POJOs

 

 

Step 6: Creating the FilmHelper.java Helper Class

We will now create a helper class in the dvdrental package that will be used to perform Hibernate queries on the database. We will use the Hibernate Query Language (HQL) editor to construct and test the queries for retrieving data. After we test the queries we will create methods in the helper class that construct and run the queries. We will then invoke the methods in the helper class from a JSF managed bean.

 
6.1. Creating the Helper Class

In this section we use the New File wizard to create the helper class FilmHelper.java in the dvdrental package. We will create a Hibernate session by calling getSessionFactory() in HibernateUtil.java and create some helper methods to create queries to retrieve data from the database. We will invoke the helper methods from the JSP pages.

    1. Right-click the dvdrental source package node and select New > Java Class to open the New File wizard.
    2. Type FilmHelper for the class name.
    3. Confirm that dvdrental is selected as the Package. Click Finish.
    4. Adding the following code (in bold) to create a Hibernate session.
      public class FilmHelper {
      
          Session session = null;
      
          public FilmHelper() {
              this.session = HibernateUtil.getSessionFactory().openSession();
          }
      
      }
    5. Right-click in the editor and choose Fix Imports (Alt-Shift-I) to add any required import statements (org.hibernate.Session) and save the changes.

We will now modify FilmHelper.java to add methods that query the DB.

 
6.2. Enumerating Film Titles and Retrieving Actors Using an HQL Query

In this exercise, we will create a Hibernate Query Language (HQL) query that queries the database to retrieve a list of film titles from the Film table. We will then add a method that queries both the Actor and Film_actor tables to fetch the actors involved in a particular film.

The Film table has 1000 records so the method to retrieve the list of films should be able to retrieve records based on the filmId primary key. We will use the HQL editor to construct and test the HQL query. After we have created the correct query we will add a method to the class that can generate the proper query.

    1. Right-click the project node in the Projects window and choose Clean and Build.
    2. Right-click hibernate.cfg.xml in the Projects window and choose Run HQL Query to open the HQL query editor.
    3. Select hibernate.cfg from the drop down list in the toolbar.
    4. Test the connection by typing the following in the editor and clicking the Run HQL Query button ( Run HQL Query button ) in the toolbar.
      from Film

      When we click Run HQL Query we can see the results of the query in the bottom window of the HQL query editor.

      Generate Hibernate Mapping Files and POJOs wizard

      If we click the SQL button we can see the equivalent SQL query.

      select film0_.film_id as col_0_0_ from sakila.film film0_
    5. We now type the following query to retrieve the records in the Film table where the film id is between 100 and 200.
      from Film as film where film.filmId between 100 and 200

      The result window displays a list of records. Now that we have tested that the query returns the desired results, we can use the query in the helper class.

    6. Add the following method getFilmTitles() to FilmHelper.java to retrieve the films where the film id is between a certain range specified by the variables startID and endID.
      public List getFilmTitles(int startID, int endID) {
          List filmList = null;
          try {
                org.hibernate.Transaction tx = session.getTransaction();
      Query q = session.createQuery("from Film as film where film.filmId between '" + startID + "' and '" + endID + "'");
      filmList = (List) q.list();
      session.getTransaction().commit(); }
      catch (Exception e) { e.printStackTrace(); } return filmList; }
    7. Add the following method getActorsByID() that retrieves the actors in a particular film. The method constructs the query using filmId as the input variable.
      public List getActorsByID(int filmId){
          List actorList = null;
          try {
      org.hibernate.Transaction tx = session.getTransaction();
      Query q = session.createQuery("from Actor as actor where actor.actorId in (select filmActor.actor.actorId from FilmActor as filmActor where filmActor.film.filmId='" + filmId + "')");
      actorList = (List) q.list();
      session.getTransaction().commit();
      }
      catch (Exception e) {
      e.printStackTrace();
      } return actorList; }
    8. Fix the imports and save necessary changes.

      When we fix the imports we want to choose java.util.List and org.hibernate.Query.

 
6.3. Adding Additional Helper Methods

We will now add additional helper methods to FilmHelper.java to create queries based on an input variable. We can check the queries in the HQL query editor.

    1. Add the following method to retrieve a list of categories according to filmId.
      public Category getCategoryByID(int filmId){
          List categoryList = null;
          try {
                org.hibernate.Transaction tx = session.getTransaction();
      Query q = session.createQuery("from Category as category where category.categoryId in (select filmCat.category.categoryId from FilmCategory as filmCat where filmCat.film.filmId='" + filmId + "')");
      categoryList = (List) q.list();
      session.getTransaction().commit(); }
      catch (Exception e) { e.printStackTrace(); } return categoryList.get(0); }
    2. We add the following method to retrieve a single film according to filmId.
      public Film getFilmByID(int filmId){
          Film film = null;
          try {
                org.hibernate.Transaction tx = session.getTransaction();
      Query q = session.createQuery("from Film as film where film.filmId=" + filmId);
      film = (Film) q.uniqueResult();
      session.getTransaction().commit(); }
      catch (Exception e) { e.printStackTrace(); } return film; }
    3. We add the following method to retrieve the film language according to langId.
      public String getLangByID(int langId){
          Language language = null;
          try {
                org.hibernate.Transaction tx = session.getTransaction();
      Query q = session.createQuery("from Language as lang where lang.languageId=" + langId);
      language = (Language) q.uniqueResult();
      session.getTransaction().commit(); }
      catch (Exception e) { e.printStackTrace(); } return language.getName(); }
    4. Save the changes.

 

Step 7: Creating the JSF Managed Bean

In this step we will create a JSF managed bean. The methods in the managed bean are used for displaying data in the JSF pages and for accessing methods in the helper class to retrieve records. The JSF 2.0 specification enables us to use annotations in a bean class to identify the class as a JSF managed bean, to specify the scope and to specify a name for the bean.

To create the managed bean, perform the following steps.

  1. Right-click the dvdrental source package node and choose New > Other.
  2. Select JSF Managed Bean from the JavaServer Faces category. Click Next.
  3. Type FilmController for the Class Name.

    We will use the Managed Bean name filmController as the value for the inputText and commandButton in the JSF page index.xhtml when calling methods in the bean.

  4. Select dvdrental for the Package.
  5. Type filmController for the Name that will be used for the managed bean.
  6. Set Scope to Session. Click Finish.

New JSF Managed Bean wizard

 

When we click Finish, the IDE creates the bean class and opens the class in the editor. The IDE added the @Named and @SessionScoped annotations. We have also added the annotation @ManagedBean from javax.faces.bean.ManagedBean. See it below.

@Named(value = "filmController")
@ManagedBean
@SessionScoped
public class FilmController implements Serializable {
/** Creates a new instance of FilmController */ public FilmController() { } }

 

After addting fields & methods and fixing the imports the final code would look like this:

package dvdrental;

import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;

@Named(value = "filmController")
@ManagedBean
@SessionScoped
public class FilmController implements Serializable {

int startId;
int endId;
DataModel filmTitles;
FilmHelper helper;
private int recordCount = 1000;
private int pageSize = 10;

private Film current;
private int selectedItemIndex;

/**
* Creates a new instance of FilmController
*/
public FilmController() {
helper = new FilmHelper();
startId = 1;
endId = 10;
}

public FilmController(int startId, int endId) {
helper = new FilmHelper();
this.startId = startId;
this.endId = endId;
}

public Film getSelected() {
if (current == null) {
current = new Film();
selectedItemIndex = -1;
}
return current;
}

public DataModel getFilmTitles() {
if (filmTitles == null) {
filmTitles = new ListDataModel(helper.getFilmTitles(startId, endId));
}
return filmTitles;
}

void recreateModel() {
filmTitles = null;
}

public boolean isHasNextPage() {
if (endId + pageSize <= recordCount) {
return true;
}
return false;
}

public boolean isHasPreviousPage() {
if (startId - pageSize > 0) {
return true;
}
return false;
}

public String next() {
startId = endId + 1;
endId = endId + pageSize;
recreateModel();
return "index";
}

public String previous() {
startId = startId - pageSize;
endId = endId - pageSize;
recreateModel();
return "index";
}

public int getPageSize() {
return pageSize;
}

public String prepareView() {
current = (Film) getFilmTitles().getRowData();
return "browse";
}

public String prepareList() {
recreateModel();
return "index";
}

public String getLanguage() {
int langID = current.getLanguageByLanguageId().getLanguageId().intValue();
String language = helper.getLangByID(langID);
return language;
}

public String getActors() {
List actors = helper.getActorsByID(current.getFilmId());
StringBuffer totalCast = new StringBuffer();
for (int i = 0; i < actors.size(); i++) {
Actor actor = (Actor) actors.get(i);
totalCast.append(actor.getFirstName());
totalCast.append(" ");
totalCast.append(actor.getLastName());
totalCast.append(" ");
}
return totalCast.toString();
}

public String getCategory() {
Category category = helper.getCategoryByID(current.getFilmId());
return category.getName();
}

}

 

Step 8: Creating the Web Pages

In this exercise we will create two web pages for displaying the data. We will modify the index.xhtml generated by the IDE to add a table that displays the films in the database. We will then create browse.xhtml to display a film’s details when we click the “View” link in the table. We will also create a JSF template page that is used by index.xhtml and browse.xhtml.

 8.1. Creating template.xhtml

We will first create the JSF Facelets template template.xhtml that is used in the composition of the index.xhtml and browse.xhtml pages.

    1. Right-click the DVDStore project node in the Projects window and choose New > Other.
    2. Select Facelets Template in the JavaServer Faces category. Click Next.
    3. Type template for the File Name and choose the first CSS layout style.
    4. Click Finish.

      When we click Finish, the file template.xhtml opens in the editor. The template contains the following default code. The color marked code within and </h:head> will be replaced a little bit later.

      <h:head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <h:outputStylesheet name="./css/default.css"/>
      <h:outputStylesheet name="./css/cssLayout.css"/>
      <title>Facelets Template</title>
      </h:head>

      <h:body> <div id="top" class="top"> <ui:insert name="top">Top</ui:insert> </div> <div id="content" class="center_content"> <ui:insert name="content">Content</ui:insert> </div> </h:body>

      5. Modify the <ui:insert> element to change the default generated name to “body”.

      <div id="content" class="center_content">
              <ui:insert name="body">Content</ui:insert>
      </div>

      6. Save the changes.

The content enclosed within the element in index.xhtml and browse.xhtml will be inserted into the location identified with Content in the template. The CSS files also have to be added within <h:head> and </h:head> .

The final code would look like this:

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

<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
<link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
<title>Facelets Template</title>
</h:head>

<h:body>

<div id="top" class="top">
<ui:insert name="top">Top</ui:insert>
</div>

<div id="content" class="center_content">
<ui:insert name="body">Content</ui:insert>
</div>

</h:body>

</html>

 

8.2 Modifying index.xhtml

When we created the web application, the IDE automatically generated the page index.xhtml. In this exercise we modify the page to display a list of film titles. The JSF page calls the methods in the JSF Managed Bean FilmController to retrieve the list of films and then displays a table with the film titles and descriptions.

    1. Expand the Web Pages folder in the Projects window and open index.xhtml in the editor.

      The New Project wizard generated the following default index.xhtml page.

      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:h="http://java.sun.com/jsf/html">
      <h:head>
              <title>Facelet Title</title>
          </h:head>
          <h:body>
              Hello from Facelets
          </h:body>
      </html>
    2. Modify the page to use the JSF <ui:composition> and <ui:define> elements and add a <h:form> element.
      <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ui="http://java.sun.com/jsf/facelets">
          <ui:composition template="./template.xhtml">
              <ui:define name="body">
                  <h:form>
      
                  </h:form>
              </ui:define>
          </ui:composition>
      </html>

      When we start typing the tags, the IDE adds xmlns:ui="http://java.sun.com/jsf/facelets" tag library declaration.

      The <ui:composition> and <ui:define> elements are used in combination with the page template that we will create. The <ui:composition> element references the location of the template that will be used by this page. The <ui:define> element references the position in the template that the enclosed code will occupy.

    3. Add the following navigation links that call the previous and next methods in the JSF managed bean.
      <ui:define name="body">
                  <h:form>
                      <h:commandLink action="#{filmController.previous}" value="Previous #{filmController.pageSize}" rendered="#{filmController.hasPreviousPage}"/> 
                      <h:commandLink action="#{filmController.next}" value="Next #{filmController.pageSize}" rendered="#{filmController.hasNextPage}"/> 
                  </h:form>
          </ui:define>

         

    4. Add the following dataTable element (in bold) to generate the table to display the retrieved items.
      <h:form styleClass="jsfcrud_list_form">
                      <h:commandLink action="#{filmController.previous}" value="Previous #{filmController.pageSize}" rendered="#{filmController.hasPreviousPage}"/> 
                      <h:commandLink action="#{filmController.next}" value="Next #{filmController.pageSize}" rendered="#{filmController.hasNextPage}"/> 
                      <h:dataTable value="#{filmController.filmTitles}" var="item" border="0" cellpadding="2" cellspacing="0" rowClasses="jsfcrud_odd_row,jsfcrud_even_row" rules="all" style="border:solid 1px">
                          <h:column>
                              <f:facet name="header">
                                  <h:outputText value="Title"/>
                              </f:facet>
                              <h:outputText value="#{item.title}"/>
                          </h:column>
                          <h:column>
                              <f:facet name="header">
                                  <h:outputText value="Description"/>
                              </f:facet>
                              <h:outputText value="#{item.description}"/>
                          </h:column>
                          <h:column>
                              <f:facet name="header">
                                  <h:outputText value=" "/>
                              </f:facet>
                              <h:commandLink action="#{filmController.prepareView}" value="View"/>
                          </h:column>
                      </h:dataTable>
                      <br />
                  </h:form>

         

    5. Save the changes.

The index page will now display a list of film titles in the database. Each row in the table includes a “View” link that invokes the prepareView method in the managed bean. The prepareView method returns “browse” and will open browse.xhtml.

Note. When we type the <f:facet> tag, the IDE will add xmlns:f="http://java.sun.com/jsf/core tag library declaration. Confirm that the tag library is declared in the file.xmlns:f="http://java.sun.com/jsf/core tag library declaration. 

 

8.3 Creating browse.xhtml

We will now create the browse.xhtml page for displaying details of the selected film. We can use the Facelets Template Client wizard to create the page based on the JSF Facelets template template.xhtml that we created.

    1. Right-click DVDStore project node in the Projects window and choose New > Other.
    2. Select Facelets Template Client in the JavaServer Faces category. Click Next.
      screenshot of Facelets Template Client in New File wizard
    3. Type browse for the File Name.
    4. Locate the Template for the page by clicking Browse to open the Browse Files dialog box.
    5. Expand the Web Pages folder and select template.xhtml. Click Select File.
      screenshot of Browse Files dialog
    6. Select  <ui:composition> for the Generated Root Tag. Click Finish.

      When we click Finish, the file browse.xhtml opens in the editor with the following code.

      <ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
          template="./template.xhtml">
      
          <ui:define name="top">
              top
          </ui:define>
      
          <ui:define name="body">
              body
          </ui:define>
      
      </ui:composition>

      We can see that the new file specifies the template.xhtml file and that the tag <ui:define> has the property name="body"

    7. Add the following code (in bold) between the <ui:define> tags to create the form and call the methods in the managed bean FilmController to retrieve the data and populate the form.
      <ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
          template="./template.xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core">
      
              <ui:define name="top">
                  top
              </ui:define>
      
              <ui:define name="body">
              
                  <h:form>
                      <h:panelGrid columns="2">
                          <h:outputText value="Title:"/>
                          <h:outputText value="#{filmController.selected.title}" title="Title"/>
                          <h:outputText value="Description"/>
                          <h:outputText value="#{filmController.selected.description}" title="Description"/>
                          <h:outputText value="Genre"/>
                          <h:outputText value="#{filmController.category}"/>
      
                          <h:outputText value="Cast"/>
                          <h:outputText value="#{filmController.actors}"/>
      
      
                          <h:outputText value="Film Length"/>
                          <h:outputText value="#{filmController.selected.length} min" title="Film Length"/>
      
                          <h:outputText value="Language"/>
                          <h:outputText value="#{filmController.language}" title="Film Length"/>
      
                          <h:outputText value="Release Year"/>
                          <h:outputText value="#{filmController.selected.releaseYear}" title="Release Year">
                              <f:convertDateTime pattern="MM/dd/yyyy" />
                          </h:outputText>
                          <h:outputText value="Rental Duration"/>
                          <h:outputText value="#{filmController.selected.rentalDuration}" title="Rental DUration"/>
                          <h:outputText value="Rental Rate"/>
                          <h:outputText value="#{filmController.selected.rentalRate}" title="Rental Rate"/>
                          <h:outputText value="Replacement Cost"/>
                          <h:outputText value="#{filmController.selected.replacementCost}" title="Replacement Cost"/>
                          <h:outputText value="Rating"/>
                          <h:outputText value="#{filmController.selected.rating}" title="Rating"/>
                          <h:outputText value="Special Features"/>
                          <h:outputText value="#{filmController.selected.specialFeatures}" title="Special Features"/>
                          <h:outputText value="Last Update"/>
                          <h:outputText value="#{filmController.selected.lastUpdate}" title="Last Update">
                              <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" />
                          </h:outputText>
                      </h:panelGrid>
                      <br />
                      <br />
                      <h:commandLink action="#{filmController.prepareList}" value="View All List"/>
                      <br />
                  </h:form>
      
              </ui:define>
          </ui:composition>
      </html>

      We can see that browse.xhtml and index.xhtml will use the same page template.

    8. Save the changes.

 

Step 9: Running the Project

The basics of the application are now complete. We can now run the application to check if everything is working correctly.

1. Click Run Main Project in the main toolbar or right-click the DVDStore application node in the Projects window and choose Run.

The IDE saves all changed files, builds the application, and deploys the application to the server. The IDE opens a browser window to the URL http://localhost:8484/DVDStore/ that displays the list of films.

 

 

2. In our browser, click “View” for the first one in the list to load browse.xhtml to view the film details.

 
 
Hope you have enjoyed learning here!!