Products Docs & Support Community

Using the Java Persistence API to Modify Database Table Rows in a Visual Web Application

This article is the second article in a two-part series. In the first article ( "Using the Java Persistence API from a Visual Web Application" ), you learned how to use the Java Persistence API to access a database table and retrieve its data, and then display that data using a Visual Web Table component. Now you’re ready to use the same Java Persistence API and Visual Web Table component to add, update, and delete database table rows.

For more information about working with NetBeans IDE, see the Support and Docs page on the NetBeans web site.

Expected duration: 30 minutes

Contents

 

Article Prerequisites


This is the second article in a two-part series. You should have already read the article, "Using the Java Persistence API from a Visual Web Application" and have created the two projects described in that article, along with the different classes and web page. The first article provides all the information necessary to set up these two projects.

Before you proceed, make sure you review the requirements in this section.

Prerequisites

This article assumes that you have some basic knowledge of, or programming experience with, the following technologies.

  • Java Persistence API
  • JavaScript

Software Needed for This Article

Before you begin, you need to install the following software on your computer:

  • NetBeans IDE 6.0 (download)

top

Introduction

The first article provided background on the Java Persistence API. It walked you through the steps to use the Java Persistence API to access a database table and retrieve its data, and then display that data using a Visual Web Table component. Recall that you created two projects, a TestModelApp standard JSE project and a TestWebApp Visual Web project. You also created a page in TestWebApp to display database table data, and two classes containing Java Persistence API methods, Users and UserController, in TestModelApp. You also included code in TestWebApp to invoke methods on the two classes in TestWebApp to retrieve data from a database table.

Now you’re ready to use the same Java Persistence API and Visual Web Table component to add, update, and delete database table rows. For this to work, you add additional methods to the TestModelApp UserController class. You also modify the TestWebApp page that displays the Table component, adding functionality that enables user interaction and improves the table display.

Let's start by modifying the code in TestModelApp. Then, we'll show you how to modify the page in TestWebApp. We also explain the code you need to add to different Button component handlers so that everything works as intended.

Modify the Java Database Access Class

Recall that the UserController class in the TestModelApp project contained code that did some set up work and returned the data in the database table as an array. The UserController set up code called the EntityManagerFactory to create an EntityManager object. Then, it invoked the createQuery method on the EntityManager to construct a Java Persistence query that selected the rows from the Users database table.

Now you need to add three methods to the UserController class:

  • An addUser method to add records to the Users table.
  • A removeUser method to remove records from the table.
  • An updateUser method to modify records in the table.

First, add the addUser method to the UserController class. The addUser method relies on methods from the EntityManager and EntityTransaction interfaces. Specifically, it establishes a transaction context by calling getTransaction().begin(). From within the transaction context, it uses the EntityManager persist method to make the user entity instance persistent, then commits the transaction, which writes the data to the database table and ends the transaction context.

Code Example 1: addUser Method
public boolean addUser(Users users) {
  EntityManager em = getEntityManager();
   try{
     em.getTransaction().begin();
     em.persist(users);
     em.getTransaction().commit();
   } finally {
    em.close();
    return false;
   }
}

Next, add the removeUser code to UserController to remove a record. Similar to the addUser method, this method establishes a transaction context, uses the primary key to locate the database table row that matches the entity to be deleted, then removes that entity instance. The commit call completes the removal and ends the transaction.

Code Example 2: removeUser Method
public boolean removeUser(Users users) {
  EntityManager em = getEntityManager();
  try{
    em.getTransaction().begin();
    Users userx = em.find(Users.class, users.getUserId());
    em.remove(userx);
    em.getTransaction().commit();
  } finally {
    em.close();
    return false;
  }
}

Last, add the updateUser method to update a record. Similar to the previous two methods, the updateUser method does its work within the context of a transaction. It uses the primary key to find the matching entity instance, then invokes the get and set methods from the Users class to make the necessary changes to the table columns (user name, email address, and password), and commits the changes to end the transaction.

Code Example 3: updateUser Method
public boolean updateUser(Users users) {
  EntityManager em = getEntityManager();
  try{
    em.getTransaction().begin();
    Users userx = em.find(Users.class, users.getUserId());
    userx.setUsername(users.getUsername());
    userx.setPassword(users.getPassword());
    userx.setEmailAddress(users.getEmailAddress());
    em.getTransaction().commit();
  } finally {
    em.close();
    return false;
  }
}

 

Modify the Web Page Design

After adding the code to the TestModelApp UserController class, you are ready to change the Page1 web page in the TestWebApp project. Changes include enhancing the Table component display, adding other components to the page, and customizing some of the page component code.

Start by enhancing the page and Table component display. The binding example in the first article created a page and Table component that was rather minimal in appearance and functionality. Since that example only demonstrated the steps to display database data retrieved with the Java Persistence API, a bare-bones display was sufficient. Now we show you how to use the Visual Web features to create a web page and a Table component that more closely approximates that of a “real world” application.

In brief, you add three buttons (Add, Delete, and Update) to the page and place them so that they display beneath the table. You also add input fields so that users can enter a user name, password, and email address, if they are creating a new user entry or modifying an existing entry. You also add Add Record and Update Record buttons, so that users can indicate that they are adding or modifying the table rows.

You’ll also see how to use the Grid Panel components to align the input fields and buttons for a better presentation. Grid Panels are useful components for laying out text and other components on a page. When added to a page, they actually create a table-like container into which you add other components. Components added to a Grid Panel display from left to right (this horizontal direction can be reversed) and from top to bottom, and the Grid Panel can have from one to many columns plus as many rows as needed.

In addition, you’ll learn how to use the prerender method in conjunction with the Grid Panels to dynamically display portions of the page in the browser, depending on options chosen by the user. For example, when the page initially displays, you see only the table listing the users data stored in the database. The basic display remains the same when you delete an entry from the table; of course, the specified row is removed. But, when you indicate that you want to an entry or modify an existing entry, the page display changes to show the data fields you need to enter along with the corresponding two buttons. The prerender method code controls the page display according to boolean values set by the button action handlers.

Altogether, you place four Grid Panel components on the page, three of which will be nested within the first Grid Panel, and the other components (including the Table component, buttons, and input fields) are placed within these Grid Panels.

After placing all components on the page, you’ll see how to change the Table component’s display using the Table Layout functions.

Use Grid Panel Components to Control Page Display

Start by placing the Grid Panel components on the web page. The first Grid Panel you place on the page serves as a container for subsequent Grid Panel components plus other components.

Add a Grid Panel to serve as a component container. Open Page1 in the Designer window and drop a Grid Panel component onto the page. (The Grid Panel is in the Layout section of the Palette.) To help identify it, change the Grid Panel’s id property to mainContainer. This Grid Panel serves as a container for the other components on the page. You drop other components, such as other Grid Panels, buttons, and text fields, onto the Grid Panel and it helps control the alignment of these components.

By default, components added to a Grid Panel display from left to right based on the order they are added. If you find that this is not the case, check the setting of the Grid Panel's dir property (found in the Advanced section of the Properties sheet). The dir property direction should be set to Left to Right; if not, use the property's pull-down menu to change the setting.

Figure 1: Add mainContainer Grid Panel


Click to enlarge

Use the Outline Window to Position Components

Next, add components to the mainContainer Grid Panel and use the Outline window to reposition these components. Begin by dropping a Table component onto the mainContainer Grid Panel. If this were a new page, you would drop a Table component onto the Grid Panel and then bind that Table component to the users array, just as you did previously. Since you already have a Table component bound to the users array on the page, you can instead use the Outline window to move the Table component onto the Grid Panel. Generally, the Outline window provides an easy-to-use mechanism for accessing and moving components on a page, especially since the Outline window displays all components on a page regardless of the component’s visibility on the page. It’s important to keep this in mind, since a number of components are not explicitly visible when added to a page.

You can drop a new Table component directly on the Grid Panel in the Design window. If you do so, be sure that the Grid Panel is highlighted before you drop the component. You can place the Table component already on the page onto mainContainer by dragging it within the Outline window and dropping it on the Grid Panel. Figure 2 illustrates dragging table1 and placing it over the Grid Panel mainContainer, which is then highlighted. After dropping table1, the Outline display changes to show that table1 is within mainContainer. The display on the page changes, too.

Figure 2: Use the Outline Window to Position Components


Click to enlarge

Add Remaining Components to Page

Now, add a Grid Panel for the Add, Delete, and Update buttons, then the Button components themselves. Add a second Grid Panel to the page and place three buttons (Add, Delete, and Update) in that panel. Be sure to drop this new Grid Panel on top of the first mainContainer (or, after adding it to the page, use the Outline window to move it so that it is within mainContainer). Set the id property for this Grid Panel to buttonPanel.

Since the three buttons should line up horizontally, use the buttonPanel Properties sheet to set the columns property to three (3). Then, drop three buttons on the buttonPanel and set their id and text properties as shown here. To keep the buttons to the left side, resize the width of buttonPanel to about half that of mainContainer.

  • First button: Set the id to addButton and text property to Add.
  • Second button: Set the id to deleteButton and text to Delete.
  • Third button: Set id to updateButton and text to Update.

Figure 3: Place Button Components in Grid Panel


Click to enlarge

Add a Grid Panel for the user input fields, then the labels and input fields themselves. Drop a third Grid Panel on the mainContainer Grid Panel. Set its id property to addUpdatePanel and its columns property to two (2). Then add three Label and Text Field components to the addUpdatePanel, for the input fields user name, password, and email address. By dropping first a Label then a Text Field onto addUpdatePanel, the labels and their input fields should align horizontally in this two-column Grid Panel and each pair should align vertically with the table. Add the following Label and Text Field component pairs in this order, and set their respective text and id properties as shown:

  • Label1: set text property to User Name; Text Field: set id property to userNameField.
  • Label2: set text property to Password; Text Field: set id property to passwordField.
  • Label3: set text property to Email Address; Text Field: set id property to emailAddressField.

Add a Grid Panel for the Add Record and Update Record buttons, along with these two buttons. Drop this Grid Panel on addUpdatePanel, set its property id to addUpdateButtonPanel and its columns property to two (2), and then add the following two buttons to it. Resize the width, too, to keep the buttons to the left side of the display. (You can change addUpdateButtonPanel’s width property in the Properties sheet, or use the mouse to resize the panel in the Design window.)


  • First button: Set the id to addRecordButton and text property to Add Record.
  • Second button: Set the id to updateRecordButton and text property to Update Record.

Placing the addUpdateButtonPanel buttons within the addUpdatePanel keeps these two buttons with the three data input fields. Later, after we add code for the button action handlers, we’ll also customize the prerender method so that the contents of the addUpdatePanel (the three input fields and the panel with the add/update record buttons) display only when a user wants to add a record or modify an existing record. The addUpdatePanel will not display when the table listing all users appears on the page or when a user deletes a row from the table.

Customize Table Display Using Table Layout

Use the Table Layout function to change the Table component display. Using the Table Layout dialog, you add a new column to the table display and, by moving it to the top of the columns list, position it to be the leftmost column in the table. When added, it is given a default column header text of tableColumn5. Remove this text from the Header Text field and leave it empty. In addition, from the Component Type pull-down list, select Radio Button and remove the text in the Value Expression Field.

Figure 4: Table Layout Dialog

The completed Page1 looks as shown in Figure 5. Notice that there is column without a column heading to the left of emailAddress. Figure 5 also shows how to resize a Grid Panel in the Design window.

Figure 5: Grid Panel in Design Window


Click to enlarge

Add Logic for Button Components

Now that you have completed the design of the web page, you need to add logic to the application so that the various buttons work as intended. You need to:

  • Write some Java code for the Page1.java file, the backing bean for the web page.
  • Write a JavaScript function for the Table component.
  • Use the Visual Web GUI to bind button properties to values returned by the JavaScript function.

Write Java Code for the Radio Buttons

You need to write some logic (Java code) to hold information about the radio button that is selected on Page1, and you place the code in the Page1.java file. This code relies on the TableSelectPhaseListener class, a utility class that is part of the JavaServer Faces event package (com.sun.webui.jsf.event). The utility class is specifically for radio button components, and you use its methods to select rows of a table. The methods return a selected Table row as a RowKey object, which is a retrievable representation of a data row table identifier.

With Page1 displayed in the Design window, click the Java tab to open the Java code in the source editor. Add the code shown in Code Example 4. After adding the code, click Fix Imports so that the IDE imports the two missing classes (RowKey and TableSelectPhaseListener) and fixes the errors.

Code Example 4: Radio Button TableSelectPhaseListener Code
    private TableSelectPhaseListener tablePhaseListener =
                                  new TableSelectPhaseListener();
    public void setSelected(Object object) {
        RowKey rowKey = (RowKey)getValue("#{currentRow.tableRow}");
        if (rowKey != null) {
            tablePhaseListener.setSelected(rowKey, object);
        }
    }
    public Object getSelected(){
        RowKey rowKey = (RowKey)getValue("#{currentRow.tableRow}");
        return tablePhaseListener.getSelected(rowKey);
    }
    public Object getSelectedValue() {
        RowKey rowKey = (RowKey)getValue("#{currentRow.tableRow}");
        return (rowKey != null) ? rowKey.getRowId() : null;
    }
    public boolean getSelectedState() {
        RowKey rowKey = (RowKey)getValue("#{currentRow.tableRow}");
        return tablePhaseListener.isSelected(rowKey);
    }

Add JavaScript Code to the JavaServer Page File

Now you add JavaScript code to Page1’s JavaServer Page (JSP) file. In the Design window, click the JSP tab to open the JSP page for editing. Add the code shown in Code Example 5 to the Table component; that is, add it within the <webuijsf:table> tag.

Code Example 5: Radio Button JavaScript Code
<script>
function initAllRows() {
var table = document.getElementById("form1:table1");
table.initAllRows();
}
</script>

After you add the JavaScript code, notice that the Page1.jsp display in the Navigator window reflects the table bindings (the individual bindings to the columns of the users database table plus the radio button that you added) along with the JavaScript you just inserted. The JSP code itself shows the details of the table bindings. (Note: If the Navigator window does not display the updated Page1.jsp, click the Window->Reset Windows option.)

Figure 6: Page1.jsp Displayed in Navigator Window

Bind the Radio Button to the Table Component

The Table component must keep track of the current selected table row via the Radio Button (which you added to the table earlier). To do so, you use the Visual Web Properties Binding dialog to bind a property of the Radio Button to the current row value. When you complete the dialog, the IDE updates the JSP code for you. Here’s how to do this binding.

  1. Open the Properties Binding dialog for radioButton1 on Page1. In the Outline window, scroll down the Page1 tree until you find radioButton1 within the table. (To see the Outline window, select the Design tab for Page1. If the Outline window does not display, click the Window->Reset Windows option.) Right click the radioButton1 node and select Property Bindings from the context menu.

    Figure 7: Properties Binding Dialog

  2. Use the Properties Binding dialog to set three properties, noted here. You need to click the All option to see these properties in the Set bindable property column. After setting the binding expression for each property, be sure to click the Apply button so that the new expression is saved to the JSP file. Set the property selected to #{Page1.selected}. Click selected in the Select bindable property column, then click selected in the Select binding target column. Click Apply when the New binding expression field shows the correct binding; the Current binding field should change to the new binding.
    • Set the property selectedValue to #{Page1.selectedValue}. Set this property in the same manner as the selected property.
    • Set the property name to #{Page1.radioButton1.id}. You have to manually enter the new binding expression for this property.
  3. When the bindings are completed properly, the Radio Button tag in the JSP file should look as follows:

    Code Example 5: Radio Button Tag in JSP File

    <webuijsf:radioButton binding="#{Page1.radioButton1}" id="radioButton1" label="" name="#{Page1.radioButton1.id}"selected="#{Page1.selected}" selectedValue="#{Page1.selectedValue}"/>

    Figure 8: Applying Property Bindings

There are some additional property bindings that you must do.

  1. You need to bind some properties for the table column in which the Radio Button has been placed. In our example, this is tableColumn5. Select that table column in the Navigator window (or click that column in the Design window), open the Properties Binding dialog from the context menu, and set two properties. You have to manually enter these binding expressions. As before, click Apply after setting each property.
    • Set the onClick property to setTimeout(‘initAllRows()’,0). It’s quite possible that the Current binding field may not reflect the new binding expression after it is applied. Even so, the binding should appear in the JSP code.
    • Set the selectId property to #{Page1.radioButton1.id}
  2. When completed, the JSP code for the tableColumn5 tag should look as follows:
    Code Example 6: JavaScript Code for tableColumn5
    <webuijsf:tableColumn binding="#{Page1.tableColumn5}" id="tableColumn5" onClick="setTimeout('initAllRows()', 0)" selectId="#{Page1.radioButton1.id}">
  3. Now, bind the selected property on the table’s table row group (tableRowGroup1 in our example) to selectedState. The new binding expression should be #{Page1.selectedState}, as shown in Figure 9. The JSP code for the tag tableRowGroup should be as follows:

    Code Example 7: JavaScript Code for tableRowGroup1


    <webuijsf:tableRowGroup binding="#{Page1.tableRowGroup1}" id="tableRowGroup1" rows="10" selected="#{Page1.selectedState}" sourceData="#{SessionBean1.users}" sourceVar="currentRow"

    Figure 9: Modified Property Binding Expression

Write Code for Button Handler Methods

You need to add some code to the Add and Update button action handlers in Page1. (These two buttons are in the buttonPanel immediately below the table.) Later, we cover the code you add to the action handler methods for the two buttons at the bottom of the page, the Add Record and Update Record buttons.

This code also requires two boolean variables, which you need to add when you update the button action handler methods. After setting up all the button action handlers, you need to add some custom code to the prerender method.

Create Boolean Variables

Add the two boolean variables to the Page1.java source file. Call these variables addRequest and updateRequest and set both values to false. You should have the following statements in the source file.

Code Example 8: Create Boolean Variables in Page1.java
private boolean addRequest = false;
private boolean updateRequest = false;

Write Button Action Handler Methods

Add code to the Add button’s addButton_action method. The added code sets a flag (addRequest) to true to enable the addUpdatePanel, which contains the entry fields for user name, password, and email address. The prerender method uses these boolean values to determine its handling of the addUpdatePanel.

Open the button code in the Java source editor by double clicking the Add button on the page in the Design window. Add a line to the addButton_action method that sets addRequest to true. The action handler should look as follows:

Code Example 9: Add Button Action Handler Method
private boolean addRequest = false;
  public String addButton_action() {
  addRequest = true;
  return null;
}

Note: If you open the Java source file for Page1 by clicking the Java tab rather than double clicking the button, you will not see the button’s action handler method. When you double click the button, the IDE adds an empty method for the action handler as a convenience and you only need add the custom lines of code.

Double click the Update button to open the updateButton_action method and add the following code. As with the addButton action handler, this code sets the boolean updateRequest to true so that the addUpdatePanel is enabled. The action handler should look as follows:

Code Example 10: Update Button Action Handler Method
private boolean updateRequest = false;
public String updateButton_action() {
updateRequest = true;
return null;
}

Now, add code to the Delete button action handler so that when the button is clicked, the selected row from the table is deleted from the database. This code first obtains the selected RowKey from the tableRowGroup1. It uses the RowKey index to identify and obtain the corresponding row within the Users table. It then invokes the UserController.removeUser method, passing it the row identifier, and removeUser removes the selected row from the database. Most likely you will need to use the Fix Imports function after adding this code to the Page1.java file.

Code Example 11: Delete Button Action Handler Method
public String deleteButton_action() {
        if (getTableRowGroup1().getSelectedRowsCount() > 0){
          RowKey[] selectedRowKeys = getTableRowGroup1().getSelectedRowKeys();
          Users[] users = getSessionBean1().getUsers();
          int rowId = Integer.parseInt(selectedRowKeys[0].getRowId());
          Users user = users[rowId];
          // Remove the Entity from the database using UserController
          UserController userController = new UserController();
          userController.removeUser(user);
        }
        return null;
}

Write Code to Create Entity Bean and Add to Database

Now you are ready to add code to the Add Record and Update Record action handler methods. The code for the Add Record action handler takes the data entered to the addUpdatePanel fields and creates a new entity bean encapsulating a row of data in the Users table. It then calls the UserController method addUser to add this entity bean data to the database. It also sets the boolean updateRequest to false. Later, you add code to the prerender method, which executes after the button action handler completes, that makes use of the boolean variables updateRequest and addRequest to determine the processing path to take.

Double click the Add Record button in the Design window to open the addRecordButton action handler in the Java source editor. Then, add the following code to the method. The complete method should look as follows:

Code Example 12: Add Record Button Action Handler Method
    public String addRecordButton_action() {
// Create a new User Entity
Users newUser = new Users();
newUser.setUsername((String) userNameField.getText());
newUser.setPassword((String) passwordField.getText());
newUser.setEmailAddress((String) emailAddressField.getText());
// Add the new Entity to the database using UserController
UserController userController = new UserController();
userController.addUser(newUser);
updateRequest = false;
return null;
}

Write Code to Update Database Record

You add code to the Update Record button’s action handler to update an existing record in the database. The action handler takes the data entered by the user in the fields of the addUpdatePanel and writes that data to the database record.

Double click the Update Record button to open the updateRecordButton_action action handler in the Java source editor and add the following code to the action handler. The added code first obtains the Users entity bean using the current selection in the table. It updates the Users fields with data entered in the addUpdatePanel fields, then calls the UserController.updateUser method to update the database data with the entity bean data. The completed action handler should look as follows:

Code Example 13: Update Record Button Action Handler Method
    public String updateRecordButton_action() {
// TODO: Process the action. Return value is a navigation
// case name where null will return to the same page.
// Create a new Users Entity
RowKey[] selectedRowKeys = getTableRowGroup1().getSelectedRowKeys();
Users[] users = getSessionBean1().getUsers();
int rowId = Integer.parseInt(selectedRowKeys[0].getRowId());
Users user = users[rowId];
user.setUsername((String) userNameField.getText());
user.setPassword((String) passwordField.getText());
user.setEmailAddress((String) emailAddressField.getText());
// Update the database table data using UserController
UserController userController = new UserController();
userController.updateUser(user);
addRequest = false;
return null;
}

Modify prerender Method to Control Page Display

The prerender method on the page sets up any custom parameters for the page display and is invoked before the page is displayed. The following code, which you add to the prerender method, uses the boolean values addRequest and updateRequest to determine whether to show or hide the addUpdatePanel. It also updates the display of the user’s data based on whether modifications or data additions occur.

Code Example 14: Modified prerender Method
     public void prerender() {
if(addRequest){
addUpdatePanel.setRendered(true);
addRecordButton.setRendered(true);
updateRecordButton.setRendered(false);
userNameField.setText("");
passwordField.setText("");
emailAddressField.setText("");
}else if (updateRequest){
if (getTableRowGroup1().getSelectedRowsCount() > 0){
// Get the data from the selected Entity and update the fields
RowKey[] selectedRowKeys = getTableRowGroup1().getSelectedRowKeys();
Users[] users = (Users[]) getSessionBean1().getUsers();
int rowId = Integer.parseInt(selectedRowKeys[0].getRowId());
Users user = users[rowId];
userNameField.setText(user.getUsername());
passwordField.setText(user.getPassword());
emailAddressField.setText(user.getEmailAddress());

addUpdatePanel.setRendered(true);
addRecordButton.setRendered(false);
updateRecordButton.setRendered(true);
}
}else{
addUpdatePanel.setRendered(false);
}
// Refresh the users data array in the session bean to to show
// the newly added data or modified data in the Table Component
getSessionBean1().updateUsers();
}

Run the Application

You are now ready to build and run the TestWebApp application. Right click TestWebApp in the Projects window and select Run Project. When the page opens in the browser, the display is very much like what you expect for an enterprise-level application.

Figure 10: Example of TestWebApp Running in Browser

You can modify information for existing records, plus add new records and delete existing records. The page display changes depending on the buttons you selected. For example, if you want to modify an existing user record, check the radio button for that record and then click Update. The browser window displays the fields of the selected record and you can modify them as desired. Click the Update Record button to save any changes to the database.

Figure 11: Updating a User Record

Summary


This article showed you how to modify the projects that you had previously set up to access a database using the Java Persistence API. You learned how to use the Java Persistence API to modify existing database records, add new records, and delete records. In addition, the article showed how to use the Visual Web components and features to create professional-looking web pages.

top

Next Steps

  • To learn more about the Java Persistence API, go to Java Persistence API.
  • To send comments and suggestions, obtain support, and stay informed of the latest changes to the NetBeans IDE development features, join the mailing list.

See Also

You might also be interested in these articles on Java Persistence:

  • The Java Persistence API - A Simpler Programming Model for Entity Persistence
  • Using the Persistence API in Desktop Applications

Also, read Winston Prakash's blog on this topic.


 

top

>> More NetBeans IDE Documentation