<< Contents< PreviousNext >Index >> Lutris Technologies, Inc.


 

Chapter 4
Tutorial: Building Enhydra Applications

 

 

This chapter describes how to build a Enhydra application from the ground up, and provides important tips on Enhydra application development. It begins with using the application wizard to create a starting framework, and leads you through using XMLC to expand the application, then adding simple database access.

If you are already familiar with the basics of Enhydra, you may want to skip to the next chapter, "The DiscRack Example Application," for a look at an application with more advanced features.

Note: In this tutorial, you are often instructed to enter commands. On UNIX platforms, you can enter the commands in any shell. On Windows, you must enter the commands in a Cygwin shell window.

Creating Your First Application

The application wizard (sometimes referred to as "newapp") is a quick way to get up and running with Enhydra. It is a command-line tool that generates the basic Java files and directory structure for a new application.

First, create a directory to contain your new application, and name it anything you want, for example "myapps." Then, open a shell window and make the new directory the current directory, for example:

Now, run the application wizard by typing newapp followed by the name of the application to create. In this case, call it simpleApp:

The application wizard will create a new directory called simpleApp. This directory is sometimes referred to as the application root directory.

Make this the active directory:

Notice that the application wizard created the following in this directory:

Building the Application

Enter the make command to build the application:

This will create two sub-directories in the application root directory:

The top-level make file, Makefile, contains directives that tell make to recursively descend the application directory tree, following the directives of the make file in each sub-directory. It also has an INCLUDE directive that references config.mk, which in turn references <enhydra_root>/lib/stdrules.mk, a large make file shared by all Enhydra applications.

When you build the application, make compiles the files in the simpleApp/simpleApp source directory and creates a corresponding directory structure in the classes directory. It then combines those classes into a jar (Java archive) file and places the jar file into the output directory along with the configuration files needed to run the application.

To start the application, enter the following commands:

Now, to access the application, enter the following URL in your browser's location field: http://localhost:9000.

You will see the following page in your browser:

[Picture]

You have just built and run your first Enhydra application!

Now hit Ctrl+C in the shell window to stop the Enhydra process.

How It Works

The application created by the application wizard provides a simple example of how Enhydra works. Look at the file myapps/simpleApp/simpleApp/presentation/Welcome.html, which contains a few dozen HTML tags. Notice tags such as these:

At runtime, Enhydra replaces the content of the SPAN tag with a date value. The text in there is just a placeholder; it will never appear at runtime. Note the period outside of the SPAN tag will not be replaced. Thus, the sentence will always end with a period.

Look also at the Welcome.java file in the same directory. In particular, notice these lines of code:

When you build the application, XMLC finds the SPAN tag in the HTML and recognizes the ID attribute with value "Time". It creates a Java class called WelcomeHTML with a method setTextTime() that the application uses to modify the text content of the SPAN tag. In general, XMLC will create a setTextXXX() method for each SPAN tag with ID attribute value "XXX".

Then, at runtime, the application replaces the original text content of the SPAN tag with a string representation of the current date. Then, the call to writeHTML() writes the document out to the HTTP response, looking something like this:

For a more detailed explanation of XMLC, see "Using XMLC."

The Directories and Files in SimpleApp

Let's take a closer look at the directories and files in the simpleApp directory:

The finished Enhydra application includes the jar file and the configuration file. The make program also copies the multiserver configuration file and the start script to the output directory to make it easier to run the application.

Configuration Files

The application configuration files contain critical information that determine how an Enhydra application runs:

By editing the configuration files, you can change the various settings contained in the files, as explained below.

Note: The application wizard creates "input" versions of the two configuration files in the app_root/appName directory; for example, simpleApp/simpleApp. These are the files that you should edit. Running make creates "runtime" versions of the files in the app_root/output directory, for example simpleApp/output. You should not edit these versions of the files, because they will be over-written each time you re-build the project.

The Multiserver configuration file contains information that the Multiserver uses to run the application, including:

The application configuration file contains the following important application-specific information:

    When a browser requests the application URL, this is the URL (typically a presentation object) that the Multiserver returns by default.

Using XMLC

XMLC, the Extensible Markup Language Compiler was introduced in Chapter 2, "Overview." It is a powerful tool that you can use to create applications that have a clean separation between the user interface and the back-end programming logic.

In general, XMLC can work with XML pages, but for practical reasons we are going to focus on how it works with HTML pages. XMLC parses an HTML file and creates a Java object that enables an application to change the HTML file's content at runtime, without regard for its formatting. The Java objects that XMLC creates have interfaces defined by the Document Object Model (DOM) standard from the World Wide Web Consortium (W3C).

For simplicity, the remainder of this chapter will refer to HTML documents, but in most cases the discussion can be extended to include XML documents in general.

Adding a Hit Counter

To get a feel for how XMLC works, you are going to extend your application to display a "hit counter" that shows the number of users who have accessed it.

Find the files Welcome.html and Welcome.java in the presentation directory.Add the following line of HTML to Welcome.html before the closing </CENTER> tag:

The ID attribute tells XMLC to generate an object corresponding to the SPAN tag, so that it can replace the text "no count" at runtime.

Now, add the two lines of code indicated below to Welcome.java in the same directory.

Build the application by running make from the top-level simpleApp directory. Then restart Enhydra:

Building the application with make runs XMLC on all the HTML files in the application, in this case, just Welcome.html.

Test the application by loading http://localhost:9000 in your browser. You will see this:

[Picture]

Notice that the page now displays the number of times it has been accessed. Reload the page several times to verify that it works correctly.

The application is doing two things:

Recall that the presentation manager instantiates a presentation object for each request. So, the Welcome class is instantiated once per browser request. But because hitCount is a static property, it is shared by all Welcome objects, and its value gets incremented by each request.

In the same way that it added a setTextTime method for the <SPAN ID="Time"> tag, XMLC creates a setTextHitCount method for the <SPAN ID="HitCount"> tag. The application then uses the setTextHitCount method to write the value of hitCount into the page, within the corresponding SPAN tag.

Note: XMLC creates the WelcomeHTML class, but by default it deletes the Java source file.

Understanding the DOM

HTML documents have a hierarchical or tree-like structure that can be modeled in an object-oriented language such as Java. The Worldwide Web Consortium's standard for the XML/HTML object model is called the Document Object Model (DOM).

Enhydra applications use the DOM to manipulate HTML content at runtime. For example, consider the following HTML:

This HTML snippet has a TABLE tag that contains TR tags, that in turn contain TD tags containing text. This defines a tree-like hierarchy, as illustrated in Figure 4.1

[Picture]

Figure 4.1    DOM tree of HTML

Each box or ellipse in the above figure is a node in the tree. The node above a node in the hierarchy is called is parent; the nodes below are called its children. Some nodes (like HTML tags) have attributes, for example a table cell has a background color attribute. The W3C defines packages and interfaces that mirror the object hierarchy of nodes in an HTML document. In addition, XMLC includes an API for changing attribute values.

You could use code like this to set the color of one of the table cells:

The class HTMLTableElement and setBgColor() came from the W3C packages, and getElementCellOne() came from XMLC. This code illustrates one important thing XMLC does--create methods to access nodes in the DOM. XMLC generates the getElementXXX() methods that return objects corresponding to tags with ID attributes. You could change the color of a table cell with the W3C classes alone, but your code would have to traverse the DOM tree, so it would have been more laborious.

SPAN and DIV Tags

SPAN and DIV are HTML tags that you may not be familiar with. They are typically used to apply styles using Cascading Style Sheets. Outside of that, they are largely ignored by browsers. XMLC makes extensive use of them, however.

Use the SPAN tag to enclose a block of text that you want to replace at runtime. In general, a SPAN tag can enclose any text or in-line tag. An in-line tag is any tag that does not cause a line break in the layout, for example A (anchor) or B (bold) tags. Do not use SPAN tags to enclose other tags, such as TABLE or P (paragraph). Use the DIV tag to enclose block tags, such as TABLE, that do cause a line break in the HTML layout.

Using XMLC From the Command Line

Previously, you have run XMLC implicitly when you built the project with make. To run XMLC from the command line, you must have the enhydra.jar file on your CLASSPATH.This is something that the make files automatically do for you.

Set your CLASSPATH with one of the following commands:

UNIX: export CLASSPATH=<enhyra_root>/lib/enhydra.jar:.

Windows: export CLASSPATH=<enhydra_root>/lib/enhydra.jar\;.

The basic command-line syntax of XMLC is:

where options is a set of command line options, and file is the name of the input file. There are several dozen command line options. In this section we introduce three immediately useful ones: dump, class, and keep.

The -dump Option

The -dump option makes XMLC display the DOM tree for a document. This is primarily useful as a learning tool; once you are familiar with XMLC you will rarely use it.

Create a new file called Simple.html in the simpleApp/simpleApp/presentation directory. Add the following HTML to it:

Change to the presentation directory and enter this command:

XMLC displays the following in the shell window:

Each line shows the DOM object name followed by a colon and then the corresponding HTML tag; if the tag has attributes they are listed following the tag in name/value pairs. For instance, HTMLHeadingElement is the DOM name for the H1 tag, and it has an id attribute with value "MyHeading." The level of indenting shows the object relationships, so for example, you can see that the first HTMLHeadingElement is the child of HTMLBodyElement.

The -class and -keep Options

By default, XMLC creates a class with the same name as the HTML file. So, for Simple.html it would create Simple.java. Use the -class option to specify a name for the class that XMLC creates.

By default, XMLC deletes the Java source file that it creates; leaving only the compiled class file. Use the -keep option to keep the Java source file. The source file is useful primarily for understanding how XMLC and the DOM API works.

To create a Java object named SimpleHTML for the HTML file Simple.html, and to keep the Java source, enter this command:

XMLC generates two files: SimpleHTML.java and SimpleHTML.class.

Open SimpleHTML.java. At the beginning of the file, you will see two methods, getElementMyHeading() and getElementTime(). XMLC recognized the ID attributes of the heading and SPAN tags and generated these methods. XMLC also generated the method setTextTime() for the SPAN tag. Peruse this file to get an idea of the object that XMLC creates for a very simple document.

You're done exploring how XMLC works for now. But keep your Simple.html file, because you are going to use it later in this tutorial.

Enhydra Programming

This section covers some more topics essential to Enhydra application development:

Maintaining Session State

Since HTTP is a stateless protocol, an application that needs to keep user-specific information across multiple requests must perform session maintenance. For an overview of how Enhydra performs session maintenance, see "Session Manager."

Think of the user's session as a container in which the application can store any information associated with a particular user. The class that you use as the container is com.lutris.appserver.server.session.SessionData; it is similar to a hash table in that it has a set() method to which you pass a string key and an object to store, and a get() method that returns the object, given the string key.

Enhydra matches a user to a particular SessionData object with a session key, a very long randomly-generated character string. When the Enhydra session manager first creates a SessionData object for a user, it generates a session key and stores it in its internal data structure. Enhydra also gives the session key to the client, either passed as a cookie or appended to the URL. The next time the client makes a request, the session manager uses the key to find that user's SessionData object.

Generally, you don't need to worry about the session key--Enhydra handles all those details for you "under the hood." You do, however, need to keep track of the keyword strings that you use to get and set each object you want to save to the session.

To help you understand session maintenance, you are going to enhance your application so that the Welcome page displays the number of times a particular user has accessed it, in addition to the total "hits" on the page. For fun, you'll also display the session key on the page.

Add these four lines of HTML just before the closing </CENTER> tag in Welcome.html:

Now add the following code to Welcome.java. Add this import statement:

Add this member property to the Welcome class (just after hitCount):

The string "HITS" is the keyword that the application will use to save and recall the hit count information.

Now add the following code to the run() method, just before the call to comms.response.writeHTML(). You can find this code in the <enhydra_root>/doc/samples/SessionMaint.java file.

This code begins by calling getSessionData().get(hits) to get the value stored for the keyword string "HITS." Because SessionData stores only generic java.lagn.Objects, you have to type cast it to Integer. If the object has not been previously stored in the session, the code creates a new Integer of value one. If it does exist, it is incremented.

The code then saves the Integer object back into the session with setSessionData().set(hits, personalHits) and writes the value into the web page with getSessionKey(). Normally, you would not need to deal with the session key, but for curiosity's sake this example shows you how to display it.

Rebuild and start the application, and access the page with your browser. The page now looks like this:

[Picture]

The page now displays the total number of hits as well as the number of hits from a particular client. Since you are running the application on your Localhost server, it is not accessible to any other clients, so these two numbers will always be the same. However, if it were running on a "real" server, you would see different numbers depending on how many times you had accessed the page versus the total number of hits. Notice also that the session ID string always stays the same.

Adding a New Page to the Application

Next, you are going to add a new page (HTML file and presentation object) to your application. You're going to use the little HTML file you created previously, Simple.html. In addition to learning how to add a page, you're also going to play around with the DOM a little bit to become more familiar with it.

First, you need to create a new presentation object. Copy the file Welcome.java, and call it Simple.java. Edit Simple.java and change the name of the class from Welcome to Simple, and then remove all the session-related code you added to Welcome. Change all the occurrences of WelcomeHTML to SimpleHTML; also change the welcome identifier to simple.

Now, you have a "stripped down" presentation object. The run method should look like this:

Add the following statements at the top of the file, after the other import statements:

Now add the following lines just before the last statement in the run() method:

This code does the following:

You could have done the same thing by putting a SPAN tag around the text in the heading, since then XMLC would have generated a setTextMethod() that you could have then called in the code, but this example illustrates how to do it with the DOM.

Note: This code performs some low-level DOM manipulation that you should normally not do in your application, because it violates the separation of presentation and business logic. It is only presented here to help explain the DOM.

Finally, edit Makefile in the presentation directory and add the new files to the CLASSES and HTML_CLASSES variables, to make them look like this:

The HTML_CLASSES variable is passed to the XMLC -class option to make it create the specified classes, just as you did on the command line. The Lutris convention is to create fooHTML class for a file foo.html. This convention is defined in <enhydra_root>/lib/stdrules.mk.

Save all the files and run make in the presentation directory to build the package.

To create a link from the Welcome page to your new page, add the following HTML at the bottom of Welcome.html:

If you have not done so already, stop your Multiserver by hitting ctrl-C in the shell window, and build the application from the top level:

Now access the application from your browser, as you did before. Click on the link "Go to simple page" to view the Simple PO. You will see the following rather uninteresting page:

[Picture]

Don't worry, though: you're going to make this page more interesting in the next section.

Populating a table

Another common task in web application development is how to populate an HTML table with dynamic data. This section discusses populating a table using a static String array as the data source; in a later section, you will modify the code to get data from a database.

Follow these steps to populate a table:

Create the table in HTML

Edit the file presentation/Simple.html in your simpleApp project. Add the HTML shown below just before the end of the BODY tag.

Note: If you don't want to type in all this HTML, you can copy and paste it from <enhydra_root>/doc/GettingStarted/samples/TableCode.html.

This HTML contains a table with a single "template" row (TR tag). Notice that both this row and the SPAN tags enclosing the cell contents have ID attributes. This is called a template row, because it is used as a model from which you construct further rows of the table.

Programmatically Populate the Table

Now copy the file <enhydra_root>/doc/GettingStarted/samples/TableCode.java. into your application's presentation directory, and rename it Simple.java. If you like, you can save your old Simple.java to Simple.sav for future reference.

Now, look at your new Simple.java: In addition to the standard features of a presentation object, the first thing you'll notice in this code is a member property of that is an array of strings representing the content the application will use to populate the table. This array takes the place of a database result set for this example:

The next new section of code gets the document objects for the table elements:

The next section of code removes the ID attributes from these objects. The reason for this is that the DOM requires that each ID in the document be unique; when you make a copy of the table row, you would otherwise have duplicate IDs. The removeAttribute() method removes the attribute with the specified name:

Then, a call to getParentNode() gets a reference to the table document object, which you'll be using later:

Next comes the heart of the code, a for loop that iterates through each "row" in the "result set," puts text in each cell in the table row, and then appends a copy (or clone) of the row to the table:

That last statement is crucial: The cloneNode() method creates a copy of the Node object which calls it, in this case, templateRow. The boolean argument determines if it copies only the node itself or the node and all its children, and their children, and so on. In this example, the argument is true, because you want to copy the row and its child nodes (the table cells and the text inside them).

Finally, removeChild() removes the template row from the table. This ensures that the "dummy data" in the template does not show up in the runtime page.

Rebuild and Run the Application

Now rebuild the application, and load the page in your browser. You should see the following result:

[Picture]

Adding a Business Object

So far, your application has three objects: the SimpleApp application object, and two presentation objects, Welcome and Simple. Now, you are going to add a business object that you will use it in the following sections. This will not change what the application displays.

The business object represents a list of discs; this is not terribly useful, but it does suffice to illustrate a basic role of business objects as you proceed.

Create a new file called SimpleDiscList.java in the business directory, simpleApp/simpleApp/business. It's in your application's business package, so the first line in the file will be:

Now, add the following lines (cut and paste the array initializer from the Simple class, but be sure to add the underscore in front of the identifier):

To ensure that this file gets compiled when you build the project, edit the make file in the business directory, and add the name of the file to the CLASSES variable:

This make file is automatically included by the top-level make file, so that is all you have to do to add the file to the project. Make sure the file compiles by entering make in the business directory.

Now, back in the presentation directory, edit Simple.java as follows:

Rebuild and test your application.

You won't see anything different, but you have extracted some functionality out of the presentation object into the new business object. This will come in handy in an upcoming section: when you replace the static array with a real database query, you won't have to change your presentation class, because the business object provides a buffer between it and the data layer.

Connecting the Application to a Database

Enhydra uses Java Database Connectivity (JDBC), a standard Java API, to communicate with databases. Enhydra can connect to any JDBC-compliant database, such as Oracle, Sybase, Informix, Microsoft SQL Server, PostgreSQL, and InstantDB.

Before you can proceed to connect the application to a database, you are going to take a brief detour to lay some groundwork. In particular, you are going to:

Creating a Database Table

The remainder of this section requires the existence of a specific table in your data, so you need to create that table before proceeding. Most databases provide a tool for directly executing SQL statements. For example, Oracle supplies SQL*Plus. Use this tool to execute the provided SQL file and create the table in your database. The SQL file is in <enhydra_root>/doc/GettingStarted/samples/tutorial_create.sql

Here is the command for Oracle SQL*Plus:

This SQL file contains a CREATE TABLE statement to create a simple table, LE_TUTORIAL_DISCS, and some INSERT statements to populate it with data. You are going to use this table in the forthcoming sections of the tutorial.

If you are using a database other than Oracle, refer to your database documentation for instructions on how to execute a SQL file or create tables.

Establishing a JDBC Connection

Before you can create a database application, you need to establish a JDBC connection from your system to the database server, which may be running on a different system.

This section shows you how to write a simple stand-alone program to establish a JDBC connection to database server. Starting with a stand-alone program enables you to isolate any problems that occur.

This example uses an Oracle database. If you are using a different database, refer to your database's documentation for more specific information

Note: If you have already configured JDBC on your system, you can skip this section.

  1. Configure your database to "listen" on a specific TCP port. Most database servers listen on a certain port by default (for example, Oracle uses port 1521). See your database's documentation for details.

  2. Install the JDBC driver for your database. This consists of a zip or jar file containing the database-specific JDBC classes, for example the Oracle JDBC driver is classes111.zip. See your database's documentation for details.

    Windows: The Cygnus tools require the JDBC driver to be on the C drive, so make sure the JDBC driver library is on the C drive.

  1. Determine the connection string for your database. The connection string contains:

    • The name of the system running the database server

    • The TCP port on which the database server is listening

    • The name of the database instance

Every database has its own format. For example, the connection string for the Oracle driver is

where db_host is the name of the database server, xxxx is the port number (1521, by default), and db_inst is the name of the database instance. You will also need your database username and password. Use these values as illustrated in the call to DriverManager.getConnection() in the code below

Use the following simple program to test your JDBC connection:

To use this program:

  1. Create a directory with a name such as /tmp/jdbcTest.

      cd /tmpmkdir jdbcTestcd jdbcTest

  2. Copy the above code from <enhydra_root>/doc/GettingStarted/samples/JDBCTest.java into the new directory.

  3. Edit the file to put in your connect string, username and password. These appear in the call to getConnection(), the second statement in the try block.

  4. Compile the file:
      javac JDBCTest.java 
      

  5. Set your CLASSPATH so the JVM can find your JDBC driver and the test program. For an Enhydra application, this would normally be performed in an application's start script; however, since this is a stand-alone test application, you'll just do it in the shell window. On UNIX, enter this command:
      export CLASSPATH=<path_to_your_JDBC_driver>:. 
      

    On Windows, enter this command:

  1. Run the program:
      java JDBCTest 
      

If you have populated the table as instructed previously, you will see the following in the shell window:

If there was an error, you will see some exception messages in the shell window that should help you isolate the problem. Also, refer to your database's JDBC documentation or the Enhydra mailing list.

Configuring the Application to use JDBC

To make the JDBC classes available to your Enhydra application, you must put the JDBC driver in the CLASSPATH system variable. To do this, set CLASSPATH in the application's start script. Note there are two copies of the start script: one in the application's source directory and one in the output directory. As with application.conf, building the application overwrites the one in the output directory.

Note: Enhydra has its own class loader, so if you put the JDBC driver in the CLASSPATH by specifying it in the application's configuration file, the driver will not work.

So, edit the file simpleApp/simpleApp/start and add these lines just before the last line in the file:

where JDBC_LIB is the JDBC driver library (generally a jar or zip file), including the file path. For example,

Be careful not to put any blank spaces in this line, since they will prevent it from working properly.

Configuring the Database Manager

Now that you have verified your JDBC connection, you need to provide the database connection parameters to your application. You do this in the application's configuration file, appName.conf. In this example, the file is simpleApp.conf. The make utility copies this file to the output directory after every build, so be sure to edit the file in simpleApp/simpleApp, not the version in simpleApp/output.

Open simpleApp/simpleApp/simpleApp.conf in a text editor. Add the following lines to the bottom of the file:

Note: This is an example of the configuration file for Oracle; for information on configuring for other databases, see Appendix A, "Database Configuration."

Change all of the items shown in bold to match your connection parameters as follows:

Make sure there is a carriage return at the end of the file; this is required for the file to work properly.

After you edit the configuration file, run make to propagate the changes to the file in the output directory.

Adding Data Access

Now that you have laid the groundwork, you are ready to add data access to simpleApp. This section describes how to add a simple data object with embedded SQL that replaces the static array used in "Populating a table." The next section, "Using DODS," describes how to build a "real" data layer for the application using DODS.

First, you are going to create a data object that queries the database. Copy the file SimpleDiscQuery.java from <enhydra_root>/doc/GettingStarted/samples to your data layer, that is, the simpleApp/simpleApp/data directory. Remember to edit the make file in the data directory to add the file to the CLASSES variable, just as you did in "Adding a Business Object."

Take a look at SimpleDiscQuery.java. In particular, notice the import statement right at the top:

This tells you right away that this class is going to use JDBC. In addition to the constructor, there is only one other method, query(), where the object performs most of its real work.

The constructor has essentially one statement:

This statement tells the Enhydra database manager to allocate a database connection. Then, the query() method calls executeQuery on the connection to execute the SQL query statement:

The remainder of the code in query() iterates through the result set returned by the SELECT statement, and returns it in the form of a Vector of Vectors. Although each row is known to contain only four elements (since there are four columns in the table), the number of rows is unknown in general, which is why the method returns a Vector.

However, you will recall that the presentation object Simple expects the data to be in the form of a two-dimensional array of Strings. So, the SimpleDiscList needs to perform some conversion.

Edit the file for the business object you created previously, SimpleDiscList.java.

Now, find the file <enhydra_root>/doc/GettingStarted/samples/SimpleDiscList.java. You can simply replace your old SimpleDiscList.java with this file, or if you prefer, you can make the changes manually:

  1. Add two import statements at the top:
      import simpleApp.data.SimpleDiscQuery;

      import java.util.*;

  2. Add a member variable corresponding to the data object:
      SimpleDiscQuery _sdq;
      

  3. Replace the body of the getDiscList() method with the code in the new file. It converts the Vector of Vectors returned by query() to a two-dimensional String array that the presentation object expects.

Notice that you did not have to change the presentation object at all. The data object provides a buffer between the PO and the data object.

Now, build the application from the top level. When you get it to compile, try running it. If everything is in place, you will see the following:

[Picture]

Notice the discs displayed in the table have the values from the database, not the static array. You've created your first database query page!

Using DODS

The Data Object Design Studio (DODS) is an graphical object-relational mapping tool that generates SQL code to create tables in a database and the corresponding application code to access the tables. DODS creates code that is specific to different databases, so you don't have to learn the nuances of each database. DODS also handles common issues such as transactions and data integrity.

DODS is most useful when you are creating a database from scratch, or when you are free to modify the database schema, as explained in "Loading the Schema."

You are not required to use DODS in developing a Enhydra database application, but it does significantly simplify the process.

Introduction

This section introduces DODS and explains how to use it to create the database schema and associated data objects for the DiscRack application (see Chapter 5, "The DiscRack Example Application"). This example uses an Oracle database.

Start DODS by entering the following command:

Note: If DODS does not run when you enter this command, you need to set your PATH. See "Setting the PATH Environment Variable."

You will see the DODS graphical interface. Open the DODS file for the DiscRack project by choosing File | Open, and selecting<enhydra_root>/examples/DiscRack/discRack.doml.

DODS will show the DiscRack data model:

[Picture]

Figure 4.2    DODS with the discRack.doml loaded.

The DODS window has three sub-panels:

The schema of the discRack database is pictured in Figure 4.2. DODS shows the features common to both the database schema and the object model. For example, the disc data object has title and artist fields, that are the properties (members) of the Java class as well as the columns of the corresponding database table.

DODS creates Java code for object operations and SQL code for database operations, for example the one-to-many relationship between person and discs.

[Picture]

Figure 4.3    Disc Rack object-model/schema

Creating Data Objects

Now you are going to create the data layer for the discRack application from scratch.

  1. Create a new data model by choosing File | New. DODS will close any open data model file and start a new one containing a single package, named "root" by default.

  2. Select your database type. Using the Database menu, select your database type. For example, if you are using Oracle, choose Database | Oracle. This will ensure that the SQL statements that DODS generates have the correct syntax for your database.

  3. Now create the package hierarchy.

    Begin by changing the name of the root package. In the lower left panel, select the root folder then choose Edit | Package. Enter the name of this application in the dialog box, "simpleApp," then hit Enter.

    Add the data package: select the discRack folder, choose Insert | Package, type "data," then hit Enter.

    Similarly, create disc and person directories as subdirectories of the data directory. Recall that package names in Java begin with a lowercase letter. The package panel (in the lower left of the window) should now look like this:

    [Picture]

  1. Create the Person data object.

    Select the person package in the lower left pane then choose Insert | Data Object. You will see the Data Object Editor dialog box.

    [Picture]

    Change the defaults as follows:

    Leave the rest of the defaults and click OK. This will create both a Person table in the database and a Person object in the Java application. Note the class is uppercase "Person" while the package name is lowercase "person."

    Now add the login attribute to the Person data object. Select the Person data object (indicated by a blue dot) and click Insert | Attribute. The Attribute Editor window comes up:

    [Picture]

    Change the defaults as follows:

    Leave the rest of the defaults and click OK.

    Notice that the attributes appear in the attribute panel in the lower right of the DODS window. The fields show the different options you can set in the Attribute Editor; for example, the yellow "Q" means that the data object can be queried. Move the cursor over the other symbols to see what they represent.

    Repeat this procedure to add three more attributes to the person data object: "password," "firstname," and "lastname." You may want to use the Add Attribute button on the toolbar.

  1. Create the Disc data object similarly to the procedure in the previous step. Add the following attributes: title, artist, and genre.

    Adding the owner attribute is a little more complicated because there is a one to-many relationship between Person and Disc based on the owner attribute. Select the Disc data object and choose Insert | Attribute. Change the name to Owner. Click on the Java tab and then on the Java Type list box. Scroll down and select "discRack.data.person.PersonDO."

    Click on Database tab. Select "Can be queried" and "Referenced DO must exist." Choose OK to close the Attribute Editor.

    You will notice a red arrow in the interface between the Disc object and Person object showing that Disc uses Person. Notice the attribute pane displays icons indicating that the owner attribute has an object reference and a referential constraint.

  1. Save and build the data model.

    Save the data model file. DODS stores the data model specification in a doml file, with an XML-like syntax. Select File | Save and choose a location for the doml file. Save it in the top level project directory.

    Now that you have defined all the data objects, DODS is ready to generate and compile the code. The "Build All" command causes DODS to overwrite the existing data directory with all the new information from the data model, so if you want to save your old data layer code, copy it to another directory.

    Now, the big moment you have been waiting for... select File | Build All. The "Destroy and Create New DODS Directory" dialog box appears. Select the data directory of your simpleApp project. Choose the Re/Create Directory button. You will see the following warning dialog box:

    [Picture]

    Choose Yes, and the build will begin. DODS will align the directory structure in the GUI with the directory structure in the project, generate Java and SQL files, and then run make to build the data layer.

    As it proceeds, DODS displays messages in a dialog box:

    [Picture]

    If the build is successful, you will see the message "DODS BUILD COMPLETE." If the build fails, look at the messages in the output screen. Verify that the paths of the files are correct. You can also search the doml file for clues, since it is easy to read.

DODS generates the following files in the data directory:

Each data object directory contains Java source files to create four classes. For example, the person data object contain personDO, personQuery, personDataStruct, and personBDO. The data object and the query classes are the most commonly used classes.

DODS also generates make files for the data layer. This allows you to compile the data layer independently or along with the entire project. The empty classes directory is only used if you compile the data layer separately.

Loading the Schema

The next step in the process is to run the SQL script that DODS generated to create the tables in the database. Figure 4.4 illustrates the complete schema generated by DODS:

[Picture]

Figure 4.4    Disc Rack database schema generated by DODS

Notice there are some differences from the original database schema:

The OID column is the primary key for each table created by DODS. The application code generated by DODS ensures that every row has a value of OID that is unique within the database. Whenever a new row is added to a table, the application generates a unique Object ID to put in the OID column; it uses the OBJECTID table to keep track of the next Object ID to be assigned.

DODS application code uses the VERSION column in each table to ensure that the data that an application is updating is accurate. Because many users can be accessing the database simultaneously, a record can change between the time an application retrieves it when it attempts to change the record.

Every time an application updates a row, it increments the VERSION column in the database. The application qualifies updates on both the VERSION and OID columns--if it finds that there are no rows that have the expected values, then it knows that another process has changed the row it is trying to update, and it throws an exception. You can catch the exception in your application code to handle such situations appropriately.

Procedure

To load the SQL scripts that DODS creates, follow these steps:

  1. Edit the create_tables.sql file in the <DiscRack_root>/discRack/data directory.

    The file contains the SQL CREATE TABLE commands to create the PERSON, DISC, and OBJECTID tables:

    Note: DODS may generate SQL files that are not fully compatible with your database server. You may have to edit the file manually to remove extraneous text that may be causing errors when reading the file. For example, for Oracle, you may have to remove extra blank lines.

    You can configure many things about the SQL that DODS generates in the configuration file <enhydra_root>/dods/dods.conf. For example, by default DODS generates C-style comments, but you can change the style of comments if your database requires a different format.

  1. Load the tables into the database. For example, the command for SQL*Plus is:
      SQL> @<enhydra_root>/examples/DiscRack/discRack/data/create_tables.sql
      

  2. Add some dummy data to the database for testing purposes. The file <enhydra_root>/doc/GettingStarted/samples/tutorial_insert.sql contains some sample data, including one person and several discs. Here is the command for SQL*Plus:
      SQL> @/<enhydra_root>/doc/GettingStarted/samples/tutorial_insert.sql
      

Using the DODS Data Objects

Now all you need to do is modify the business object, SimpleDiscList, to use the DODS data objects instead of the simplified one you created previously. Replace your old SimpleDiscList.java with the file <enhydra_root>/doc/GettingStarted/samples/SimpleDiscList.java.

The main difference between the old and new objects is in the getDiscList() method; here is the heart of it:

This code uses the DiscQuery and DiscDO objects in the data.disc package to get data from the database. DiscQuery provides a set of methods for querying the DISC table; by default it performs the equivalent of SELECT * FROM DISC. It has methods that you can use to qualify the query (the WHERE clause of the SELECT statement) and order the result set. The getDOArray() method returns an array of DiscDO objects returned from the query.

The DiscDO object is the basic data object representing a row of data from the DISC table. It has getter and setter methods for each column in the table. The above code only uses the getter methods getTitle(), getArtist(), getGenre(), and getIsLiked(), which returns a boolean value. All of them except getIsLiked() return a string, so the method performs some simple logic to translate the boolean value to the appropriate string.

Run the Application

The last step is to recompile the project, by running make at the top level. Then start the multiserver with the start command, and load http://localhost:9000 in your browser.

When you access the Simple page, you should see the following in your browser:

[Picture]

If you don't see this page, check the following:

  1. Look in the discRack.conf file in the output directory to be sure that the database settings are correctly listed.

  2. Check the output displayed in the shell window when you start the Multiserver for errors. If the database settings are in discRack.conf and the JDBC driver is in the application's CLASSPATH, there should be no errors listed when multiserver starts.

  3. Re-run the JDBC connection test to verify that the database is correct and JDBC is working.

  4. Try putting the wrong password into the application configuration file. Multiserver should start, but the application will return an SQL exception and a stack trace.

  5. Make sure you do not have any extraneous Java VMs running. Sometimes, the classloader can fail to find the correct classes if it picks up an old CLASSPATH from a running VM.


Lutris Technologies
http://www.lutris.com
1200 Pacific Ave., Suite 300
Santa Cruz, CA 95060
Voice: (831) 471-9753
Fax: (831) 471-9754
documentation@lutris.com
<< Contents< PreviousNext >Index >>
© 2000 by Lutris Technologies, Inc. All Rights Reserved