Developing Web applications with the Java Persistence API and JavaServer Faces

How Rational Application Developer Version 7.5 makes it easier to build JPA Web applications

The Java™ Persistence API (JPA) provides an easy mechanism to use with relational databases when you need applications to persist data. Although it is traditionally used with Enterprise Java™Beans (EJBs), JPA works quite well directly with Web applications. This article describes the simplified programming model and tools that IBM® Rational® Application Developer for WebSphere® Software Version 7.5 provides for easily building Web applications that use JPA. Note: This article is based on Rational Application Developer v7.5 Open Beta.

Share:

Thomas F Mutdosch (mutdosch@us.ibm.com), Advisory Software Engineer, Systems Documentation, Inc. (SDI)

  Thomas MutdoschThomas has worked on Web and data tooling at IBM for the last seven years, focusing largely on providing data access for Web applications. He has worked extensively on creating tools for developing Service Data Object (SDO) and JPA applications for Rational Application Developer.



19 August 2008

Also available in Chinese

The Java™ Persistence API (JPA) is a specification for the persistence of Java model objects with a relational database. This article gives you an overview of JPA, shows how it operates in a Web application environment, and explains how you can use Rational Application Developer Version 7.5 to build JPA Web applications by using Java™Server Faces (JSF).

An overview of JPA

JPA is a simplified programming model used for object relational mapping and data persistence. Data persistence ensures that applications that retrieve and update data are kept in sync with the current state of the back-end database. Traditionally, this was done using Java Database Connectivity (JDBC) APIs and other data frameworks, which were cumbersome and usually involved writing complex query statements to add or modify data.

JPA simplifies this process by using Java representations of your database tables, called entities, and providing a set of APIs to persist and query your data.

Entities

Entity objects are the primary model used in JPA applications. An entity is a POJO (Plain Old Java Object) that models a table in a database. It contains attributes that correspond to the table columns, and it allows applications to interact directly with a conceptual model of the database.

Example
There is a database table named Department containing a column named deptname. In the application, there is a corresponding Java class named Department, and it contains a field named deptname, along with the appropriate get and set methods. It's that simple. Figure 1 shows the entire Department table, along with the corresponding entity class.
Figure 1. Department table and entity
Columns listed on left, classes on right

Information mapping an entity and a relational database, such as identifying primary keys and relationships, can be specified directly in an entity class by using Java annotations. Optionally, these mappings can also be specified in a separate mapping configuration file. JPA uses commonsense default values for the metadata mappings whenever possible. This eliminates a lot of boilerplate code and extraneous mapping information from your application. For example, an entity class named Department is assumed to map to a database tabled named Department. There is no need to explicitly define the mapping by using an annotation or the configuration file unless you need to override the default value.

Retrieving and persisting data

JPA provides an API for managing and persisting the entities in your applications. The EntityManager class is used to retrieve, persist, update, and delete entities. In a JPA application, you always deal directly with entity objects and do not have to write any of the underlying JDBC code to insert or update database rows.

To add a new row to your table, you simply create an instance of your entity class, set the attributes, and tell the EntityManager to persist the new entity. Updating and deleting existing data is just as easy.

JPA provides the Java Persistence Query Language (JPQL) to query the database and retrieve data. JPQL is a full-featured query language with syntax similar to SQL, but it operates on entities rather than database tables.

JPQL query example
SELECT d FROM Department d ORDER BY d.deptNo

This query can be passed into the Entity Manager to retrieve a list of all Department entities, ordered by their department number.

JPA in a Web container

JPA was originally proposed as part of the EJB 3.0 specification, but it was separated as an independent specification, thus allowing other domains to take advantage of its benefits. This means that JPA can be used inside any Java EE environment, such as in a Web container, or even a stand-alone Java SE application. You will get all of the benefits of JPA and the ease of use that it provides no matter what environment you prefer.

Resource injection

Another mechanism used to simplify programming tasks in Java Enterprise Edition 5 (Java EE) applications is resource injection. Through the use of annotations, it is possible to have a Java EE container inject resources, such as data sources, Web services, and EJBs, directly into your code. This eliminates the need for you to write the code normally required to handle such tasks.

Not all Web container components support resource injection. You cannot use it directly inside of a JSP page, for instance. These Web components support resource injection:

  • Servlets
  • Servlet filters and listeners
  • Taglib tag handlers
  • JavaServer Faces Managed Beans

The sample application described later in this article will use resource injection in JavaServer Faces Managed Beans.

JPA in Rational Application Developer

Rational Application Developer provides a variety of tools to aid in JPA development. You can use editors, property views, and visual modeling diagrams to create and edit JPA entity classes. This article focuses on the visual tooling used to help easily integrate JPA into a Web application.

Rational Application Developer provides wizards that allow developers to easily complete many of the tasks that would otherwise be time-consuming and error-prone if done in a text editor.

Tools for visually configuring JPA-related data:

  • JPA entity-creation wizard, which uses a target database schema
  • Visual configuration of JPA entities
    • Set primary keys
    • Set concurrency
    • Add and delete relationships between entities
    • Add and configure Named Queries
  • Visual JPQL query builder
    • Easily add filters for your queries
    • Order your results
    • Write custom queries to retrieve individual columns or to return results in a user-specified Java class
  • Add and configure JPA Manager Beans
  • Automatically set up your JPA application for runtime deployment
    • Sets up appropriate JPA configuration files
    • Creates an IBM WebSphere Application Server data source automatically
  • Refactoring support for relationships and named queries
  • Validation and quick fixes

When you have your JPA model in place, there are additional tools that are available that make your job easier, as the next list shows.

Tools for adding JPA data to Web pages:

  • Palette and Page Data views where you can add JPA data to your page
  • A facade pattern provided by JPA Manager Beans, which is used in a service approach
  • Tools to easily switch the queries used by those pages without touching the Web page code (after your Web pages have accessed JPA data)
  • Tools to add JSF converters for complex JPA entities and to create different UI controls for relationship fields

Adding JPA data to Web pages

Using JPA directly inside of a Web application is easy, and this is a nice option if you are familiar with two-tier Web application programming or if you do not need the complexity of EJBs. The JPA specification does not require entities to be packaged inside of Java Archives, or JARs (as they must be within an EJB environment); therefore, the JPA entity classes can be loose in your Web application. This fits naturally with the traditional Web application model.

JPA Manager Beans

Purpose of JPA Manager Beans

JPA Manager Beans are a concept introduced by Rational Application Developer and are not part of the JPA specification. They are used to provide an easy programming model and to handle the JPA-specific persistence tasks for you.

Rational Application Developer V7.5 introduces the concept of JPA Manager Beans, which are service beans that act as facades or controllers over a particular JPA entity. They encapsulate and abstract all of the data access code for creating, updating, deleting, and displaying information from your database, using JPA entities.

JPA Manager Beans are an ideal programming model for use in two-tier Web environments. They fill the role that would normally be filled by a session bean in an EJB environment; all of the business logic related to an entity is performed by the JPA Manager Bean.

JPA Manager beans map one-to-one to a JPA entity. For example, if you have a Department entity, the tools provided in Rational Application Developer V7.5 can be used to create a JPA Manager Bean named DepartmentManager, which contains all of the data access logic needed to work with that entity (Figure 2).

Figure 2. DepartmentManager default methods
Screen capture of list of methods

Use of JPA Manager Beans is not limited to Web applications. They can be used anywhere that you want to take advantage of their data abstraction capabilities, such as an EJB project, a JPA Utility project, or even a plain Java project. Even if your JPA entities exist in a JPA Utility project or an EJB project, you can still generate JPA Manager Beans for those entities inside your Web project.

Integration with JSF

JPA integrates well with JSF Web applications. JPA entities are a natural fit to be used as the data-binding model required for most JSF components. You can easily bind an entity to an input form for a creation or update scenario or bind a list of entities to a JSF data grid if you want to display information in a table.

Using JPA Manager Beans as a programming model

The service-oriented nature of JPA Manager Beans makes them easy to integrate into service-oriented architecture (SOA) environments, as is common with a well-designed Web application. In such an environment, a Web application interfaces directly with a JPA Manager Bean. The Manager Bean then handles the logic for retrieving and updating entities by calling the appropriate JPA APIs to interface with the backend database (Figure 3). This programming model enables you to focus solely on the business logic of your application, without getting bogged down by the details of the persistence mechanism.

Figure 3. Example application flow
diagram

When using JSF technology, you can register your JPA Manager beans as JavaServer Faces-managed beans and access them directly from your Web application. In the following example, the Faces configuration file (/WEB-INF/faces-config.xml) contains a managed bean, DepartmentManager, in the request scope (see Figure 4 and Listing 1).

Figure 4. JPA Manager Bean defined as a Managed Bean
Managed Bean screen element with 3 fields
Listing 1. Code that defines Managed Bean
        <managed-bean>
        <managed-bean-name>departmentManager</managed-bean-name>
        <managed-bean-class>entities.controller.DepartmentManager</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        </managed-bean>

This enables you to use the DepartmentManager bean from anywhere in your application; you don't have to worry about instantiating it, as it is managed by JSF. Another advantage of using managed beans is that they allow you to use resource injection because the bean is managed by the Web container.

Example of building a Web Application with JPA using Rational Application Developer

Goal: You will develop an application that displays a list of company departments and their assigned employees. You will also add the ability to update any employee information on file. You will use a two-tier architecture with a single Web module that contains all of the JPA entities, JPA Manager Beans, and Web pages. Your Web pages will interact directly with the data layer, without the use of EJBs.

In the first part of this example, you will build your data layer by creating JPA entities and JPA Manager Beans to interact with your backend Derby database. In the second part, you will focus on using those JPA elements in your Web pages.

Part 1. Set up JPA data for use

First, you need to create a new dynamic Web project.

  1. From the menu bar, select File > New > Dynamic Web Project.

This will launch the Dynamic Web Project wizard (Figure 5).

Figure 5. Creating new dynamic Web project
Dynamic Web Project wizard view
  1. Enter JpaWebExample as the project name.
  2. Set the target runtime to WebSphere Application Server V7.0 (which includes the JPA implementation), and set the Web Module version to 2.5.
  3. In the Configuration drop-down menu, select Faces Project to enable the use of JavaServer Faces in your project.
  4. Click Finish.

After your Web project is created, you are ready to begin adding JPA data to your application. In your application, you will be taking a top-down approach to creating your entities. This means that your database tables already exist, and your entities will be generated based on their existing schemas. In other scenarios, you might develop using a bottom-up approach, in which you would create your entity objects first and then create the database tables from the entities later. Rational Application Developer V7.5 supports both approaches.

You will begin building your application by creating entity objects and their corresponding JPA manager beans.

  1. Right-click on the Web project in the Enterprise Explorer and select JPA Tools > Add JPA Manager Beans (Figure 6).
Figure 6. Launching JPA Manager Bean wizard
Selections made as described

The JPA Manager Bean wizard will show any existing entities in the project or any Utility project on the classpath (Figure 7).

Figure 7. JPA Manager Bean wizard
Wizard view with no entities available yet

You don't have any JPA entities yet, so you will generate entities from an existing database.

  1. Click the Create New JPA Entities button.
  2. From the Generate Entities wizard, when it opens (Figure 8), you can select an existing connection to a database (or create a new one).
Figure 8. Generating JPA entities
Database connection settings view

You will use the Derby Sample Connection that is provided by Rational Application Developer V7.5.

  1. Select the Derby Sample Connection and the SAMP schema, and then click Next.

On the second page, all available tables for the database connection are displayed (Figure 9). For this application you are concerned with only the department, employee, and employee photo tables; therefore, you will create entities for only those tables.

  1. Select the DEPARTMENT, EMPLOYEE, and EMP_PHOTO check boxes, and then click Finish.
Figure 9. Select tables to generate entities
Generate Entities from Tables view

The JPA Manager Bean Wizard now displays the newly created entities, and you can generate the corresponding JPA Manager Beans. (Figure 10).

Figure 10. Selecting entities to create JPA Manager Beans for
Department and Employee entitites selected
  1. Select the Department and Employee entities, and click Next to continue to the next page of the wizard.

The Tasks page shows various settings that can be configured for the manager beans and target entities (Figure 11). You can set primary keys, create and modify queries, add and remove relationships, and set a concurrency column.

Figure 11. JPA Manager Bean tasks
deptno string selected

Your database tables did not have primary keys defined, so you will set them now.

  1. On the primary key Tasks page, select deptno as the primary key for the Department entity.
  2. Click the Employee entity, and select empno its primary key.
  3. Then click back on the Department entity.

You also want to create a one-to-many relationship between Department and Employee (because a department has many employees). The sample database did not explicitly define the relationship, so you will add it to your entities.

  1. Select the Relationships task in the left column and click Add to launch the Add Relationship dialog (Figure 12).
Figure 12. Adding a relationship
  1. Select Employee from the drop-down menu. Set the multiplicity to be one-to-many, and choose a bidirectional relationship.

Bidirectional relationships

A bidirectional relationship means that the Department entity will contain a List of Employees, and, conversely, the Employee will contain the Department that it belongs to. If you want to create only a one-way relationship, where an Employee does not know about its Department, choose unidirectional.

"Employee" is the owner of this relationship (that is, Employee is the many side, thus it contains the foreign key to Department). Therefore, you need to map the foreign key attribute in Employee to the Department's primary key.

  1. Select the workdept attribute from the Employee Foreign Keys column in the table, and click OK to create the relationship.

How JPA queries are added

Let's look at how JPA queries are added.

  1. Click the Query Methods task. This page shows a list of all of the Query Methods that will be generated into your JPA Manager Bean.

Tip: Clicking each Query Method will display the JPQL query that will be run when you run that method. (Figure 13).

Figure 13. Query Methods task
JPA Manager Bean wizard, Tasks view

You can add new methods to fit the use cases of your application. To see an example, create a query that returns a list department numbers and names, filtered by their locations.

  1. Click Add to launch the Add Query Method dialog (Figure 14).
Figure 14. Query Method builder
Add Query Method view
  1. Change the name of your query to something more descriptive than the default value: getDepartmentNamesAndNumbers.
  2. Under the Result Attributes tab, deselect all attributes except "deptname" and "deptno." These will be the only two attributes returned from the database by this query.

The Query Statement field at the bottom of the dialog displays the actual JPQL query being generated, and it is updated to reflect the current state of the dialog. You can also edit the query from this text field directly.

  1. Switch to the Filter Results tab, and click the green plus button to add a filter to your query. This will launch the Add Filter Condition dialog. (Figure 15).
Figure 15. Adding a query filter
Add Filter Condition view

For this exercise, assume that you are interested in showing departments that are located in North Carolina.

  1. Select location as the attribute to use as the filter.
  2. Select LIKE as the filter operator.
  3. Select the Constant/Entity Attribute radio button and enter NC as the value.
  4. Click OK to add the query statement to the list.

Tip:
Alternatively, if you don't want to hardcode the state name, you can use a variable and dynamically pass the value to your query method when it runs.

  1. Lastly, click the Order Results tab to set the order in which you want your results to appear (Figure 16).
Figure 16. Adding an OrderBy to a query
deptname attribute selected

Sort by the department name to get your results in alphabetical order.

  1. Select deptname from the list of Available Attributes, and click Order.
  2. Click OK in the Add Query Method dialog.

This is the query that you have created:

      SELECT d.deptname, d.deptno FROM Department d WHERE d.location LIKE 'NC' ORDER
      BY d.deptname
  1. To see additional advanced options, click the Other task (Figure 17).
Figure 17. Advanced options
Tasks view in wizard

On this page, you can set the name of your manager bean, and consider these advanced options:

  • Use Resource Injection. This setting determines whether to use resource injection in the JPA Manager Bean code. You will here, because your application is inside of a Web container and you are using Faces Managed Beans.
  • Use Named Queries. If this option is enabled, named queries will be generated into the appropriate entities, and the JPA Manager Bean query methods will use them. If this option is unchecked, the JPQL query statements will be used directly inside of the JPA Manager Bean code.
  • Update Entity for use in JSF applications. This option helps ensure that things work smoothly in a JSF scenario by making sure that entities are using Java types that work well with JSF.
  • Update Relationship fetch types. Set Eager or Lazy fetching for any relationships.

You can also use this page to set up the runtime configuration details for your application:

  1. Select the Configure Project for JDBC Deployment link to launch the "Set up connections for deployment" dialog (Figure 18).
Figure 18. Setting runtime connection details
  1. In this dialog, you can set up these configuration files, which are required by JPA to use the proper connection information at run time:
    • persistence.xml, which contains connection details
    • orm.xml, which contains mapping information, schema details

Next, choose a development-time connection with which to seed the runtime details.

  1. Select your Derby Sample Connection in the connection field. This will automatically fill in the default values in the rest of the dialog.

You set the data source or resource reference that you want to use at runtime, along with the default schema to use for all of your entities. You could change the default schema here if you used separate schemas for testing and deployment. Checking the check box to Deploy JDBC Connection to Server will automatically create a data source in the extended information of your EAR file.

  1. Click OK to update the appropriate configuration files and create the data source.

You do not have to do anything else to get your application to connect to the database at run time, which is often a complex and error-prone task.

  1. Finish the Add Manager Bean wizard and take a look at what artifacts have been generated. The Enterprise Explorer view shows all of the newly generated entities.

Notice that they contain fields corresponding to the database table columns and that the primary keys and relationships have been set (Figure 19).

Figure 19. JPA entities
Screen capture of list of entities

Listing 2 shows the Java code for the Department entity.

Listing 2. Department entity code
@Entity
@NamedQueries( {
     @NamedQuery(name = "getDepartment", 
                query = "SELECT d FROM Department d"),
     @NamedQuery(name = "getDepartmentByDeptname", 
                query = "SELECT d FROM Department d WHERE d.deptname = :deptname"),
     @NamedQuery(name = "getDepartmentByMgrno", 
                query = "SELECT d FROM Department d WHERE d.mgrno = :mgrno"),
     @NamedQuery(name = "getDepartmentByAdmrdept", 
                query = "SELECT d FROM Department d WHERE d.admrdept = :admrdept"),
     @NamedQuery(name = "getDepartmentByLocation", 
                query = "SELECT d FROM Department d WHERE d.location = :location"),
     @NamedQuery(name = "getDepartmentOrdered", 
                query = "SELECT d FROM Department d ORDER BY d.deptno"),
     @NamedQuery(name = "getDepartmentNamesAndNumbers", 
                query = "SELECT d.deptname, d.deptno FROM Department d WHERE
d.location LIKE \'NC\' ORDER BY d.deptname") })
public class Department implements Serializable {
    @Id
    private String deptno;

    private String deptname;

    private String mgrno;

    private String admrdept;

    private String location;

    private static final long serialVersionUID = 1L;

    @OneToMany(mappedBy="workdept",fetch=FetchType.EAGER)
    private List<Employee> employeeList;

    // … 
    // …

The class is annotated with an @Entity annotation to indicate to JPA that this class is a mapped entity. All of the named queries have been added as NamedQuery annotations on the entity. This enables you to reference these queries from anywhere in your application simply by their query names; you do not have to worry about the actual Java Persistence Query Language (JPQL) statement. This approach makes these queries highly reusable in your applications. It keeps you from having to change all references to a query if you happen to change the named query itself.

Next, you see that "deptno" has been annotated with an @Id annotation, signifying that it is the primary key attribute. The List of Employee objects is marked with the OneToMany annotation to let the JPA runtime process know that this field is filled by a relationship.

Now let's see how your JPA Manager Beans interface with the entities. Figure 20 gives you an overview of your JPA Manager Beans, as shown in the Page Data View.

Figure 20. JPA Manager Beans
Screen capture of list of Manager Beans

You will notice that the create, retrieve, update, and delete (CRUD) operations have been generated (createDepartment, deleteDepartment, updateDepartment), as well as all of the query methods that you had specified. There will be a corresponding query method for each named query that was created on the Department entity.

Listing 3 shows the Java code for the DepartmentManager.

Listing 3. DepartmentManager code
@JPAManager(targetEntity=entities.Department.class)
@SuppressWarnings("unchecked")
public class DepartmentManager {

    @PersistenceUnit
    private EntityManagerFactory emf;
    @Resource
    private UserTransaction utx;

    public DepartmentManager() { 
    } 

    @Action(Action.ACTION_TYPE.DELETE)
    public String deleteDepartment(Department department) throws Exception {
        EntityManager em = getEntityManager();
        try {
            utx.begin();
            em.joinTransaction();
            department = em.merge(department);
            em.remove(department);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception e) {
                ex.printStackTrace();
                throw e;
            }
            throw ex;
        } finally {
            em.close();
        }
        return "";
    }

    @Action(Action.ACTION_TYPE.UPDATE)
    public String updateDepartment(Department department) throws Exception {
        EntityManager em = getEntityManager();
        try {
            utx.begin();
            em.joinTransaction();
            department = em.merge(department);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception e) {
                ex.printStackTrace();
                throw e;
            }
            throw ex;
        } finally {
            em.close();
        }
        return "";
    }

    @NamedQueryTarget("getDepartmentByLocation")
     public List<Department> getDepartmentByLocation(String location) {
        EntityManager em = getEntityManager();
        List<Department> results = null;
        try {
            Query query = em.createNamedQuery("getDepartmentByLocation");
            query.setParameter("location", location);
            results = (List<Department>) query.getResultList();
        } finally {
            em.close();
        }
        return results;
    }

// …
// …

The first thing to notice is the two fields where resource injection is being used. Because the JPA Manager Bean is defined as a Faces Managed Bean, the Web container is able to inject an EntityManagerFactory and a UserTransaction into the code, as you see in this code:

 @PersistenceUnit
 private EntityManagerFactory emf;
 @Resource
 private UserTransaction utx;

The EntityManagerFactory is used to get an EntityManager, and you need to wrap all of your transactional code in a UserTransaction.

Breaking down the deleteDepartment method, you see that the method accepts a Department entity that will be deleted from your database. The method first obtains an EntityManager and begins a transaction. It verifies that you have the latest copy of that entity and then tells the EntityManager to remove it from the database. Finally, the transaction is committed. Until the transaction is committed, the operation does not actually run.

Now let's look at one of the query methods used to retrieve departments. The getDepartmentByLocation method takes in a parameter for a given location and returns a list of Department entities. This method gets an EntityManager and then creates a NamedQuery by using the name of the named query specified in the Department entity. That NamedQuery looks like this:

 @NamedQuery(name = "getDepartmentByLocation", query = "SELECT 
  d FROM Department d WHERE d.location = :location")

The method then sets the parameter named "location" (marked by :location in the namedQuery) on the query, using the user-supplied value passed into this method. Calling query.getResultList() actually runs the query and returns the results.

Now that you have your data layer in place, your application is ready to use your entities and JPA Manager Beans.

Part 2. Adding JPA data to a Web application

For this example application, you want to display a list of departments and their corresponding employees. Additionally, you want the ability to update any of the employees' information.

You will create two Web pages: one to display a list of departments and one for updating an employee.

  1. Right-click on the project and select New > Web Page. Create two pages: listDepartments.jsp and updateEmployee.jsp.

Now you will add JPA data to your application.

  1. Open the listDepartments.jsp file.

In the Palette view, there is a Data and Services category that enables you to add various types of data to your Web pages (Figure 21).

  1. Select the JPA data item from the palette and drop it onto the page.
Figure 21. Data palette
Arrow points to where item is being dropped

The Add JPA data wizard opens (Figure 22). On the first page, you can select one of the available JPA Managers that you want to use in the current page. You can also select whether you want to display a single record or list and whether to create or update an entity. Your current page will display a list of departments.

  1. Select the DepartmentManager, and then select the Retrieve a list of data radio button.
Figure 22. Add JPA Data wizard
DepartmentManager selected
  1. Click Next so that you can see all of the available query methods in the DepartmentManager bean (Figure 23).
Figure 23. Choosing JPA Query Method
getDepartmentOrdered selected

Here, you will display departments, sorted by their department numbers.

  1. Select the getDepartmentOrdered method.

The Query Statement area shows the actual named query that will be performed by this method.

  1. Moving on to the next page, you can choose the columns that you want displayed on your Web page (Figure 24).
Figure 24. Selecting columns to display on your Web page
3 columns selected

For this purpose, you are only concerned with seeing a brief summary of each department in your list, such as the department numbers, names, and employees.

  1. Make sure that only the deptno, deptname, and employeeList fields in the list are selected.

The employeeList field is a list of all of the employees in this department. By default, a nested data table of employees will be added for each department entry. You can select the columns that you want displayed for the employee.

  1. Click the button on the right side of the row to configure the employeeList controls and then select empno, firstname, and lastname.
  2. Click Finish to add the JPA data to the Web page.

Figure 25 shows what the resulting data table looks like in the design view of Page Designer.

Figure 25. Data table displaying list of departments
3 columns, including EmployeeList (3 subcolumns)

By looking at this generated source code in the JSP, you see that the data table has been bound to a data method in the JSP's Page Code file (a backing bean for the current page):

<hx:dataTableEx id="departmentList1" value="#{pc_ListDepartments.departmentList}"

Managed beans

Note that the datatable is bound to the Web page's Page Code, which in turn calls the DepartmentManager. This mechanism isolates your Web page code, allowing you to easily change the Manager Bean method that you use to retrieve data for your page.

The Page Code method contains logic to retrieve the list of departments (see Listing 4). The getDepartmentList method retrieves the DepartmentManager managed bean and then simply calls the getDepartmentOrdered() method, which you selected in the wizard, and returns the result back to the page.

Listing 4. getDepartmentList method in Page Code
@JPA(targetEntityManager = entities.controller.DepartmentManager.class, 
targetNamedQuery = "getDepartmentOrdered")
public List<Department> getDepartmentList() {
    if (departmentList == null) {
        DepartmentManager departmentManager = (DepartmentManager)
getManagedBean("departmentManager");
        departmentList = departmentManager.getDepartmentOrdered();
    }
    return departmentList;
}

Now that you have your list of departments, you will complete your second Web page that enables you to update an employee record.

  1. Open the updateEmployee.jsp page.
  2. Select the JPA Data item from the palette, and drag it onto the page.
  3. Select the EmployeeManager and then select the action to Update an Existing Record (Figure 26).
Figure 26. Adding data to update an Employee
EmployeeManager selected

On the next page of the wizard, you can choose how you want to retrieve a particular employee record for updating (Figure 27). The typical method is to look up the entity by its primary key, because that will guarantee a unique result.

Retrieving unique entities

Rather than retrieving a single entity through its primary key, you can also use any of the query methods that are defined on the Manager Bean. This will return the first result of that query. You could use this technique if you had a query that you were sure would return a unique result, even though it wasn't using the primary key (such as getEmployeeBySSN).

Figure 27. Retrieving an employee by its primary key
Screen capture
  1. Select the Get Record By Primary Key radio button.

On the next page, you choose where to retrieve the value of the primary key (Figure 28). You can enter a constant or any JSF expression. In this case, you will use the default, which is a variable in the parameter scope.

  1. Leave the JSF expression {param.empno} as the primary key value.
Figure 28. Setting the primary key value
Set Filter Values view

When you Finish the wizard, the code is generated into the Web page and the backing Page Code file. Figure 29 shows what the page designer view looks like.

Figure 29. UI to display and update an employee record
Page designer view (fields)

An input form has been generated that shows all of the employee attributes and allows them to be updated when you click Submit. Additionally, a Delete button was generated to allow you to delete that particular employee. Again, let's look at the backing code generated into the Page Code file.

A getEmployee data get method was generated and is bound to the JSF form (Listing 5). This method retrieves the EmployeeManager managed bean and then calls a method to resolve the parameter passed in on the JSF parameter scope. Finally, it calls the EmployeeManager's findEmployeByEmpno method, passes in the resolved empno value, and then returns the retrieved Employee record.

Listing 5. getEmployee method
public Employee getEmployee() {
    if (employee == null) {
        EmployeeManager employeeManager = (EmployeeManager) 
getManagedBean("employeeManager");
        String empno = (String) resolveParam("employee_empno",
            "#{param.empno}", "java.lang.String");
        employee = employeeManager.findEmployeeByEmpno(empno);
    }
    return employee;
}

The updateEmployeeAction and deleteEmployeeAction methods call the respective updateEmployee and deleteEmployee methods on the EmployeeManager, thereby passing in the current Employee from the page (Listing 6).

Listing 6. Update and Delete Employee actions
public String updateEmployeeAction() {
    EmployeeManager employeeManager = (EmployeeManager) 
getManagedBean("employeeManager");
    try {
        employeeManager.updateEmployee(employee);
    } catch (Exception e) {
        logException(e);
    }
    return "";
} 
public String deleteEmployeeAction() {
    EmployeeManager employeeManager = (EmployeeManager) 
getManagedBean("employeeManager");
    try {
        employeeManager.deleteEmployee(employee);
    } catch (Exception e) {
        logException(e);
    }
    return "";
}

The last thing that you need to do is to set up the link from your list page to your update page when you select an employee entry.

  1. On the listDepartments.jsp page, select the EmployeeList data table and, in the Properties view, select DisplayOptions.
  2. Click the Add button next to "Add an action that's performed when a row is clicked" (Figure 30).
Figure 30. Adding a row action
Properties tab view

Next, ensure that whenever a row is clicked you will go to the updateEmployee page:

  1. Click requestRowAction in the Properties view.
  2. Click the Add Rule button to add a JSF navigation rule for the action (Figure 31).
  3. Select updateEmployee.jsp for the page, set the radio button for "This rule is used by this action only," and then click OK.
Figure 31. Adding a navigation rule to the updateEmployee page
Add Navigation Rule view

You also need to pass a parameter to the updateEmployee page to indicate which employee record to display. The updateEmployee page is to be passed a parameter named empno.

  1. Select requestRowAction in the Properties view, and then select the Parameter property (Figure 32).
  2. Create a parameter named empno, and assign it the value of the employee's empno for the selected row:
    #{varemployeeList.empno}
Figure 32. Passing empno as a parameter
Fields for Name and Value parameters

Run the application on the server

Now you're ready to run your application on the server.

  1. Right-click listDepartments.jsp in the Project Explorer, and select Run As > Run on Server.
  2. Run the listDepartments.jsp page on WebSphere Application Server V7.0.

The list of departments will display, ordered by department number, along with all of the list of employees in that department (Figure 33).

Figure 33. Displaying a list of departments on the server
Screen output: columns and subcolumns

You can click on any employee entry to see additional details.

  1. Click the entry for first employee, Christine Haas.

You will be forwarded to the updateEmployee page, where you can change any detail of the employee entry (Figure 34).

Figure 34. Updating an employee record
Employee record fields

Perhaps you need to update the employee's name:

  1. Change Firstname to CHRISTY and Lastname to JOHNSON, and click Submit.
  2. Now go back to the listDepartments page.

The employee's updated details are displayed (Figure 35).

Figure 35. Updated employee shown in list
Updated view of columns shown previously

Summary

As you have learned from this article, JPA provides an easy way to persist data in your applications. In addition to reviewing the concepts and benefits of JPA, you have seen how it can be used within a Web container. This article also introduced JPA Manager Beans and explained how you can use them in a Web application to handle all of the data persistence logic. These beans and other tools provided by Rational Application Developer V7.5 help you easily build a Web application by using JPA and JSF.

Acknowledgements

The author wishes to acknowledge Christopher Jaun for his many contributions to this article, as well as Daniel Lee for editorial support.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Rational software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational, Agile transformation
ArticleID=330669
ArticleTitle=Developing Web applications with the Java Persistence API and JavaServer Faces
publish-date=08192008