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 = 
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" 
  <persistence-unit name="MinimalApp">
      <!-- Request auto-generation of the database schema -->
      <property name="javax.persistence.schema-generation.database.action" 
      <!-- Use the JPA annotations for creating the database schema -->
      <property name="javax.persistence.schema-generation.create-source" 

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"?>
  <Resource id="MinimalApp" type="DataSource"> 
    JdbcDriver com.mysql.jdbc.Driver 
    JdbcUrl jdbc:mysql://localhost:3306/MinimalApp
    UserName MinimalApp 
    Password MinimalApp 
    JtaManaged true 

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

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".