Understanding and Implementing Information Management Concepts and Techniques

Java Back-End Web App Tutorial Part 1: Building a Minimal App in Seven Steps

Learn how to build a back-end web application with minimal effort, using Java with Java Server Faces (JSF) as the user interface technology, the Java Persistence API (JPA) for object-to-storage mapping, and a MySQL database

Mircea Diaconescu

Gerd Wagner

Warning: This tutorial may still contain errors and may still be incomplete in certain respects. Please report any issue to Gerd Wagner at G.Wagner@b-tu.de or Mircea Diaconescu at M.Diaconescu@b-tu.de.

This tutorial is also available in the following formats: PDF. See also the project page, or run the example app from our server, or download it as a ZIP archive file.

This tutorial article, along with any associated source code, is licensed under The Code Project Open License (CPOL), implying that the associated code is provided "as-is", can be modified to create derivative works, can be redistributed, and can be used in commercial applications, but the article must not be distributed or republished without the authors' consent.

2015-07-24

Revision History
Revision 0.220150619gw, md
some small revisions
Revision 0.120140611gw, md
create first version

Table of Contents

Foreword
1. A Quick Tour of the Foundations of Web Apps
1. The World Wide Web (WWW)
2. HTML and XML
2.1. XML documents
2.2. Unicode and UTF-8
2.3. XML namespaces
2.4. Correct XML documents
2.5. The evolution of HTML
2.6. HTML forms
3. Styling Web Documents and User Interfaces with CSS
4. JavaScript - "the assembly language of the Web"
4.1. JavaScript as an object-oriented language
4.2. Further reading about JavaScript
5. Accessibility for Web Apps
2. Java Summary
1. Compared to JavaScript, what is different in Java?
2. JavaBean Classes and Entity Classes
3. Building a Minimal Java Web App in Seven Steps
1. Step 1 - Set up the Folder Structure
2. Step 2 - Write the Model Code
2.1. Storing Book objects in a database table books
2.2. Creating a new Book instance and storing it
2.3. Retrieving all Book instances
2.4. Updating a Book instance
2.5. Deleting a Book instance
2.6. Creating test data
2.7. Clearing all data
3. Step 3 - Configure the App
3.1. Create the EntityManager and UserTransaction objects
3.2. Configure the JPA database connection
3.3. Create the main template
3.4. Define the managed beans needed in facelets
3.5. Build the WAR file and deploy it to TomEE
4. Step 4 - Implement the Create Use Case
5. Step 5 - Implement the Retrieve/List All Use Case
6. Step 6 - Implement the Update Use Case
7. Step 7 - Implement the Delete Use Case
8. Run the App and Get the Code
9. Possible Variations and Extensions
9.1. Accessibility for Web Apps
9.2. Using resource URLs
9.3. Dealing with date/time information using Date and <time>
9.4. Using an alternative DBMS
10. Points of Attention
10.1. Code clarity
10.2. Boilerplate code
10.3. Offline availability
10.4. Architectural separation of concerns
11. Practice Projects
11.1. Develop a Java back-end web app for Managing Movie Data
Glossary

List of Figures

3.1. The object type Book.
3.2. The object type Movie.

List of Tables

2.1. Java Visibility Level
3.1. Sample data for Book
3.2. Book objects represented as a table
3.3. Sample data

Foreword

This tutorial is Part 1 of our series of six tutorials about model-based development of back-end web applications with Java in combination with the Java Persistence API (JPA) and Java Server Faces (JSF) as a back-end platform. It shows how to build a simple web app with minimal functionality.

This tutorial provides example-based learning materials and supports learning by doing it yourself.

A distributed web app is composed of at least two parts: a front-end part, which, at least, renders the user interface (UI) pages, and a back-end part, which, at least, takes care of persistent data storage. A back-end web app is a distributed web app where essentially all work is performed by the back-end component, including data validation and UI page creation, while the front-end only consists of a web browser's rendering of HTML-forms-based UI pages. Normally, a distributed web app can be accessed by multiple users, possibly at the same time, over HTTP connections.

In the case of a Java/JPA/JSF back-end app, the back-end part of the app can be executed by a server machine that runs a web server supporting the Java EE specifications Java Servlets, Java Expression Language (EL), JPA and JSF, such as the open source server Tomcat/TomEE.

The minimal version of a Java data management application discussed in this tutorial only includes a minimum of the overall functionality required for a complete app. It takes care of only one object type ("books") and supports the four standard data management operations (Create/Read/Update/Delete), but it needs to be enhanced by styling the user interface with CSS rules, and by adding further important parts of the app's overall functionality:

Chapter 1. A Quick Tour of the Foundations of Web Apps

Table of Contents

1. The World Wide Web (WWW)
2. HTML and XML
2.1. XML documents
2.2. Unicode and UTF-8
2.3. XML namespaces
2.4. Correct XML documents
2.5. The evolution of HTML
2.6. HTML forms
3. Styling Web Documents and User Interfaces with CSS
4. JavaScript - "the assembly language of the Web"
4.1. JavaScript as an object-oriented language
4.2. Further reading about JavaScript
5. Accessibility for Web Apps

If you are already familiar with HTML, XML and JavaScript, you may skip this chapter and immediately start developing a minimal web application by going to the next chapter.

1. The World Wide Web (WWW)

After the Internet had been established in the 1980'ies, Tim Berners-Lee developed the idea and the first implementation of the WWW in 1989 at the European research institution CERN in Geneva, Switzerland. The WWW (or, simply, "the web") is based on the Internet technologies TCP/IP and DNS. Initially, it consisted of

Later, further technology components have been added to this set of basic web technologies:

  • the page/document style language Cascading Style Sheets (CSS) in 1995,

  • the web programming language JavaScript in 1995,

  • the Extensible Markup Language (XML), as the basis of XHTML and the web formats SVG and MathML, in 1998.

2. HTML and XML

HTML allows to mark up (or describe) the structure of a human-readable web document or web user interface, while XML allows to mark up the structure of all kinds of documents, data files and messages, whether they are human-readable or not. XML has become the basis for HTML.

2.1. XML documents

XML provides a syntax for expressing structured information in the form of an XML document with nested elements and their attributes. The specific elements and attributes used in an XML document can come from any vocabulary, such as public standards or (private) user-defined XML formats. XML is used for specifying

  • document formats, such as XHTML5, the Scalable Vector Graphics (SVG) format or the DocBook format,

  • data interchange file formats, such as the Mathematical Markup Language (MathML) or the Universal Business Language (UBL),

  • message formats, such as the web service message format SOAP

2.2. Unicode and UTF-8

XML is based on Unicode, which is a platform-independent character set that includes almost all characters from most of the world's script languages including Hindi, Burmese and Gaelic. Each character is assigned a unique integer code in the range between 0 and 1,114,111. For example, the Greek letter π has the code 960, so it can be inserted in an XML document as &#960; using the XML entity syntax.

Unicode includes legacy character sets like ASCII and ISO-8859-1 (Latin-1) as subsets.

The default encoding of an XML document is UTF-8, which uses only a single byte for ASCII characters, but three bytes for less common characters.

Almost all Unicode characters are legal in a well-formed XML document. Illegal characters are the control characters with code 0 through 31, except for the carriage return, line feed and tab. It is therefore dangerous to copy text from another (non-XML) text to an XML document (often, the form feed character creates a problem).

2.3. XML namespaces

Generally, namespaces help to avoid name conflicts. They allow to reuse the same (local) name in different namespace contexts. Many computational languages have some form of namespace concept, for instance, Java and PHP.

XML namespaces are identified with the help of a namespace URI, such as the SVG namespace URI "http://www.w3.org/2000/svg", which is associated with a namespace prefix, such as svg. Such a namespace represents a collection of names, both for elements and attributes, and allows namespace-qualified names of the form prefix:name, such as svg:circle as a namespace-qualified name for SVG circle elements.

A default namespace is declared in the start tag of an element in the following way:

<html xmlns="http://www.w3.org/1999/xhtml">

This example shows the start tag of the HTML root element, in which the XHTML namespace is declared as the default namespace.

The following example shows a namespace declaration for an svg element embedded in an HTML document:

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   ...
  </head>
  <body>
    <figure>
      <figcaption>Figure 1: A blue circle</figcaption>
      <svg:svg xmlns:svg="http://www.w3.org/2000/svg">
        <svg:circle cx="100" cy="100" r="50" fill="blue"/>
      </svg:svg>
    </figure>
  </body>
</html>

2.4. Correct XML documents

XML defines two syntactic correctness criteria. An XML document must be well-formed, and if it is based on a grammar (or schema), then it must also be valid with respect to that grammar, or, in other words, satisfy all rules of the grammar.

An XML document is called well-formed, if it satisfies the following syntactic conditions:

  1. There must be exactly one root element.

  2. Each element has a start tag and an end tag; however, empty elements can be closed as <phone/> instead of <phone></phone>.

  3. Tags don't overlap, e.g. we cannot have

    <author><name>Lee Hong</author></name>
  4. Attribute names are unique within the scope of an element, e.g. the following code is not correct:

    <attachment file="lecture2.html" file="lecture3.html"/>

An XML document is called valid against a particular grammar (such as a DTD or an XML Schema), if

  1. it is well-formed,

  2. and it respects the grammar.

2.5. The evolution of HTML

The World-Wide Web Committee (W3C) has developed the following important versions of HTML:

  • 1997: HTML 4 as an SGML-based language,

  • 2000: XHTML 1 as an XML-based clean-up of HTML 4,

  • 2014: (X)HTML5 in cooperation (and competition) with the WHAT working group supported by browser vendors.

HTML was originally designed as a structure description language, and not as a presentation description language. But HTML4 has a lot of purely presentational elements such as font. XHTML has been taking HTML back to its roots, dropping presentational elements and defining a simple and clear syntax, in support of the goals of

  • device independence,

  • accessibility, and

  • usability.

We adopt the symbolic equation

HTML = HTML5 = XHTML5

stating that when we say "HTML" or "HTML5", we actually mean XHTML5

because we prefer the clear syntax of XML documents over the liberal and confusing HTML4-style syntax that is also allowed by HTML5.

The following simple example shows the basic code template to be used for any HTML document:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <meta charset="UTF-8" />
  <title>XHTML5 Template Example</title>
 </head>
 <body>
  <h1>XHTML5 Template Example</h1>
  <section><h1>First Section Title</h1>
   ...
  </section>
 </body>
</html>

Notice that in line 1, the HTML5 document type is declared, such that browsers are instructed to use the HTML5 document object model (DOM). In the html start tag in line 2, using the default namespace declaration attribute xmlns, the XHTML namespace URI http://www.w3.org/1999/xhtml is declared as the default namespace for making sure that browsers, and other tools, understand that all non-qualified element names like html, head, body, etc. are from the XHTML namespace.

Also in the html start tag, we set the (default) language for the text content of all elements (here to "en" standing for English) using both the xml:lang attribute and the HTML lang attribute. This attribute duplication is a small price to pay for having a hybrid document that can be processed both by HTML and by XML tools.

Finally, in line 4, using an (empty) meta element with a charset attribute, we set the HTML document's character encoding to UTF-8, which is also the default for XML documents.

2.6. HTML forms

For user-interactive web applications, the web browser needs to render a user interface. The traditional metaphor for a software application's user interface is that of a form. The special elements for data input, data output and form actions are called form controls. In HTML, a form element is a section of a web page consisting of block elements that contain controls and labels on those controls.

Users complete a form by entering text into input fields and by selecting items from choice controls. A completed form is submitted with the help of a submit button. When a user submits a form, it is normally sent to a web server either with the HTTP GET method or with the HTTP POST method. The standard encoding for the submission is called URL-encoded. It is represented by the Internet media type application/x-www-form-urlencoded. In this encoding, spaces become plus signs, and any other reserved characters become encoded as a percent sign and hexadecimal digits, as defined in RFC 1738.

Each control has both an initial value and a current value, both of which are strings. The initial value is specified with the control element's value attribute, except for the initial value of a textarea element, which is given by its initial contents. The control's current value is first set to the initial value. Thereafter, the control's current value may be modified through user interaction or scripts. When a form is submitted for processing, some controls have their name paired with their current value and these pairs are submitted with the form.

Labels are associated with a control by including the control as a child element within a label element ("implicit labels"), or by giving the control an id value and referencing this ID in the for attribute of the label element ("explicit labels"). It seems that implicit labels are (in 2015) still not widely supported by CSS libraries and assistive technologies. Therefore, explicit labels may be preferable, despite the fact that they imply quite some overhead by requiring a reference/identifier pair for every labeled HTML form field.

In the simple user interfaces of our "Getting Started" applications, we only need four types of form controls:

  1. single line input fields created with an <input name="..." /> element,

  2. single line output fields created with an <output name="..." /> element,

  3. push buttons created with a <button type="button">...</button> element, and

  4. dropdown selection lists created with a select element of the following form:

    <select name="...">
      <option value="value1"> option1 </option>
      <option value="value2"> option2 </option>
      ...
    </select>

An example of an HTML form with implicit labels for creating such a user interface is

<form id="Book">
  <p><label>ISBN: <output name="isbn" /></label></p>
  <p><label>Title: <input name="title" /></label></p>
  <p><label>Year: <input name="year" /></label></p>
  <p><button type="button">Save</button></p>
</form>

In an HTML-form-based user interface, we have a correspondence between the different kinds of properties defined in the model classes of an app and the form controls used for the input and output of their values. We have to distinguish between various kinds of model class attributes, which are mapped to various kinds of form fields. This mapping is also called data binding.

In general, an attribute of a model class can always be represented in the user interface by a plain input control (with the default setting type="text"), no matter which datatype has been defined as the range of the attribute in the model class. However, in special cases, other types of input controls (for instance, type="date"), or other controls, may be used. For instance, if the attribute's range is an enumeration, a select control or, if the number of possible choices is small enough (say, less than 8), a radio button group can be used.

3. Styling Web Documents and User Interfaces with CSS

While HTML is used for defining the content structure of a web document or a web user interface, the Cascading Style Sheets (CSS) language is used for defining the presentation style of these web pages, which means that you use it for telling the browser how you want your HTML (or XML) rendered: using which layout of content elements, which fonts and text styles, which colors, which bachgrounds, and which animations. Normally, these settings are made in a separate CSS file that is associated with an HTML file via a special link element in the HTML's head.

CSS is based on a form of rules that consist of selectors, which select the document element(s) to which a rule applies, and a list of property-value pairs that define the styling of the selected element(s) with the help of CSS properties such as font-size or color. There are two fundamental mechanisms for computing the CSS property values for any page element as a result of applying the given set of CSS rules: inheritance and the cascade.

The basic element of a CSS layout is a rectangle, also called "box", with an inner content area, an optional border, an optional padding (between content and border) and an optional margin around the border. This structure is defined by the CSS box model.

We will not go deeper into CSS in this tutorial, since our focus here is on the logic and functionality of an app, and not so much on its beauty.

4. JavaScript - "the assembly language of the Web"

This section provides a brief overview of JavaScript, assuming that the reader is already familiar with basic programming concepts and has some experience with programming, for instance, in PHP, Java or C#.

JavaScript is a dynamic functional object-oriented programming language that can be used for

  1. Enriching a web page by

    • generating browser-specific HTML content or CSS styling,

    • inserting dynamic HTML content,

    • producing special audio-visual effects (animations).

  2. Enriching a web user interface by

    • implementing advanced user interface components,

    • validating user input on the client side,

    • automatically pre-filling certain form fields.

  3. Implementing a front-end web application with local or remote data storage, as described in the book Building Front-End Web Apps with Plain JavaScript.

  4. Implementing a front-end component for a distributed web application with remote data storage managed by a back-end component, which is a server-side program that is traditionally written in a server-side language such as PHP, Java or C#, but can nowadays also be written in JavaScript with NodeJS.

  5. Implementing a complete distributed web application where both the front-end and the back-end components are JavaScript programs.

The version of JavaScript that is currently supported by web browsers is called "ECMAScript 5.1", or simply "ES5", but the next two versions, called "ES6" and "ES7" (or "ES 2015" and "ES 2016", as new versions are planned on a yearly basis), with lots of added functionality and improved syntaxes, are around the corner (and already partially supported by current browsers and back-end JS environments).

4.1. JavaScript as an object-oriented language

JavaScript is object-oriented, but in a different way than classical OO programming languages such as Java and C++. There is no explicit class concept in JavaScript. Rather, classes have to be defined by following some code pattern in the form of special JS objects: either as constructor functions or as factory objects.

However, objects can also be created without instantiating a class, in which case they are untyped, and properties as well as methods can be defined for specific objects independently of any class definition. At run time, properties and methods can be added to, or removed from, any object and class. This dynamism of JavaScript allows powerful forms of meta-programming, such as defining your own concepts of classes and enumerations (and other special datatypes).

4.2. Further reading about JavaScript

Good open access books about JavaScript are

5. Accessibility for Web Apps

The recommended approach to providing accessibility for web apps is defined by the Accessible Rich Internet Applications (ARIA) standard. As summarized by Bryan Garaventa in his article on different forms of accessibility, there are 3 main aspects of accessibility for interactive web technologies: 1) keyboard accessibility, 2) screen reader accessibility, and 3) cognitive accessibility.

Further reading on ARIA:

Chapter 2. Java Summary

Table of Contents

1. Compared to JavaScript, what is different in Java?
2. JavaBean Classes and Entity Classes

1. Compared to JavaScript, what is different in Java?

  1. No program without a class: Any Java program must include at least one class.

  2. No object without a class: For creating an object, a class has to be used (or defined) for

    • defining the properties of the object's property slots

    • defining the methods and functions that can be applied to the object (and all other objects instantiating the class)

  3. No global variables, no global methods: In Java, all variables and methods must be defined in the context of a class, which provides their name space.

  4. Classes, properties and methods are defined with a visibility level: public, protected or private.

  5. Java is strongly typed: Properties, parameters and variables must be declared to be of some type.

  6. Type parameters: Classes and complex data structures (such as lists) can be defined with the help of type parameters. See, for instance, this tutorial.

  7. Arrays are static: Arrays have a fixed size, which cannot be changed at run-time.

  8. Java programs must be compiled before they can be executed.

  9. Speed: Java is about twice as fast as optimized JavaScript.

In Java, visibility levels are used to define the possible levels of access:

Table 2.1. Java Visibility Level

Class Package Subclass World
public y y y y
protected y y y n
no modifier y y n n
private y n n n


Normally, properties are defined as private, with public getters and setters, so they are only directly accessible at the level of the class defining them.

2. JavaBean Classes and Entity Classes

A JavaBean class (or, simply, bean class) is a Java class with a parameter-free constructor where all properties are serializable and have a get and set method (also called "getter" and "setter"). A Java bean is an object created with the help of a bean class.

A JPA entity class (or, simply, entity class) is a JavaBean class with an @Entity annotation, implying that a JavaEE runtime environment (such as provided by the TomEE PLUS web server) will take care of the persistent storage of its instances.

Chapter 3. Building a Minimal Java Web App in Seven Steps

Table of Contents

1. Step 1 - Set up the Folder Structure
2. Step 2 - Write the Model Code
2.1. Storing Book objects in a database table books
2.2. Creating a new Book instance and storing it
2.3. Retrieving all Book instances
2.4. Updating a Book instance
2.5. Deleting a Book instance
2.6. Creating test data
2.7. Clearing all data
3. Step 3 - Configure the App
3.1. Create the EntityManager and UserTransaction objects
3.2. Configure the JPA database connection
3.3. Create the main template
3.4. Define the managed beans needed in facelets
3.5. Build the WAR file and deploy it to TomEE
4. Step 4 - Implement the Create Use Case
5. Step 5 - Implement the Retrieve/List All Use Case
6. Step 6 - Implement the Update Use Case
7. Step 7 - Implement the Delete Use Case
8. Run the App and Get the Code
9. Possible Variations and Extensions
9.1. Accessibility for Web Apps
9.2. Using resource URLs
9.3. Dealing with date/time information using Date and <time>
9.4. Using an alternative DBMS
10. Points of Attention
10.1. Code clarity
10.2. Boilerplate code
10.3. Offline availability
10.4. Architectural separation of concerns
11. Practice Projects
11.1. Develop a Java back-end web app for Managing Movie Data

In this chapter, we build a simple Java web application with the Java Persistence API (JPA) for object-to-storage mapping and Java Server Faces (JSF) as the user interface technology. Such an application requires a web server (as a back-end) environment executing the Java code, but also consists of HTML, CSS and possibly some auxiliary JavaScript front-end code that is executed on the user's computer. Since essentially all data processing (including constraint validation) is performed on the back-end, and the front-end only renders the user interface, we can classify Java/JPA/JSF web applications as back-end web apps.

JPA is a Java API for the management of persistent data in Java applications. It uses the Java Persistence Query Language (JPQL), a platform-independent object-oriented query language, which is heavily inspired by SQL, and its query expressions are quite similar to SQL query expressions, but they are executed in the context of JPA entity objects.

JSF is a Java specification for building component-based user interfaces for web applications. Its current version, JSF 2, by default, uses Facelets as its template technology. In contrast, JSF 1 has used JavaServer Pages (JSP) as its default template technology.

In this tutorial, we show how to develop, deploy and run a simple example app using the TomEE web server, which provides an execution environment for Java/JPA/JSF web apps. We assume that you have already installed the TomEE PLUS web server, the MySQL DBMS, and the ANT build tool on your computer.

The purpose of our example app is to manage information about books. For simplicity, in this chapter we deal with a single object type Book, as depicted in Figure 3.1.

Figure 3.1. The object type Book.

The object type Book.

The following is a sample data population for the model class Book:

Table 3.1. Sample data for Book

ISBN Title Year
006251587X Weaving the Web 2000
0465026567 Gödel, Escher, Bach 1999
0465030793 I Am A Strange Loop 2008

What do we need for a data management app? There are four standard use cases, which have to be supported by the app:

  1. Create a new book record by allowing the user to enter the data of a book that is to be added to the collection of stored book records.

  2. Retrieve (or read) all books from the data store and show them in the form of a list.

  3. Update the data of a book record.

  4. Delete a book record.

These four standard use cases, and the corresponding data management operations, are often summarized with the acronym CRUD.

For entering data with the help of the keyboard and the screen of our computer, we use HTML forms, which provide the user interface technology for web applications.

For any data management app, we need a technology that allows to store data in persistent records on a secondary storage device, such as a hard-disk or a solid state disk. JPA allows using a great number of different data storage technologies, including many SQL database management systems (DBMS) such as Oracle, MySQL and PostgreSQL. We don't have to change much in the application code for switching from one storage technology to another. Adding the right driver implementation to our Java runtime environment, properly setting up the DBMS and changing the database access configuration is all we need to do. Below, in step 3, we explain how to set up the JPA configuration for MySQL.

1. Step 1 - Set up the Folder Structure

In the first step, we set up our folder structure for the application program code. The application name in this chapter will be "Public Library", and we will use a corresponding name for the application folder, "publicLibrary". Then we create the application structure. There are many ways to do this, like for example to use the Eclipse development environment (and create and configure a Dynamic Web Project). In this tutorial we show how to do it manually, so there is no need to use special tools, except ANT for being able to compile and deploy the application more easily. For your convenience, we provide an ANT script (available for download at the end of this tutorial), which is able to create the folder structure of a web application, compile it to a Web application Archive (WAR) file and then deploy it to a TomEE web server for execution. The application structure (which is compatible with the Dynamic Web Project structure of Eclipse, so it can be imported in Eclipse) is the following:

publicLibrary
  src
    pl
      model
      ctrl
    META-INF
      persistence.xml
  WebContent
    views
      books
    WEB-INF
      templates
      faces-config.xml
      web.xml

This folder structure has the following parts:

  1. The src folder contains the app code folder pl, defining the Java package name for the app (as a shortcut of 'public library'), and the folder META-INF with configuration files:

    1. the app code folder pl contains the model and controller code in its subfolders model and ctrl, while the view/UI code is contained in the WebContent folder;

    2. the most important configuration file (and the only one we need for this app) is the persistence.xml file. It contains the configuration for the database connection. The content of this file is discussed in Section 3.2.

  2. The WebContent folder contains various web resources, including template files and custom view files:

    1. the views stores our custom view files for the application, so it represents the View part of the MVC paradigm. Please note that it is not strictly required to name it views, but it makes a lot of sense to do it so, since this is what this folder represents. We will discuss in details about its content, later in this tutorial.

    2. the WEB-INF folder contains the used libraries (jar files) of the project (as part of the lib subfolder), the JSF template files for your pages (as part of the templates subfolder), the faces-config.xml file, which stores the facelets configuration data and the web.xml configuration file, specific to the Tomcat (TomEE) environment server used to run our application.

2. Step 2 - Write the Model Code

In the second step, we create the model classes for our app, using a separate Java source code file (with extension .java) for each model class. In the information design model shown in Figure 3.1 above, there is only one class, representing the object type Book. So, we create a file Book.java in the folder src/pl/model with the following code:

@Entity @Table( name="books")
public class Book {
  @Id private String isbn;
  private String title;
  private int year;
  // default constructor, required for entity classes
  public Book() {}
  // constructor
  public Book( String isbn, String title, int year) {
    this.setIsbn( isbn);
    this.setTitle( title);
    this.setYear( year);
  }
  // getter and setter methods
  public String getIsbn() {return isbn;}
  public void setIsbn( String isbn) {this.isbn = isbn;}
  public String getTitle() {return title;}
  public void setTitle( String title) {this.title = title;}
  public int getYear() {return year;}
  public void setYear( int year) {this.year = year;}
  // CRUD data management methods
  public static void add(...) {...}
  public static List<Book> retrieveAll(...) {...}
  public static Book retrieve(...) {...}
  public static void update(...) {...}
  public static void destroy(...) {...}
  public static void clearData(...) {...}
  public static void createTestData(...) {...}
}

Notice that the model class Book is encoded as a JPA entity class, which is a JavaBean class enriched with the following JPA annotations:

  1. The annotation @Entity designates a class as an entity class implying that the instances of this class will be stored persistently.

  2. The annotation @Table( name="books") specifies the name of the database table to be used for storing the Book entities. This annotation is optional and defaults to a table name being the same as the class name but in lower case (that is, it would be book in our case).

  3. The @Id annotation marks the standard identifier attribute, implying that the corresponding column of the underlying SQL database table is designated as the PRIMARY KEY. In our example, isbn is used as the standard identifier attribute, and the corresponding isbn column of the books table stores the primary key values.

In the entity class Book, we also define the following static (class-level) methods:

  1. Book.add for creating a new Book instance.

  2. Book.retrieveAll for retrieving all Book instances from the persistent data store.

  3. Book.retrieve for retrieving a specific Book instance from the persistent data store by means of its standard identifier.

  4. Book.update for updating an existing Book instance.

  5. Book.destroy for deleting a Book instance.

  6. Book.createTestData for creating a few example book records to be used as test data.

  7. Book.clearData for clearing the book database table.

These methods are discussed in the following sections.

The JPA architecture for data management and object-to-storage mapping is based on the concept of an entity manager, which provides the data management methods persist for saving a newly created entity, find for retrieving an entity, and remove for deleting an entity.

Since the database access operations of an entity manager are executed in the context of a transaction, our data management methods have a parameter ut of type UserTransaction. Before the entity manager can invoke the database write method persist, a transaction needs to be started with ut.begin(). After all write (and state change) operations have been performed, the transaction is completed (and all changes are committed) with ut.commit().

2.1. Storing Book objects in a database table books

The instances of our entity class Book are special Java objects representing "entities" (or business objects), which can be serialized, or, in other words, turned into database records, or rows of a database table. Consequently, they can be shown as a table like in Table 3.2.

Table 3.2. Book objects represented as a table

ISBN Title Year
006251587X Weaving the Web 2000
0465026567 Gödel, Escher, Bach 1999
0465030793 I Am A Strange Loop 2008

The data storage technology used in our example app is MySQL, and the (My)SQL code used to create the schema for the database table books is the following:

CREATE TABLE IF NOT EXISTS books (
  isbn VARCHAR(10) NOT NULL PRIMARY KEY,
  title VARCHAR(128),
  year SMALLINT
);

While it is also possible to create the database schema manually (with the help of CREATE TABLE statements such as the one above), we'll show later in this tutorial how the database schema can be automatically generated by JPA. In both cases, the database setup, including a user account and the associated rights (create, update, etc), must be done manually before the JPA application can connect to it.

2.2. Creating a new Book instance and storing it

The Book.add method takes care of creating a new Book instance and saving it to a database with the help of an 'entity manager':

public static void add( EntityManager em, UserTransaction ut, 
    String isbn, String title, int year) throws Exception {
  ut.begin();
  Book book = new Book( isbn, title, year);
  em.persist( book);
  ut.commit();
}

For storing the new object, the persist method of the given 'entity manager' is invoked. It is responsible for creating the corresponding SQL INSERT statement and executing it.

2.3. Retrieving all Book instances

The instances of an entity class, such as Book, are retrieved from the database with the help of a corresponding query expressed in the Java Persistence Query Language (JPQL). These queries are similar to SQL queries. They use class names Instead of table names, property names instead of column names, and object variables instead of row variables.

In the Book.retrieveAll method, first a query asking for all Book instances is created, and then this query is executed with query.getResultList() assigning its answer set to the list variable books:

public static List<Book> retrieveAll( EntityManager em) {
  Query query = em.createQuery( "SELECT b FROM Book b", Book.class);
  List<Book> books = query.getResultList();
  return books;
}

2.4. Updating a Book instance

For updating an existing Book instance we first retrieve it from the database with em.find, and then set those attributes the value of which has changed:

public static void update( EntityManager em, 
    UserTransaction ut, String isbn, String title, 
    int year) throws Exception {
  ut.begin();
  Book book = em.find( Book.class, isbn);
  if (!title.equals( book.getTitle())) book.setTitle( title);
  if (year != book.getYear()) book.setYear( year);
  ut.commit();
}

Notice that, when invoking the find method for retrieving an entity, the first argument must be a reference to the entity class concerned (here: Book.class), so the JPA runtime environment can identify the database table from which to retrieve the entity's data. The second argument must be the value of the entity's primary key.

Notice that in the update case, we do not have to use persist for saving the changes. Saving is automatically managed by the JPA runtime environment when we complete the transaction with ut.commit().

2.5. Deleting a Book instance

A book entity can be deleted from the database as shown in the following example code:

public static void destroy( EntityManager em, 
    UserTransaction ut, String isbn) throws Exception {
  ut.begin();
  Book book = em.find( Book.class, isbn);
  em.remove( book);
  ut.commit();
}

To delete an entity from the database, we first need to retrieve it with the help of the find method as in the update case. Then, the remove method has to be invoked by the 'entity manager', and finally the transaction is completed with ut.commit().

2.6. Creating test data

For being able to test our code, we may create some test data and save it in our database. We can use the following procedure for this:

public static void createTestData( EntityManager em, 
    UserTransaction ut) throws Exception {
  Book book = null;
  Book.clearData( em, ut);  // first clear the books table
  ut.begin();
  book = new Book("006251587X","Weaving the Web", 2000);
  em.persist( book);
  book = new Book("0465026567","Gödel, Escher, Bach", 1999);
  em.persist( book);
  book = new Book("0465030793","I Am A Strange Loop", 2008);
  em.persist( book);
  ut.commit();
}

After clearing the database, we successively create 3 instances of the Book entity class and save them with the help of persist.

2.7. Clearing all data

The following procedure clears our database by deleting all rows:

public static void clearData( EntityManager em, 
    UserTransaction ut) throws Exception {
  ut.begin();
  Query deleteStatement = em.createQuery( "DELETE FROM Book");
  deleteStatement.executeUpdate();
  ut.commit();
}

JPA does not provide a direct method to drop the entire population of a specific class from the database. However, this can be easily obtained by using a JPQL statement as shown in the above code. The JPQL code can be read as: delete all rows from the database table associated with the entity class Book.

3. Step 3 - Configure the App

In this section we show how to

  1. configure an app to connect with a database in a controller class,

  2. obtain the EntityManager and UserTransaction instances required for performing database operations,

  3. wrap an app in a WAR file and deploy it to a web server for execution.

3.1. Create the EntityManager and UserTransaction objects

A controller class contains the code that glues the views to the model, as well as all methods that do no neither belong to the model nor to the view, like getting a connection with the database server. In our example app, this class is pl.ctrl.BookController in the src/pl/ctrl folder.

JPA requires an EntityManager object for executing JPQL queries (with SELECT) and data manipulation statements (with INSERT, UPDATE and DELETE). Also, in order to perform database write operations, a UserTransaction object is required for starting and completing transactions. In a standalone application, the programmer has to create an entity manager and a transaction manually, using a factory pattern as shown in the following code fragment:

EntityManagerFactory emf = 
    Persistence.createEntityManagerFactory("MinimalApp");
EntityManager em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();

A JPA-enabled Java web application normally runs in an environment called "container" (in our case this is TomEE), which takes care of creating an EntityManager and a UserTransaction object if the right annotations are used. The code responsible for this is part of the controller class ( e.g., pl.ctrl.BookController) since the controller is responsible for managing the database connections.

public class BookController {
  @PersistenceContext( unitName="MinimalApp")
  private EntityManager em;
  @Resource() UserTransaction ut;

  public List<Book> getBooks() {...}
  public void refreshObject( Book book) {...}
  public String add( String isbn, String title, 
      int year) {...}
  public String update( String isbn, 
      String title, int year) {...}
  public String destroy( String isbn) {...}
}

A closer look at this code shows that it is sufficient to use the @PersistenceContext annotation and provide a unitName (see the next section) for obtaining an EntityManager instance at runtime. Also, obtaining a UserTransaction instance at runtime is as simple as using the @Resource annotation for the user transaction reference property ut. Not only that the required code is short and simple, but if the database type is changed (e.g. when we switch from MySQL to an Oracle database), this code remains the same.

3.2. Configure the JPA database connection

In the previous section, discussing the BookController class, we have shown how to obtain the EntityManager and UserTransaction objects required for performing database operations. The @PersistenceContext annotation of the EntityManager reference property requires a unitName, which is just a name used for identifying the storage management configuration defined in the src/META-INF/persistence.xml file. In our example app this file has the following content:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://java.sun.com/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <persistence-unit name="MinimalApp">
    <class>pl.model.Book</class>
    <properties>	
      <!-- Request auto-generation of the database schema -->
      <property name="javax.persistence.schema-generation.database.action" 
          value="create"/>
      <!-- Use the JPA annotations for creating the database schema -->
      <property name="javax.persistence.schema-generation.create-source" 
          value="metadata"/>
    </properties>
    <jta-data-source>jdbc/MinimalApp</jta-data-source>
  </persistence-unit>
</persistence>

The configuration name ("MinimalApp") is defined by the name attribute of the persistence-unit element. This is the value we have to use for the unitName property of the @PersistenceContext annotation.

The persistence-unit element has three content parts:

  1. One or more class elements, each one containing the full qualified name of an entity class of the app (like pl.model.Book in our example app).

  2. A set of configuration property elements used for providing further configuration settings.

  3. A jta-data-source element for specifying the configuration block in the config/TomEE.xml web server configuration file in the web server installation folder.

In our persistence.xml file, two configuration properties have been set:

  • javax.persistence.schema-generation.database.action, with the possible values: none (default), create, drop-and-create and drop. It specifies if the database schema is to be automatically created and additionally allows to drop the existing tables before creating the new ones (with drop or drop-and-create). .

  • javax.persistence.schema-generation.create-source, with the possible values metadata (default), script, metadata-then-script and script-then-metadata. It specifies the source of information used to create the database schema. The value metadata enforces using the JPA annotations while the value script allows using an external DDL script for defining the schema.

The jta-data-source element of our persistence.xml file refers to the Resource element with id value "MinimalApp" in the config/TomEE.xml file, which has the following content:

<?xml version="1.0" encoding="UTF-8"?>
<TomEE>
  <Resource id="MinimalApp" type="DataSource"> 
    JdbcDriver com.mysql.jdbc.Driver 
    JdbcUrl jdbc:mysql://localhost:3306/MinimalApp
    UserName MinimalApp 
    Password MinimalApp 
    JtaManaged true 
  </Resource> 
</TomEE>

The Resource element contains the information required to connect with the database (i.e. username, password, access URL and the Java class name of the connection driver).

3.3. Create the main template

The main template, called page.xhtml, is shown below. It has two sub-templates:

  1. header.xhtml defines the general header information items (such as the application name)

  2. footer.xhtml defines the general footer information items (such as a copyrights notice)

Both sub-templates are included in the main template with the help of a ui:include element. We add all three template files to the WebContent/WEB-INF/templates folder.

The content of our HTML5-compliant main template page.xhtml is the following:

<!DOCTYPE html>
<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>
    <title><ui:insert name="title">Public Library</ui:insert></title>
    <link href="#{facesContext.externalContext.requestContextPath}/resources/css/style.css" 
          rel="stylesheet" type="text/css" />
  </h:head>
  <body>
    <div id="header">
      <ui:insert name="header">
        <ui:include src="/WEB-INF/templates/header.xhtml"/>
      </ui:insert>
    </div>
    <div id="main">
      <ui:insert name="main"/>
    </div>
    <div id="footer">
      <ui:insert name="footer">
        <ui:include src="/WEB-INF/templates/footer.xhtml"/>
      </ui:insert>
    </div>
  </body>
</html>

In the code, one can see that some HTML elements are used (e.g., title, link or div) while others like h:head and ui:insert are not HTML elements, but have been defined by JSF in different namespaces. JSF is using its own head element h:head because it allows injecting special HTML code such as script elements needed for XHR (or "AJAX") messaging.

Notice that in the main template, we have a first example of an expression using JSF's Expression Language (EL). where an expression starts with # and is encapsulated between curly brackets, like #{expression}. Such an expression allows reading the value of a property of, or invoking a method on, a Java bean or a context object. In any case, the value of the expression will be inserted into the HTML generated from the template. The example in our main template is the expression #{facesContext.externalContext.requestContextPath}, which retrieves the value of the requestContextPath property of the context object facesContext.externalContext.

Our main template defines three content regions: header, main and footer. The header and footer regions are defined by sub-templates included with the help of the ui:include element.

The header.xhtml sub-template contains the following:

<div><h2>Public Library</h2></div>

The footer.xhtml sub-template contains the following::

<div>Copyright 2014-2015, Gerd Wagner and Mircea Diaconescu</div>

The main region is dynamic, and will be replaced with the content generated by a facelet template as shown below.

JSF is using the following namespaces:

  • xmlns:ui="http://java.sun.com/jsf/facelets" for the JSF Facelets Tag Library providing templating elements (like ui:define for specifying the region of a template where to inject the facelet content).

  • xmlns:h="http://java.sun.com/jsf/html" for the JSF HTML Tag Library providing JSF versions of HTML elements, which are then mapped to HTML elements. For example h:inputText, which is mapped to an HTML input element.

  • xmlns:f="http://java.sun.com/jsf/core" for the JSF Core Tag Library providing custom actions or elements that are independent of any particular render kit. For example, f:actionListener can be used to define a Java method which is executed when the user clicks a button.

  • xmlns:p="http://xmlns.jcp.org/jsf/passthrough" for using HTML attributes in JSF HTML elements and passing them through to the generated HTML. For example, with p:type in, <h:inputText p:type="number"> an HTML5 input type attribute can be created in the generated HTML: <input type="number">.

  • xmlns:c="http://java.sun.com/jsp/jstl/core" for the JSTL Core Tag Library providing all kinds of features, like dealing with loops and defining variables. For example, we can use <c:set var="isbn" value="#{book.isbn}"/> to create a variable named isbn which can then be used in the view code for conditional expressions.

  • xmlns:fn="http://java.sun.com/jsp/jstl/functions" for the JSTL Functions Tag Library providing various utility functions, such as string converters. For example, we can use fn:toUpperCase to convert a string to its uppercase representation.

3.4. Define the managed beans needed in facelets

JavaBean classes, including entity classes, can be used for creating 'managed beans' with the help of the @ManagedBean annotation, which allows defining the name of a variable for accessing the created bean in the view code, typically in an EL expression. In our example app, we want to access a Book bean as well as a BookController bean, therefore both classes have to be annotated as follows:

@Entity @Table( name="books")
@RequestScoped @ManagedBean( name="book")
public class Book { ... }

@SessionScoped @ManagedBean( name="bookCtrl")
public class BookController { ... }

Notice how a lifetime scope can be specified for a managed bean with a scope annotation. In our example the book bean is @RequestScoped, this means the instance exists as long as the HTTP request and the associated response are being processed. The bookCtrl bean is @SessionScoped, which means it is created when the session starts, and destroyed when the session is closed. Other scopes are available, but we only need these two scopes in this tutorial.

3.5. Build the WAR file and deploy it to TomEE

In this tutorial we show how to use an ANT script for generating the structure of a Java web app, and then compile the code, build the WAR file and deploy it to a TomEE web server. One may also use Eclipse (or NetBeans or other IDEs) for doing this, but for keeping it simple we use ANT. Our ANT script generates a folder structure, which is compatible with Eclipse, so in case you want to use Eclipse, you may simply create an Eclipse project from the existing application code.

The purpose of this section is only to show you how to use our ANT script for making your life easier. It is not intended to be an ANT tutorial, so we don't get into specific ANT details. The following ANT tasks are defined in the script:

create app -Dappname=yourAppName -Dpkgname=yourAppPackageName

allows creating the folder structure. Instead of yourAppName and yourAppPackageName you have to provide your app's name and its package name. In our example app, we invoke the task with ant create app -Dappname=publicLibrary -Dpkgname=pl.

The script creates the folder structure, as well as the required files src/META-INF/persistence.xml, WEB-INF/faces-config.xml and WEB-INF/web.xml. The parameter yourAppPackageName is used to create the Java top level packages. If omitted, yourAppName is used as Java top package name instead. For the next tasks/commands you have to be sure that the ANT script file is located in the same folder as your web application folder (and not one level deeper in the web application folder). This way, one can use the same ANT script for building multiple web applications.

Using the optional parameter, -Dforce=true will overwrite an existing application by first deleting the existing application folder.

Hint: a JPA/JSF application requires a set of libraries to run. The ANT script looks for the jar files in a folder named lib located on the same folder as the script itself. The location of the jar files can be modified by editing the ANT script and setting the lib.folder parameter to the right folder on your computer. You can download the dependency JAR files with the link provided at the end of this tutorial.

build war -Dappname=yourAppName

allows building the WAR file by using yourAppName as file name. The resulting WAR file will be in the same folder as the ANT script file. For our example app we use the following command:

ant war -Dappname=publicLibrary

Hint: before being able to use this command, you have to edit the ANT script and modify the value of the server.folder parameter so it points to your TomEE installation folder. In case that you get compilation errors, try to copy the mysql-connector-java-xxxx-bin.jar file to the lib folder of your TomEE installation folder. This file and some other dependency files are provided in a ZIP archive that can be downloaded with the link provided at the end of this tutorial.

deploy -Dappname=yourAppName

allows deploying the WAR file associated with yourAppName to the TomEE web server. It automatically executes the build war -Dappname=yourAppName command, which means the WAR file is built before the deploy. The location of the deploy folder is detected by using the server.folder property, by appending the webapps folder name. For our example app we invoke the following command: ant deploy -Dappname=publicLibrary.

Hint: we do not recommend using spaces in folder names, but if for any reason, the application name needs to contain spaces, then it has to be enclosed in double quotes, e.g. create app -Dappname="Hellow World".

4. Step 4 - Implement the Create Use Case

The Create use case involves creating a new object in main memory and then saving it to persistent storage with the help of the add method.

The corresponding add action method code from the src/pl/ctrl/BookController.java is shown below:

public class BookController {
  ...
  public String add( String isbn, String title, int year) {
    try {
      Book.add( em, ut, isbn, title, year);
      // clear the form after saving the Book record
      FacesContext fContext = FacesContext.getCurrentInstance();
      fContext.getExternalContext().getRequestMap().remove("book");
    } catch ( Exception e) {
      e.printStackTrace();
    } 
    return "create";
  }
}

The BookController::add action method invokes the Book.add model class method for creating and saving a Book instance. It returns the name of the view file found in the same folder as the view that triggered the action. This file (create.xhtml in our case) will be displayed after executing the action. In lines 5 and 6 above, using a FacesContext object, the form is cleared after creating a Book instance. The code of the add method in src/pl/model/Book.java is the following:

public class Book {
  ...
  public static void add( EntityManager em, UserTransaction ut,
      String isbn, String title, int year) throws Exception {
    ut.begin();
    Book book = new Book( isbn, title, year);
    em.persist( book);
    ut.commit();
  }
}

Now we need to create the facelet template for the view of the Create use case, WebContent/views/books/create.xhtml. Such a facelet template essentially defines a HTML form with data binding and action binding.

Data binding refers to the binding of model class properties to form (input or output) fields. For instance, in the following facelet code fragment, the entity property book.isbn is bound to the form input field "isbn":

<h:outputLabel for="isbn" value="ISBN: " />
<h:inputText id="isbn" value="#{book.isbn}" />

In JSF, for the inputText elements of a form, the id attribute is used with a given value, e.g., id="isbn". The rendered HTML5 input elements have both, the id and the name attributes, and their values are obtained by using the form id and element id values separated by a colon, i.e., id="createBookForm:isbn" and name="createBookForm:isbn".

Action binding refers to the binding of method invocation expressions to actionable UI elements, where the invoked methods typically are controller action methods, and the actionable UI element typically are form buttons. For instance, in the following facelet code fragment, the method invocation expression bookCtrl.add(...) is bound to the form's submit button:

<h:commandButton value="Create" 
    action="#{bookCtrl.add( book.isbn, book.title, book.year)}"/>

After discussing data binding and action binding, it's time to look at the complete code of the facelet template:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="..."
      xmlns:h="..." xmlns:p="...">
  <ui:composition template="/WEB-INF/templates/page.xhtml">
    <ui:define name="main">
      <h:form id="createBookForm">
        <h:panelGrid columns="2">
          <h:outputLabel for="isbn" value="ISBN: " />
          <h:inputText id="isbn" value="#{book.isbn}" />
          <h:outputLabel for="title" value="Title: " />
          <h:inputText id="title" value="#{book.title}" />
          <h:outputLabel for="year" value="Year: " />
          <h:inputText id="year" p:type="number" value="#{book.year}" />
        </h:panelGrid>
        <h:commandButton value="Create" 
            action="#{bookCtrl.add( book.isbn, book.title, book.year)}"/>
      </h:form>
      <h:button value="Main menu" outcome="index" />
    </ui:define>
  </ui:composition>
</html>

This facelet replaces the main region of the template defined in page.xhtml, because the name attribute of the ui:define element has been set to "main".

h:outputLabel elements can be used for creating form field labels, while h:inputText elements are used for creating HTML input elements. It is possible to specify a HTML5 type of an input element by using a special namespace prefix (xmlns:p="http://xmlns.jcp.org/jsf/passthrough") for the type attribute, enforcing it to be 'passed through'. In this way the year input field can be defined with type number, so it's rendered by the corresponding number widget in the browser.

The h:commandButton element allows creating submit buttons rendered as a input elements with type="submit", and binding them to an action to be performed when the button is clicked. The value of the action attribute is a method invocation expression. In our Create use case we want that, when the button is clicked, a Book instance with the property values provided by corresponding form fields is created and saved.

5. Step 5 - Implement the Retrieve/List All Use Case

This use case corresponds to the "Retrieve/Read" from the four basic data management use cases Create-Retrieve-Update-Delete (CRUD).

First of all, for the list objects use case we have to add a method in the controller class (src/pl/ctrl/BookController.java file), which reads all the Book records from the books database table and then delivers this information to the view. The controller action method code is shown below:

public class BookController {
  ...
  public List<Book> getBooks() {
    return Book.retrieveAll( em);
  }
  ...
}

The getBooks method returns a list of Book instances which are obtained by calling the static retrieveAll method of the Book model class. The code of the Book.retrieveAll method is:

public class Book {
  ...
  public static List<Book> retrieveAll( EntityManager em) {
    Query query = em.createQuery( "SELECT b FROM Book b");
    List<Book> books = query.getResultList();
    return books;
  }
  ...
}

The code is simple, and as already discussed in Section 2.3, it uses a JPQL statement to retrieve the Book records from the books table and create the corresponding Book instances. The EntityManager object required for being able to perform the JPQL query is passed to Book.retrieveAll from the BookController object as discussed in Section 3.1 section.

Now, it is the time to define the facelet template for displaying a table with all book records found in the database. The view template files corresponding to the model classes of our app are located in model class subfolders of the WebContent/views/ folder. For the Retrieve/list all books use case, we create a file named listAll.xhtml in WebContent/views/books/ with the following content:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="..."
      xmlns:h="..." xmlns:f="...">
  <ui:composition template="/WEB-INF/templates/page.xhtml">
    <ui:define name="main">
      <h:dataTable value="#{bookCtrl.books}" var="b">
        <h:column>
          <f:facet name="header">ISBN: </f:facet>
          #{b.isbn}
        </h:column>
        <h:column>
          <f:facet name="header">Title: </f:facet>
          #{b.title}
        </h:column>
        <h:column>
          <f:facet name="header">Year: </f:facet>
          #{b.year}
        </h:column>
      </h:dataTable>
      <h:button value="Main menu" outcome="index" />
    </ui:define>
  </ui:composition>
</html>

The ui:composition element specifies which template is applied (i.e. template="/WEB-INF/templates/page.xhtml") and which view block (<ui:define name="main">) is replaced by this facelet at render time.

The h:dataTable element defines a table view for a set of records, which is then rendered as an HTML table. Its value attribute defines a data binding to a record collection, while the var attribute defines a variable name for iteratively accessing records from this collection. The expression provided in the value attribute normally specifies a collection-valued property (here: books) which is accessed via a corresponding getter (here: getBooks) as defined in the controller class BookController. In this particular case it is just sufficient to define the getBooks method since there is no need of a books property in the controller class. In any case, value does not allow to invoke a method, so we cannot call getBooks directly. Instead we have to use the (possibly virtual) property books, which internally evaluates to a call of getBooks without checking if a books property really exists.

The h:button JSF element allows to create redirect buttons. The value of the outcome attribute specifies a name of a JSF view file by omitting the .xhtml extension (i.e. the view file name is index.xhtml).

6. Step 6 - Implement the Update Use Case

Like for the Create use case, a controller action method is defined in the BookController class:

public class BookController {
  ...
  public String update( String isbn, String title, int year) {
    try {
      Book.update( em, ut, isbn, title, year);
    } catch ( Exception e) {
      e.printStackTrace();
    } 
    return "update";
  }
  ...
}

The Book.update takes care of saving property value changes for a book object identified by its isbn value as shown below:

public class Book {
  ...
  public static void update( EntityManager em, UserTransaction ut,
      String isbn, String title, int year) throws Exception {
    ut.begin();
    Book book = em.find( Book.class, isbn);
    if (title != null && !title.equals( book.title)) {
      book.setTitle( title);
    }
    if (year != book.year) {
      book.setYear( year);
    }
    ut.commit();
  }
  ...
}

Now, we create the view where a Book can be selected so the user can edit the title and year properties, and then save the changes. The code for this view is stored in the WebContent/views/books/update.xhtml file which has the following content:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="..."
      xmlns:h="..." xmlns:f="..." xmlns:p="...">
  <ui:composition template="/WEB-INF/templates/page.xhtml">
    <ui:define name="main">
      <h:form id="updateBookForm">
        <h:panelGrid columns="2">
          <h:outputLabel for="selectBook" value="Select book: " />
          <h:selectOneMenu id="selectBook" value="#{book.isbn}">
            <f:selectItem itemValue="" itemLabel="---" />
            <f:selectItems value="#{bookCtrl.books}" var="b" 
                itemValue="#{b.isbn}" itemLabel="#{b.title}" />
            <f:ajax listener="#{bookCtrl.refreshObject( book)}" 
             render="isbn title year"/>
          </h:selectOneMenu>
          <h:outputLabel for="isbn" value="ISBN: " />
          <h:outputText id="isbn" value="#{book.isbn}" />
          <h:outputLabel for="title" value="Title: " />
          <h:inputText id="title" value="#{book.title}" />
          <h:outputLabel for="year" value="Year: " />
          <h:inputText id="year" p:type="number" value="#{book.year}" />
        </h:panelGrid>
        <h:commandButton value="Update" 
            action="#{bookCtrl.update( book.isbn, book.title, book.year)}"/>
      </h:form>
      <h:button value="Main menu" outcome="index" />
    </ui:define>
  </ui:composition>
</html>

In this facelet template, a single selection list (that is, a single-select HTML element) is created with the help of the JSF element h:selectOneMenu, where the selection list items (the HTML option elements) are defined by the JSF elements f:selectItem or f:selectItems. The value attribute of h:selectOneMenu binds book.isbn to the value of the selected item (or option element). The selection list is populated with book records with the help of a f:selectItems element bound to bookCtrl.books. The attributes itemLabel and itemValue define the option elements' text and value.

In the update view, when the user selects a book from the selection list, the form fields are filled with the (ISBN, title and year) property values of the selected book. While the ISBN is immediately available in the view (on the front-end) as the value of the selected option element, the values of the title and year properties have to be fetched from the back-end database. This can be done with the help of the JSFelement f:ajax, which performs an XHR request for invoking a remote method, bookCtrl.refreshObject, on the back-end. This method takes the managed book bean, and updates its title and year properties with the current values retrieved from the database. Its code is the following:

public class BookController {
  ...
  public void refreshObject( Book book) {
    Book foundBook = Book.retrieve( em, book.getIsbn());
    book.setTitle( foundBook.getTitle());
    book.setYear( foundBook.getYear());
  }
  ...
}

To enforce a refresh of the form after the user's selection, such that it displays the values of isbn, title and year, the f:ajax element allows specifying form fields to be updated with the render attribute like, in our case, render="isbn title year".

Finally, the h:commandButton element is used for invoking the update action method of the BookController with the parameters isbn, title and year, for making the changes persistent.

7. Step 7 - Implement the Delete Use Case

The destroy action method of the BookController invokes the Book.destroy method by providing the ISBN of the Book object to be deleted:

public class BookController {
  ...
  public String destroy( String isbn) {
    try {
      Book.destroy( em, ut, isbn);
    } catch ( Exception e) {
      e.printStackTrace();
    } 
    return "delete";
  }
  ...
}

The Book.destroy method first retrieves the Book object to be deleted, and then invokes the entity manager's remove method on it:

public class Book {
  ...
  public static void destroy( EntityManager em, UserTransaction ut, String isbn) 
      throws Exception, HeuristicRollbackException, RollbackException {
    ut.begin();
    Book book = em.find( Book.class, isbn);
    em.remove( book);
    ut.commit();
  }
  ...
}

The view for the Delete action provides a selection list for selecting the book to be deleted. A "Delete" button allows performing the deletion of the selected book. The code of the view in WebContent/views/books/delete.xhtml is as follows:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="..." xmlns:h="..." xmlns:f="...">
  <ui:composition template="/WEB-INF/templates/page.xhtml">
    <ui:define name="main">
      <h:form id="deleteBookForm">
        <h:panelGrid columns="2">
          <h:outputText value="Select book: " />
          <h:selectOneMenu value="#{book.isbn}">
            <f:selectItems value="#{bookCtrl.books}" var="b" 
                itemValue="#{b.isbn}" itemLabel="#{b.title}" />
          </h:selectOneMenu>
        </h:panelGrid>
        <h:commandButton value="Delete" 
            action="#{bookCtrl.destroy( book.isbn)}"/>
      </h:form>
      <h:button value="Main menu" outcome="index" />
    </ui:define>
  </ui:composition>
</html>

As in the Update use case, a h:selectOneMenu element is used to create and populate a selection list containing all the books to choose from. Clicking on the "Delete" command button results in invoking the destroy action method of the controller with the isbn value of the selected book, thus resulting in the deletion of the Book object from the database.

8. Run the App and Get the Code

You can run the minimal app on our server or download the code as a ZIP archive file.

For running the minimal app on your computer, first download the code and edit the ANT script file by modifying the server.folder property value as described in Section 3.5. You may then have to stop your Tomcat/TomEE server with bin/shutdown.bat for Windows or bin/shutdown.sh for Linux. Now execute the following command on your console or terminal: ant deploy -Dappname=MinimalApp. Last, start your Tomcat web server (by using bin/startup.bat for Windows OS or bin/startup.sh for Linux). Please be patient, this can take some time depending on the speed of your computer. It will be ready when the console displays the following info: INFO: Initializing Mojarra [some library versions and paths are shown here] for context '/MinimalApp'. Finally, open your favorite browser and type: http://localhost:8080/MinimalApp/faces/views/books/index.xhtml

For new projects, you may want to download the dependency libaries.

9. Possible Variations and Extensions

9.1. Accessibility for Web Apps

The recommended approach to providing accessibility for web apps is defined by the Accessible Rich Internet Applications (ARIA) standard. As summarized by Bryan Garaventa in his article on different forms of accessibility, there are 3 main aspects of accessibility for interactive web technologies: 1) keyboard accessibility, 2) screen reader accessibility, and 3) cognitive accessibility.

Further reading on ARIA:

9.2. Using resource URLs

Whenever an app provides public information about entities, such as the books available in a public library, it is desirable to publish this information with the help of self-descriptive resource URLs, such as http://publiclibrary.norfolk.city/books/006251587X, which would be the resource URL for retrieving information about the book "Weaving the Web" available in the public library of Norfolk. However, resource URLs are not supported by JSF. In the Java world, we would have to use JAX-RS, instead of JSF, for programming a web API with resource URLs. But this would imply that we need to take care of the front-end UI in a different way, since JAX-RS is a pure back-end API, not providing any UI. A natural option would be to use a JavaScript front-end framework, such as BackboneJS or AngularJS, for rendering the UI.

9.3. Dealing with date/time information using Date and <time>

Assume that our Book model class has an additional attribute publicationDate, the values of which have to be included in HTML tables and forms. While date/time information items have to be formatted as strings in a human-readable form on web pages, preferably in a 'localized' form based on the 'locale' setting of the user's browser, it's preferable to store and manipulate date/time values in the Java code not in this form, but rather as instances of the pre-defined Java datatype class Date. For example, a date attribute publicationDate could be defined like so:

public class Book {
  ...
  private Date publicationDate;
  ...
}

For creating an HTML form input field for a Date-valued attribute, we can use the JSF element h:inputText with the attribute p:type="date". This creates an HTML input element with type="date". For our example attribute, publicationDate, the following JSF template could be used:

<h:form id="createBookForm">
  ...
  <h:inputText id="publicationDate" p:type="date"  
     value="#{book.publicationDate}">
    <f:convertDateTime pattern="yyyy-MM-dd" />
  </h:inputText>
  ...
</h:form>

With JSF one can use the built-in f:convertDateTime converter to specify an output pattern for the date format (rendered HTML output value). In the above example, we specify four digits for year representation, two digits for month and two digits for day (e.g., 2015-07-23).

From this template the following HTML code is generated:

<input id="createBookForm:publicationDate" 
  name="createBookForm:publicationDate" type="date">

Notice that the intended meaning of the HTML5 input field type "date" is for the browser to render a calendar date input widget such as a date picker. But such a rendering of date input elements is still not provided by all browsers. We therefore recommend trying this with the Chrome browser.

9.4. Using an alternative DBMS

Instead of MySQL, one can use various other database management systems for persistent storage. The following four steps are required to specify the used DBMS (only one DBMS at a time is possible):

  • configure TomEE/Tomcat so it uses the corresponding resource for your application. For a list of resource configuration examples used for common DBMS check http://tomee.apache.org/common-datasource-configurations.html. For example, if PostgreSQL was chosen as DBMS, then edit the conf/tomee.xml file (part of the TomEE installation) and add the following code:

    <Resource id="application-persistence-unit-name" type="DataSource">
      JdbcDriver   org.postgresql.Driver
      JdbcUrl  jdbc:postgresql://host/database-name
      UserName     dbms-username
      Password     user-password
    </Resource>
  • copy the jar file corresponding to the DBMS driver implementation to lib folder (part of the TomEE/Tomcat installation). After this operation, the TomEE/Tomcat server needs to be restarted.

  • Install the DBMS, if not already installed. Installation instructions are usually available on the corresponding DBMS web page.

  • create the corresponding DBMS user and database to be used for your application.

10. Points of Attention

The code of this app should be extended by

  • adding some CSS styling for the user interface pages and

  • adding constraint validation.

We show how to do this in the follow-up tutorial Building Java Web Apps Tutorial Part 2: Adding Constraint Validation.

We briefly discuss further points of attention.

10.1. Code clarity

Any damn fool can write code that a computer can understand, the trick is to write code that humans can understand. (Martin Fowler in After the Program Runs)

Code is often "unnecessarily complicated, convoluted, disorganized, and stitched together with disdain", as observed in a post by Santiago L. Valdarrama who recommends using comments when necessary, only to explain things that can't be made clear enough, but rather make your code reveal its intention through the use of better names, proper structure, and correct spacing and indentation.

10.2. Boilerplate code

Another issue with the code of this Java example app is the repetitious boilerplate code needed per entity class for the storage management methods add, retrieve, update and destroy, and their wrappers in the corresponding controller classes. While it may be instructive to write this code a few times for learning app development, you don't want to write it again and again later when you work on real projects.

10.3. Offline availability

It is desirable that a web app can still be used when the user is offline. However, this is not possible in the case of a back-end application architecture as implied by JSF.

10.4. Architectural separation of concerns

One of the most fundamental principles of software architecture is separation of concerns. This principle is also the basis of the Model-View-Controller (MVC) architecture paradigm. It requires to keep the different functional parts of a software application independent of each other as much as possible. More specifically, it implies to keep the app's model classes independent of

  1. the user interface (UI) code because it should be possible to re-use the same model classes with different UI technologies;

  2. the storage management code because it should be possible to re-use the same model classes with different storage technologies.

In this tutorial, we have kept the model class Book independent of the UI code, since it does not contain any references to UI elements, nor does it invoke any view method. However, for simplicity, we didn't keep it independent of storage management code, since we have used JPA annotations, which bind the class to JPA object-to-storage mapping technology, and we have included the method definitions for add, update, destroy, etc., which invoke the storage management methods of a JPA environment's entity manager. Therefore, the separation of concerns is incomplete in our minimal example app.

We will show in a follow-up tutorial how to achieve a more complete separation of concerns.

11. Practice Projects

If you have any questions about how to carry out the following projects, you can ask them on our discussion forum.

11.1. Develop a Java back-end web app for Managing Movie Data

The purpose of the app to be developed is managing information about movies.

The app deals with just one object type: Movie, as depicted in Figure 3.2 below. In the subsequent parts of the tutorial, you will extend this simple app by adding integrity constraints, enumerations, further model classes for actors and directors, and the associations between them.

Notice that in most parts of this project you can follow, or even copy, the code of the book data management app, except that in the Movie class there is an attribute with range Date, so you have to use the HTML <time> element in the list objects table, as discussed in Section 9.3.

Figure 3.2. The object type Movie.

The object type Movie.

For developing the app, simply follow the sequence of seven steps described in the tutorial:

  1. Step 1 - Set up the Folder Structure

  2. Step 2 - Write the Model Code

  3. Step 3 - Initialize the Application

  4. Step 4 - Implement the List Objects Use Case

  5. Step 5 - Implement the Create Object Use Case

  6. Step 6 - Implement the Update Object Use Case

  7. Step 7 - Implement the Delete Object Use Case

You can use the following sample data for testing:

Table 3.3. Sample data

Movie ID Title Release date
1 Pulp Fiction 1994-05-12
2 Star Wars 1977-05-25
3 Casablanca 1943-01-23
4 The Godfather 1972-03-15


Make sure that

  1. your HTML pages comply with the XML syntax of HTML5,

  2. international characters are supported by using UTF-8 encoding for all HTML files,

  3. your JavaScript code complies with our Coding Guidelines and is checked with JSLint (http://www.jslint.com); it must pass the JSLint test (e.g. instead of the unsafe equality test with "==", always the strict equality test with "===" has to be used).

Glossary

C

CRUD

CRUD is an acronym for Create, Read/Retrieve, Update, Delete, which denote the four basic data management operations to be performed by any software application.

D

Document Object Model

An abstract API for retrieving and modifying nodes and elements of HTML or XML documents. All web programming languages have DOM bindings that realize the DOM.

Domain Name System

The DNS translates user-friendly domain names to IP addresses that allow to locate a host computer on the Internet.

E

ECMAScript

A standard for JavaScript defined by the industry organization "Ecma International".

Extensible Markup Language

XML allows to mark up the structure of all kinds of documents, data files and messages in a machine-readable way. XML may also be human-readable, if the tag names used are self-explaining. XML is based on Unicode. SVG and MathML are based on XML, and there is an XML-based version of HTML.

XML provides a syntax for expressing structured information in the form of an XML document with elements and their attributes. The specific elements and attributes used in an XML document can come from any vocabulary, such as public standards or user-defined XML formats.

H

Hypertext Markup Language

HTML allows marking up (or describing) the structure of a human-readable web document or web user interface. The XML-based version of HTML, which is called "XHTML5", provides a simpler and cleaner syntax compared to traditional HTML.

Hypertext Transfer Protocol

HTTP is a stateless request/response protocol based on the Internet technologies TCP/IP and DNS, using human-readable text messages for the communication between web clients and web servers. The main purpose of HTTP has been to allow fetching web documents identified by URLs from a web browser, and invoking the operations of a back-end web application program from a HTML form executed by a web browser. More recently, HTTP is increasingly used for providing web APIs and web services.

I

IANA

IANA stands for Internet Assigned Numbers Authority, which is a subsidiary of ICANN responsible for names and numbers used by Internet protocols.

ICANN

ICANN stands for Internet Corporation of Assigned Names and Numbers, which is an international nonprofit organization that maintains the domain name system.

IndexedDB

A JavaScript API for indexed data storage managed by browsers. Indexing allows high-performance searching. Like many SQL DBMS, IndexedDB supports database transactions.

I18N

A set of best practices that help to adapt products to any target language and culture. It deals with multiple character sets, units of measure, keyboard layouts, time and date formats, and text directions.

J

JSON

JSON stands for JavaScript Object Notation, which is a data-interchange format following the JavaScript syntax for object literals. Many programming languages support JSON as a light-weight alternative to XML.

M

MathML

An open standard for representing mathematical expressions, either in data interchange or for rendering them within webpages.

MIME

A MIME type (also called "media type" or "content type") is a keyword string sent along with a file for indicating its content type. For example, a sound file might be labeled audio/ogg, or an image file image/png.

P

PNG

PNG stands for Portable Network Graphics, which is a open (non-proprietary) graphics file format that supports lossless data compression.

Polyfill

A polyfill is a piece of JavaScript code for emulating a standard JavaScript method in a browser, which does not support the method.

R

RDF

RDF stands for Resource Description Framework, which is a W3C language for representing machine-readable propositional information on the web.

S

SGML

SGML stands for Standard Generalized Markup Language, which is an ISO specification for defining markup languages. HTML4 has been defined with SGML. XML is a simplified successor of SGML. HTML5 is no longer SGML-based and has its own parsing rules.

SVG

SVG stands for Scalable Vector Graphics, which is a 2D vector image format based on XML. SVG can be styled with CSS and made interactive using JavaScript. HTML5 allows direct embedding of SVG content in an HTML document.

U

Unicode

A platform-independent character set that includes almost all characters from most of the world's script languages including Hindi, Burmese and Gaelic. Each character is assigned a unique integer code in the range between 0 and 1,114,111. For example, the Greek letter π has the code 960. Unicode includes legacy character sets like ASCII and ISO-8859-1 (Latin-1) as subsets.

XML is based on Unicode. Consequently, the Greek letter π (with code 960) can be inserted in an XML document as &#960; using the XML entity syntax. The default encoding of Unicode characters in an XML document is UTF-8, which uses only a single byte for ASCII characters, but three bytes for less common characters.

URI

URI stands for Uniform Resource Identifier, which is either a URL or a URN.

URL

URL stands for Uniform Resource Locator, which is a resource name that contains a web address for locating the resource on the web.

URN

URN stands for Uniform Resource Name, which refers to a resource without specifying its location.

User Agent

A user agent is a front-end web client program such as a web browser.

W

WebM

WebM is an open (royatly-free) web video format supported by Google Chrome and Mozila Firefox, but not by Microsoft Internet Explorer and Apple Safari.

WHATWG

The Web Hypertext Application Technology Working Group (WHATWG) was established in 2004 by former employees of Apple, Mozilla, and Opera who have been unhappy with the slow progress of web technology standardization due to W3C's choice to focus on the standardization of XHTML2. Led by Ian Hickson, they developed HTML5 and related JavaScript APIs in competition and collaboration with the W3C.

World Wide Web

The WWW (or, simply, "the web") is a huge client-server network based on HTTP, HTML and XML, where web browsers (and other 'user agents'), acting as HTTP clients, access web server programs, acting as HTTP servers.

W3C

W3C stands for World Wide Web Consortium, which is an international organization in charge of developing and maintaining web standards.