LAB-5573: Leveraging JavaScript Toolkits for End-to-End Connectivity in Web Applications

Expected Duration: 100 minutes
Contacts: Troy Giunipero

Exercise 3: Connecting a YUI DataTable to a Java DB Database with JPA (25 minutes)

 

This exercise demonstrates how to connect a sortable YUI DataTable to an application that uses the Java Persistence API with a backend Java DB database.

As YUI's demo page states,

"[The] DataTable instance [is] based on markup that already exists on the page. By progressively enhancing markup with higher order functionality, users who do not have JavaScript enabled are still able to view the page's content and experience core functionality."

You begin with a sample project that enables users to save records to and view them from a database using Java Persistence. Records are displayed in a simple HTML table. By incorporating a YUI DataTable into the project, you enhance the appearance of the record table while providing column sorting functionality. Furthermore, if JavaScript is disabled in a client browser, the data is still displayed intact (using the original HTML table).

The completed project looks as follows:
Completed project displayed in browser

You can complete this exercise by performing the following steps:

  1. Examining the sample application.
  2. Connecting to the database in the IDE.
  3. Including the bundled YUI toolkit in the project.
  4. Adding YUI-Specific code to the web page.

Background Information

 

The sample application used in this exercise is a modified version of the WebJpa project found in the NetBeans Samples Catalog. To access the original application, open the IDE's New Project wizard and choose Samples > Java Web > WebJpa.

The use of JPA and Java DB rely on the default resources at your disposal when working in the NetBeans - GlassFish environment. Namely, you rely on:

  • the Java DB database management system that comes bundled with the GlassFish server (also, when starting GlassFish, by default the server automatically starts Java DB),
  • the sun-appserv-samples database that is included by default in Java DB,
  • the jdbc/__default data source, preconfigured in GlassFish
  • the DerbyPool connection pool, preconfigured in GlassFish

Furthermore, when using JPA, you are reliant on GlassFish as a Java EE container for the creation of an EntityManagerFactory - required by the application's Persistence Unit. For more details, see the GlassFish Project's Java Persistence Example.



Steps to Follow

 

Step 1: Examining the Sample Application

  1. In the IDE's Projects window, right-click the Ex3_YUI_Start project node and choose Set as Main Project.
  2. Click the Run Main Project ( Run Main Project button ) button in the IDE's toolbar to run the project.

    The browser opens to display the welcome page (listPerson.jsp).
    listPerson.jsp displayed in browser
  3. Click the Create a Person Record link, and type in details to enter a new record.
    createPerson.jsp displayed in browser
  4. Click Create Record, and you'll see that the application has recorded your details.
    Records displayed in browser
  5. Repeat this process to add several more records to the data store. You'll note that these records are saved in the database and dynamically reproduced in an HTML table.
    More records displayed in browser

Step 2: Connecting to the Database in the IDE

Now that you have a basic idea of how the application performs for the user, briefly examine the application's logic, then connect to the database manually to see where the data is being stored.

  1. Expand the Source Packages > servlet node, then double-click the CreatePersonServlet to open it in the editor.
  2. Examine the processRequest() method to understand how transactions are being made to the database. Specifically, look at:
    //Get the data from user's form
    String id         = (String) request.getParameter("id");
    String firstName  = (String) request.getParameter("firstName");
    String lastName   = (String) request.getParameter("lastName");
    
    //Create a person instance out of it
    Person person = new Person(id, firstName, lastName);
    
    //begin a transaction
    utx.begin();
    //create an em.
    //Since the em is created inside a transaction, it is associsated with
    //the transaction
    em = emf.createEntityManager();
    //persist the person entity
    em.persist(person);
    //commit transaction which will trigger the em to
    //commit newly created entity into database
    utx.commit();
    A new Person object is created using user input. The Persistence Unit then uses an EntityManager to persist the Person object (i.e., transfer its data to the database). To do so, a UserTransaction is employed to perform persistence operations in a transactional manner. The transaction is delineated by the utx.begin() and utx.commit() methods, and ensures that any commits are rolled back if communication problems occur while the transfer takes place.
  3. Open the Persistence Unit descriptor (persistence.xml). This file can be located in the Configuration Files folder in the Projects window. In the Design view, note that the Persistence Unit is using the jdbc/__default data source:
    Design view of the Persistence Unit
  4. Open the IDE's Services window (Ctrl-5; ⌘-5 on Mac).
  5. Expand the Servers node, then right-click the GlassFish V2 node and choose View Admin Console.
  6. Log into the GlassFish V2 Admin Console. (The default username / password is: admin / adminadmin.)
  7. In the left column of the Admin Console, expand the Resources > JDBC > JDBC Resources node, then select the jdbc/__default node to examine its properties.
    Data source properties displayed in GlassFish Admin Console
    Note that the data source is associated with the DerbyPool connection pool.
  8. Click the JDBC Connection Pools link that is displayed in the page, then click DerbyPool from the list of connection pools.
  9. Click the Additional Properties tab located at the top of the page, and you'll be able to view supplementary information on the DerbyPool connection pool.
    Connection pool properties displayed in GlassFish Admin Console
    Here, note that the database name that is associated with the connection pool is: sun-appserv-samples. Also note that the username and password used to connect to the database are: APP / APP.
  10. Exit the Admin Console and return to the IDE's Services window.
  11. Expand the Databases > Drivers node, then right-click the Java DB (Network) node and choose Connect Using.

    Note: Make sure you choose Java DB (Network) and not Java DB (Embedded).
  12. In the New Database Connection dialog, for Data Input Mode select the Direct URL Entry option, then type in the following details:
    • Username: APP
    • Password: APP
    • JDBC URL: jdbc:derby://localhost:1527/sun-appserv-samples

    New Database Connection dialog
  13. Click OK and in the Advanced Tab you'll see that a connection is established. Make sure APP is selected as the default schema, then click OK to exit the dialog.
  14. Find the new connection node in the Services window, and expand it to view the APP schema and tables contained therein. Find the PERSON database table.

    Note: The other tables that are listed in the below image are those used for the sample applications included in the Java EE 5 Tutorial.
    Services window displaying database connections
  15. Right-click the PERSON table and choose View Data. The SQL editor opens with the query, "select * from APP.PERSON", and the table data is displayed beneath.
  16. Add a new record directly to the table. Click the Insert Records icon ( Insert Records icon ) located in the upper left corner of the table that displays the data, then in the Insert Records dialog, type in details to create a new record.

    Tip: Click the Show SQL button to view to SQL code that will be applied.
    Insert Records dialog
  17. Click OK, and note that the new record displays in the table in the SQL editor.
    SQL editor displaying new record
  18. Return to the browser and click the "Create a Person Record" link, then click the "Go to List of Persons" link from the createPerson.jsp page.

    Note: Don't simply refresh the page, as this will attempt to resend form data for the last record you entered in the page (i.e., the entry with id: 333). Doing so will result in a javax.servlet.ServletException, since the primary key 333 already exists in the database.
    More records displayed in browser
    The record you entered from the IDE now displays in the table.

Step 3: Including the Bundled YUI Toolkit in the Project

To apply the YUI DataTable to the HTML table shown in the browser, you need to add the YUI toolkit to the project. Version 2.6.0 is bundled with the IDE, and contains all components necessary for utilizing the DataTable.

  1. In the Projects window (Ctrl-1; ⌘-1 on Mac), right-click the project node and choose Properties. The Project Properties window opens.
  2. Select the JavaScript Libraries category, then click the Add button. The dialog that displays shows all of the JavaScript libraries that are registered with the IDE (minus any that you may have already added to your project).
  3. Select YahooUI 2.6.0, and note that the physical path to the location within your project where the library will be extracted to displays in the dialog.
    Add JavaScript Libraries dialog
    Note: By default, the IDE extracts JavaScript libraries to a web/resources folder within your project. You could modify the path by clicking the ellipsis button ( Ellipsis button ) in the above dialog, then navigating to a new path.
  4. Click OK. When you do so, the library is extracted to the specified location in your project.
  5. Click OK to exit the Project Properties window. In your Projects window, note that a yui_2.6.0 node is now listed under Web Pages > resources.
    Projects window displaying YUI resources
    The YUI library is now added to your project.

Step 4: Adding YUI-Specific code to the Web Page

We'll be dealing with the listPerson.jsp page in this step which, from the Projects window, is located in the project's Web Pages folder. In order to complete this step, there are 3 tasks that you need to accomplish:

  1. Link to the relevant YUI resources within the project,
  2. Add JavaScript customized for column sorting,
  3. Apply a YUI "skin".

Link to the relevant YUI resources

To apply the DataTable to the page, you need to link to the relevant YUI resources from the page. But what resources? If you expand the resources > yui_2.6.0 > build > datatable node, it would be safe to assume that you'll require the datatable.js script. But is this all? Are there other dependencies? How can you find out?

There are two ways to learn of dependencies:

  1. Visit the DataTable component user's guide and search for dependencies within the sample code.
  2. Open the YUI Dependency Configurator and configure for the DataTable component.

This exercise explores the YUI Dependency Configurator to determine the necessary resources for the DataTable component. You will require an Internet connection for several of the remaining steps in this exercise.

YUI Documentation and API

When using toolkit components, it is useful to have documentation and API resources readily available. YUI provides beautifully structured documentation both in the form of component users' guides and working examples, cheat sheets in pdf format, as well as an API interface that can be viewed online or downloaded and installed:

Warning: Be aware that there may be discrepencies between toolkit versions. Online documentation and hosted resources are provided only for the most recent version (2.7.0 as of 3/2009). The toolkit version bundled with the IDE is 2.6.0.

  1. Open the YUI Dependency Configurator [Internet connection required].
  2. Select the DataTable Control button.
    YUI Dependency Configurator with DataTable selected
  3. Deselect the Combine Files option.
    YUI Dependency Configurator with Combine Files option deselected
  4. Scroll down to the Loading Script and CSS Directly tab, and copy the contents (Ctrl-C; ⌘-C on Mac) to your clipboard.
    YUI Dependency Configurator - Loading Script and CSS Directly
    The contents are as follows:
    <!-- Individual YUI CSS files -->
    <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/datatable/assets/skins/sam/datatable.css">
    <!-- Individual YUI JS files -->
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/element/element-beta.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/datasource/datasource.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/datatable/datatable.js"></script>
    
    Note: The YUI Dependency Configurator enables you to link directly to either a Yahoo! or Google content delivery network (CDN). One of the aims of this exercise is to demonstrate how it is possible to utilize the IDE's bundled toolkits, so you will modify the contents in the following steps to refer to the resources included in your project.
  5. Open the listPerson.jsp file in the editor by double-clicking it from the Projects window.
  6. Paste the contents into the file between the <head> tags. You can replace the <!-- add YUI resources here --> comment in doing so.
  7. Modify the paths to refer to the resources you added to your project (changes in red).
    <!-- Individual YUI CSS files -->
    <link rel="stylesheet" type="text/css" href="resources/yui_2.6.0/build/datatable/assets/skins/sam/datatable.css">
    <!-- Individual YUI JS files -->
    <script type="text/javascript" src="resources/yui_2.6.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
    <script type="text/javascript" src="resources/yui_2.6.0/build/element/element-beta.js"></script>
    <script type="text/javascript" src="resources/yui_2.6.0/build/datasource/datasource.js"></script>
    <script type="text/javascript" src="resources/yui_2.6.0/build/datatable/datatable.js"></script>
    
    As you can see, the DataTable requires dependencies on the Yahoo Dom Event, the Event utility, and the DataSource utility.

Add JavaScript customized for column sorting

Now let's add the YUI-specific JavaScript to the page. We need to customize the DataTable according to the HTML table.

  1. Instantiate the DataTable. Replace the // add code for DataTable here comment with the following code:
    // DataTable constructor
    this.myDataTable = new YAHOO.widget.DataTable("myContainer", myColumnDefs, this.myDataSource);
    You instantiate the DataTable using 3 parameters:
    • "myContainer": An id string to reference a container div element to host the rendered markup,
    • myColumnDefs: A set of Column definitions, and
    • this.myDataSource: A DataSource instance to manage data retrieval.
  2. To account for the first argument of the DataTable constructor, surround the HTML table with a <div id="myContainer"> tag (changes in red).
    <div id="myContainer">
        <table id="people" border="1" cellpadding="10">
            <thead>
                <tr>
                    <th bgcolor=>ID</th>
                    <th bgcolor=>FirstName</th>
                    <th bgcolor=>LastName</th>
                </tr>
            </thead>
            <tbody>
    
                <c:forEach var="person" begin="0" items="${requestScope.personList}">
                    <tr >
                        <td>${person.id}  </td>
                        <td>${person.firstName}  </td>
                        <td>${person.lastName}  </td>
                    </tr>
                </c:forEach>
    
            </tbody>
        </table>
    </div>
    Tip: To reformat your code, right-click within the editor and choose Format.
  3. To account for the second argument of the DataTable constructor, create a reference to an array of object literals that define the columns in the table. Type in the following above the constructor.
    var myColumnDefs = [
        {key:"id",label:"ID", sortable:true},
        {key:"firstName",label:"First Name", sortable:true},
        {key:"lastName",label:"Last Name", sortable:true},
    ];
    The keys you use here are applied to the DataSource in the next step. Also, note that the labels match the headings used in the HTML table. The columns are defined with sortable:true, which enables basic sort functionality when clicking on the column header.
  4. To account for the third argument of the DataTable constructor, create a DataSource that will consume data from the HTML table. To instantiate the DataSource, we'll use the LocalDataSource subclass and point to the HTML <table> element in the markup. Add the following (changes in red).
    var myColumnDefs = [
        {key:"id",label:"ID", sortable:true},
        {key:"firstName",label:"First Name", sortable:true},
        {key:"lastName",label:"Last Name", sortable:true},
    ];
    
    // Instantiate the DataSource
    this.myDataSource = new YAHOO.util.LocalDataSource(YAHOO.util.Dom.get("peopleTable"));
    
    // DataTable constructor
    this.myDataTable = new YAHOO.widget.DataTable("myContainer", myColumnDefs, this.myDataSource);
    Also, add an id="peopleTable" attribute to the <table> tag.
    <table id="peopleTable" border="1" cellpadding="10">
  5. The DataSource also requires that we specify the responseType and responseSchema. The responseType is used to determine which parsing algorithm to use, and the responseSchema values determine what data gets parsed out for use by the calling widget. (For more information, see Setting responseType and responseSchema in the official documentation. Type in the following beneath the instantiated DataSource:
    // Instantiate the DataSource
    this.myDataSource = new YAHOO.util.LocalDataSource(YAHOO.util.Dom.get("peopleTable"));
    this.myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
    this.myDataSource.responseSchema = {
        fields: [
            {key:"id"},
            {key:"firstName"},
            {key:"lastName"},
        ]
    };
  6. Finally, we need to ensure that the elements we've referenced in the markup (i.e., <div id="myContainer"> and <table id="peopleTable">) actually exist in the DOM before the YUI elements (i.e., the DataSource and DataTable) are instantiated. This can be done by setting a listener to trigger element instantiation once the window load DOM event fires.

    To do this, we can wrap the above code (the DataTable, the DataSource, and column definitions) in a Listener object that waits until the window load DOM event fires (changes in red).
    YAHOO.util.Event.addListener(window, "load", function() {
    
        // Create column definitions
        var myColumnDefs = [
            {key:"id",label:"ID", sortable:true},
            {key:"firstName",label:"First Name", sortable:true},
            {key:"lastName",label:"Last Name", sortable:true},
        ];
    
        // Instantiate the DataSource
        this.myDataSource = new YAHOO.util.LocalDataSource(YAHOO.util.Dom.get("peopleTable"));
        this.myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
        this.myDataSource.responseSchema = {
            fields: [
                {key:"id"},
                {key:"firstName"},
                {key:"lastName"},
            ]
        };
    
        // DataTable constructor
        this.myDataTable = new YAHOO.widget.DataTable("myContainer", myColumnDefs, this.myDataSource);
    
    });

Apply a YUI Skin

At this stage, all of the functionality is in place. You can run the application now to see its current status.
Records displayed without stylesheet
Click on the column headers to test the table's sorting capability. Everything is in working order, however the DataTable's appearance is understandably a little disappointing.

The YUI toolkit, like other toolkits, provides a simple and effective way to manage the visual presentation of its components. It contains a default theme, or "skin", that you can refer to, called "Sam". For more information, see Understanding YUI Skins.

There are 2 steps involved in using a YUI skin:

  1. Link to the skin's CSS file.
  2. Add the skin's class name to the page.

Recall that we copied over the link to the CSS file from the YUI Dependency Configurator, and the listPerson.jsp page now contains the line:

<!-- Individual YUI CSS files -->
<link rel="stylesheet" type="text/css" href="resources/yui_2.6.0/build/datatable/assets/skins/sam/datatable.css">
All that remains is adding the skin's class name to the page. Modify the <body> tag as follows:
<body class="yui-skin-sam">

If you run the application now, it looks much better:
Records displayed with skin

One final task is to apply optional configuration attributes to the DataTable, for example adding a caption to the table, as shown in the original screenshot above, or specifying which column is sorted upon page load. You can do this by adding a fourth argument to the DataTable constructor, and placing configuration values within curly brackets (changes in red):

// DataTable constructor
this.myDataTable = new YAHOO.widget.DataTable("myContainer", myColumnDefs, this.myDataSource,
    {caption:"List of Persons currently in Database", sortedBy:{key:"id",dir:"desc"}}
);

For more information on optional configuration attributes, visit the DataTable API and scroll down to view Configuration Attributes.

The completed listPerson.jsp page is as follows:

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <link rel="stylesheet" href="css/demo.css" type="text/css" media="screen">

        <!-- Individual YUI CSS files -->
        <link rel="stylesheet" type="text/css" href="resources/yui_2.6.0/build/datatable/assets/skins/sam/datatable.css">
        <!-- Individual YUI JS files -->
        <script type="text/javascript" src="resources/yui_2.6.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
        <script type="text/javascript" src="resources/yui_2.6.0/build/element/element-beta.js"></script>
        <script type="text/javascript" src="resources/yui_2.6.0/build/datasource/datasource.js"></script>
        <script type="text/javascript" src="resources/yui_2.6.0/build/datatable/datatable.js"></script>

        <script>
            YAHOO.util.Event.addListener(window, "load", function() {

                // Create column definitions
                var myColumnDefs = [
                    {key:"id",label:"ID", sortable:true},
                    {key:"firstName",label:"First Name", sortable:true},
                    {key:"lastName",label:"Last Name", sortable:true},
                ];

                // Instantiate the DataSource
                this.myDataSource = new YAHOO.util.LocalDataSource(YAHOO.util.Dom.get("peopleTable"));
                this.myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
                this.myDataSource.responseSchema = {
                    fields: [
                        {key:"id"},
                        {key:"firstName"},
                        {key:"lastName"},
                    ]
                };

                // DataTable constructor
                this.myDataTable = new YAHOO.widget.DataTable("myContainer", myColumnDefs, this.myDataSource,
                    {caption:"List of Persons currently in Database", sortedBy:{key:"id",dir:"desc"}}
                );

            });
        </script>

        <title>Yahoo! UI Demo</title>
    </head>

    <body class="yui-skin-sam">
        <h1>Yahoo! UI Demo</h1>

        <div id="myContainer">
            <table id="peopleTable" border="1" cellpadding="10">
                <thead>
                    <tr>
                        <th bgcolor=>ID</th>
                        <th bgcolor=>FirstName</th>
                        <th bgcolor=>LastName</th>
                    </tr>
                </thead>
                <tbody>

                    <c:forEach var="person" begin="0" items="${requestScope.personList}">
                        <tr >
                            <td>${person.id}  </td>
                            <td>${person.firstName}  </td>
                            <td>${person.lastName}  </td>
                        </tr>
                    </c:forEach>

                </tbody>
            </table>
        </div>

        <br>
        <a href="createPerson.jsp"><strong>Create a Person Record</strong></a>
    </body>
</html>


Summary

 

In this exercise, you have examined how data from a backend database can be presented in a browser using a YUI DataTable.

Specifically, you've explored how it is possible to locate the database of an application that uses JPA with a data source by using the GlassFish Admin Console.

You then connected to the Java DB database using the IDE's Services window and made modifications to the table directly.

Finally, you applied the YUI DataTable to the HTML table by adding YUI libraries to your project, and adding YUI-specific code to configure and link the DataTable to the HTML markup.

 

Back to top
To summary