Home | | Service Oriented Architecture | Modeling Databases in XML

Chapter: XML and Web Services : Building XML-Based Applications : Integrating XML with Databases

Modeling Databases in XML

In this section, you’ll learn how to model a database in XML using Java. When we model a database, we provide an external representation of the database contents. For our sample program, we’ll utilize a database that contains information on rental properties. We’ll model the rental property database as an XML document. Figure 10.3 shows the desired output.

Modeling Databases in XML

 

In this section, you’ll learn how to model a database in XML using Java. When we model a database, we provide an external representation of the database contents. For our sample program, we’ll utilize a database that contains information on rental properties. We’ll model the rental property database as an XML document. Figure 10.3 shows the desired output.


One possible solution is to use Java servlets and JDBC. Java servlets are server-side components that reside in a Web server or application server. Java servlets are com-monly used to handle requests from Web browsers using the HTTP protocol.

 

A key advantage to using servlets is the thin-client interface. The servlets handle the request on the server side and respond by generating an HTML page dynamically. This lowers the requirement on the client browser. The browser only has to provide support of HTML. As a result, there is zero client-side administration.

 

In contrast, Java applets require the browser to support the correct version of the Java Virtual Machine (JVM). This has been a thorny issue with the Java community since the early days of applet development. If the browser doesn’t support Java, the applet will not execute. Of course, there are a number of workarounds, such as the Java Plug-In and Java Web Start. However, these technologies still require an initial installation on the client machine—which can prove to be time consuming and error prone.

 

We can develop a servlet that uses JDBC. The servlet will make the appropriate query to the database and use Java Database Connectivity (JDBC) API result set metadata to cre-ate the elements. In fact, a servlet that performs this operation is presented in Chapter 7, “Parsing XML Using Document Object Model.” This is a simple and elegant solution because it leverages the result set metadata.

In this section, we’ll leverage the XML data binding features of Java Architecture for XML Binding (JAXB). JAXB provides a framework for representing XML documents as Java objects. Using the JAXB framework, we can guarantee that the documents processed by our system are well formed. Also, we have the option of validating the XML data against a schema.

 

In the JAXB framework, we can parse XML documents into a suitable Java object. This technique is referred to as unmarshaling. The JAXB framework also provides the capa-bility to generate XML documents from Java objects, which is referred to as marshaling. The process is illustrated in the Figure 10.4.


JAXB is easier to use and a more efficient technique for processing XML documents than the SAX or DOM API. Using the SAX API, you have to create a custom content handler for each XML document structure. Also, during the development of the content, you have to create and manage your own state machine to keep track of your place in the document. For very complex XML documents, the development process is very cumber-some. Using JAXB, an application can parse an XML document by simply unmarshaling the data from an input stream.

 

JAXB is similar to DOM in that we can create XML documents programmatically and perform validation. However, the hindrance with DOM is the complex API. If we have an XML tree, using the DOM API, we have to traverse through the tree to retrieve ele-ments. However, with JAXB, we retrieve the data from the XML document by simply calling a method on an object. JAXB allows us to define Java objects that map to XML documents, so we can easily retrieve data. The JAXB framework also ensures the type safety of the data.

 

See Chapter 7 for an introduction to JAXB. Also, detailed information on JAXB is avail-able in the JAXB specification at java.sun.com/xml. This chapter assumes you under-stand the basics of JAXB. We’ll apply JAXB in an enterprise application later in this chapter.

 

 

JAXB Solution

In the JAXB solution, we will model the rental property database as an XML document. First we need to review the database schema. After reviewing the schema, we will develop our desired XML document based on an XML schema. After we have the XML schema developed, we can create the JAXB binding schema. The JAXB binding schema contains instructions on how to bind the XML schema to a Java class. We’ll take the JAXB binding schema and generate the appropriate Java classes.

 

To summarize, we’ll follow these steps:

 

     Review the database schema.

 

     Construct the desired XML document.

 

     Define a schema for the XML document.

 

     Create the JAXB binding schema.

 

     Generate the JAXB classes based on the schema.

 

     Develop a Data Access Object (DAO).

 

     Develop a servlet for HTTP access.

 

Figure 10.5 illustrates the application architecture. RentalXMLServlet communicates with RentalDAO to retrieve information from the database. Once the information is retrieved by RentalDAO, RentalXMLServlet generates an XML document.


 

Reviewing the Database Schema

 

We have an existing database for the rental properties. Table 10.3 contains the database schema.

 

TABLE 10.3    Rental Property Database Schema

 


Field : Type

         

prop_num : NUMBER

name : VARCHAR2

street_address      VARCHAR2

city : VARCHAR2

state : VARCHAR2

zip_code : VARCHAR2

size_sq : NUMBER

bed_count : NUMBER

bath_count : NUMBER

monthly_rent : NUMBER

voice_phone : VARCHAR2

fax_phone : VARCHAR2

 

The source code for this chapter includes a sample MS Access database. The file is located at <install_dir>\ch10_xmldb\data\rental_property.mdb.

 

Constructing the Desired XML Document

 

The desired output XML document describes the rental property. However, the XML document does not use the exact field names listed in the database schema. Instead, the XML document provides a custom mapping of the database fields to XML element names. Table 10.4 contains the mapping.

 

TABLE 10.4    XML Database Mapping

 


A rental property is described with a root element of <rental_property>, as shown in the following code:

<rental_property> <prop_id>1</prop_id> <name>The Meadows</name> <address>

 

<street>251 Eisenhower Blvd</street> <city>Houston</city> <state>TX</state> <postal_code>77033</postal_code>

 

</address> <square_footage>500.0</square_footage> <bedrooms>1.0</bedrooms> <bath>1.0</bath>

 

<price>600</price>

 

<contact> <phone>555-555-1212</phone> <fax>555-555-1414</fax>

 

</contact> </rental_property>

 

Notice how the <address> element contains the subelements <street>, <city>, <state>, and <postal_code>. A similar approach is taken for the contact information. The <contact> element contains the <phone> and <fax> elements for the voice number and fax number, respectively.

 

In our system, we’ll normally work with a collection of rental properties. This collection is modeled using a <rental_property_list> element, as shown here:

 

<rental_property_list>

 

<rental_property> … </rental_property> <rental_property> … </rental_property>

 

…  …

 

</rental_property_list>

Defining a Schema for the XML Document

 

Based on the desired document format, we can create a schema definition. In this sec-tion, we will define the Document Type Definition (DTD). The DTD schema format was chosen because JAXB 1.0 (early access) only supports DTDs. In the future, JAXB is sup-posed to support the formal XML Schema definition.

 

Listing 10.1 contains the DTD for our rental property list.

 

LISTING 10.1  <install_dir>\ch10_xmldb\rental_property.dtd

 

<!ELEMENT  rental_property_list  (rental_property)*>

 

<!ELEMENT rental_property (prop_id, name, address, square_footage, bedrooms, bath, price, contact)>

<!ELEMENT prop_id (#PCDATA)>

<!ELEMENT name (#PCDATA)>

 

<!ELEMENT address (street, city, state, postal_code)>

<!ELEMENT street (#PCDATA)>

 

<!ELEMENT city (#PCDATA)>

<!ELEMENT state (#PCDATA)>

<!ELEMENT postal_code (#PCDATA)>

 

<!ELEMENT square_footage (#PCDATA)>

<!ELEMENT bedrooms (#PCDATA)>

<!ELEMENT bath (#PCDATA)>

 

<!ELEMENT  price  (#PCDATA)>

 

<!ELEMENT contact (phone, fax)>

<!ELEMENT phone (#PCDATA)>

<!ELEMENT fax (#PCDATA)>

 

 

Creating the JAXB Binding Schema

 

Now that the DTD is defined for our document, we need to define the JAXB binding schema. The JAXB binding schema is an XML document that contains instructions on how to bind a DTD to a Java class.

 

Using the JAXB binding schema, we can define the names of the generated Java classes, map element names to specific properties in the Java class, and provide the mapping rules for attributes. The following code example informs the JAXB system that the ele-ment <rental_property_list> should be mapped to a Java class and that it is the root element for the XML document:

 

<element  name=”rental_property_list”  type=”class”  root=”true”/>

 

There’s no requirement to define a mapping for every element in the XML document. JAXB uses a default binding schema that will create properties in the Java class based on the XML element name.

 

The binding schema also allows us to define a conversion rule for elements. For example, the numerical data for the rental property, such as price, square footage, and number of rooms, is always represented in the DTD as text data (#PCDATA). This is one of the limita-tions of the DTD format. However, by using JAXB, we can specify that a given element should be converted to a Java primitive type or class. In the following code example, we inform JAXB to convert the values of <square_footage>, <bedrooms>, and

 

<bath> to the double type; also, <price> is converted to an instance of the java.math.

 

BigDecimal class:

 

<element name=”square_footage” type=”value” convert=”double”/> <element name=”bedrooms” type=”value” convert=”double”/> <element name=”bath” type=”value” convert=”double”/>

 

<element name=”price” type=”value” convert=”BigDecimal”/> <conversion name=”BigDecimal” type=”java.math.BigDecimal”/>

 

We can also use the binding schema to define enumerated types, constructors, and interfaces. However, in the JAXB 1.0 early access version, constructors are not yet implemented.

 

The binding schema includes a section for controlling the output of the generated Java source code. For example, we can inform the system to use a given package name. The following code defines the package name as xmlunleashed.ch10.jaxb:

 

<options  package=”xmlunleashed.ch10.jaxb”/>

 

See the JAXB specification for details on the binding schema file format.

 

Now, let’s look at the JAXB binding schema file for our rental property example. The schema files normally use the filename extension .xjs (for XML Java schema). Listing 10.2 contains the complete code for our JAXB binding schema, rental_property.xjs.

LISTING 10.2  <install_dir>\ch10_xmldb\rental_property.xjs

 

<?xml version=”1.0” encoding=”ISO-8859-1” ?> <!DOCTYPE xml-java-binding-schema SYSTEM

”http://java.sun.com/dtd/jaxb/1.0-ea/xjs.dtd”>

 

<xml-java-binding-schema version=”1.0-ea”> <options package=”xmlunleashed.ch10.jaxb”/>

 

<element name=”rental_property_list” type=”class” root=”true”> <content property=”list”/>

 

</element>

 

<element name=”square_footage” type=”value” convert=”double”/>

<element name=”bedrooms” type=”value” convert=”double”/>

<element name=”bath” type=”value” convert=”double”/>

 

<element  name=”price”  type=”value”  convert=”BigDecimal”/>

 

<conversion name=”BigDecimal” type=”java.math.BigDecimal”/> </xml-java-binding-schema>

Generating the JAXB Classes Based on Schemas

 

Now we are ready to generate the Java source files based on our schemas. JAXB pro-vides a schema compiler for generating the Java source files. The schema compiler takes as input the DTD and the JAXB binding schema. Figure 10.6 illustrates the process.


We pass our DTD (rental_property.dtd) and binding schema (rental_property.xjs) to the JAXB schema compiler with the xjc command. The command should be entered in the directory <install_dir>\ch10_xmldb\. Type everything on one line:

 

java com.sun.tools.xjc.Main rental_property.dtd rental_property.xjs -d source_code

 

This command generates source code in the source_code directory. The following files are generated:

 

RentalPropertyList.java. This file models the <rental_property_list> ele-

 

ment.

 

  RentalProperty.java. This file models the <rental_property> element.

 

  Address.java. This file models the <address> subelement.

 

  Contact.java. This file models the <contact> subelement.

 

Figure 10.7 contains the Unified Modeling Language (UML) diagram for the generated Java classes.

 

Using the default schema-binding definition, the JAXB schema compiler generates a property in the Java class for each XML element. In the event the XML element contains subelements, the schema compiler will create a new class.

 

Listing 10.3 contains the partial source code for RentalProperty.java. Some of the code and methods are not listed to preserve space.


LISTING 10.3  <install_dir>\ch10_xmldb\source_code\xmlunleashed\ch10\jaxb\

 

RentalProperty.java

 

package  xmlunleashed.ch10.jaxb;

 

import java.io.IOException;

import java.io.InputStream;

import java.math.BigDecimal;

 

import javax.xml.bind.ConversionException;

import javax.xml.bind.Dispatcher;

 

import  javax.xml.bind.Element;

 

import javax.xml.bind.InvalidAttributeException;

import javax.xml.bind.LocalValidationException;

import javax.xml.bind.MarshallableObject;

 

import  javax.xml.bind.Marshaller;

 

import javax.xml.bind.MissingContentException;

import javax.xml.bind.NoValueException;

 

import javax.xml.bind.StructureValidationException;

import javax.xml.bind.UnmarshalException;

 

import javax.xml.bind.Unmarshaller;

import javax.xml.bind.Validator; import javax.xml.marshal.XMLScanner;

import javax.xml.marshal.XMLWriter; import xmlunleashed.ch10.jaxb.Address;

import xmlunleashed.ch10.jaxb.Contact;

public class RentalProperty extends MarshallableObject implements Element

 

{

 

private String _PropId; private String _Name; private Address _Address;

 

private  double  _SquareFootage;

 

private boolean has_SquareFootage = false; private double _Bedrooms;

 

private boolean has_Bedrooms = false; private double _Bath;

 

private boolean has_Bath = false; private BigDecimal _Price; private Contact _Contact;

 

public String getPropId() { return _PropId;

 

}

 

public void setPropId(String _PropId) { this._PropId = _PropId;

 

if (_PropId == null) { invalidate();

 

}

 

}

 

public String getName() { return _Name;

 

}

 

public void setName(String _Name) { this._Name = _Name;

 

if (_Name == null) { invalidate();

 

}

 

}

 

public Address getAddress() { return _Address;

 

}

 

public void setAddress(Address _Address) { this._Address = _Address;

 

if (_Address == null) { invalidate();

 

}

 

}

public  void  validateThis()

 

throws  LocalValidationException

 

{

 

…  …

 

}

 

public void marshal(Marshaller m) throws IOException

 

{

 

//  code  to  output  the  XML  document

 

}

 

public void unmarshal(Unmarshaller u) throws UnmarshalException

 

{

 

//  code  to  read  in  the  XML  document

 

}

 

…  …

 

}

The source code for RentalProperty.java contains private data members for the ele-ments defined in <rental_property>. The public get/set methods provide access to the properties. For example, to retrieve the name of the rental property from the Java object, we call the getName() method. In the case of a nested element, such as address, we call the getContact() method, which returns a Contact object. The Contact class is defined in a similar manner with get/set methods for the properties.

 

Also, we can validate the object by calling the validateThis() method. Recall that this source code was generated based on the DTD, so we can verify that the contents of the object adheres to the grammar rules of the DTD. The validate() method is very useful if the contents of the RentalProperty object are modified using the setter methods. It is also useful if we construct a RentalProperty object from scratch.

 

Finally, the RentalProperty class contains methods to marshal and unmarshal the content.

 

The source code for the remaining files is available in the source code download in the directory <install_dir>\ch10_xmldb\source_code\xmlunleashed\ch10\jaxb. Feel free to investigate these files’ contents.

 

Developing a Data Access Object (DAO)

A Data Access Object (DAO) provides access to the backend database. The goal of the DAO design pattern is to provide a higher level of abstraction for database access. The DAO encapsulates the complex JDBC and SQL calls. The DAO provides access to the backend database via public methods. The DAO converts a result set to a collection of objects. The objects model the data stored in the database. The application interaction with a DAO is shown in Figure 10.8.


By using a DAO, the implementation details of the database are hidden from the applica-tion clients. The implementation details include the database schema and database ven-dor. This follows closely with the design principle of encapsulation. A benefit of using the DAO is improved application maintenance. If the database schema changes, such as a column name being modified, we only have to update the DAO. No modifications are required to the client programs. Also, if we decide to change the database implementa-tion from Sybase to Oracle, modifications are only required to the DAO. The clients can continue to use the DAO without any modification. The DAO design pattern is widely used in the industry and is documented in Sun’s J2EE Patterns Catalog, found at java.sun.com/j2ee.

 

In our solution, we’ll create a DAO called RentalPropertyDAO. This version of the DAO will only provide the method getRentalProperties(). Later in the chapter, we’ll pro-vide additional methods. The getRentalProperties() method submits a SQL query to the database and converts the result set to a collection of JAXB RentalProperty objects. This process is illustrated in Figure 10.9.


Let’s examine the components of the RentalPropertyDAO source code. The class defini-tion and constructor for RentalPropertyDAO are shown here:

 

public  class  RentalPropertyDAO  {

*/

 

protected  Connection  myConn;

 

/**

 

         Constructor for DAO. Setup the database connection. * Use the default properties.

 

*/

 

public RentalPropertyDAO() throws DAOException {

 

this(“sun.jdbc.odbc.JdbOdbcDriver”,

 

”jdbc:odbc:RentalPropertyDSN”, ”test”, “test”);

 

}

 

/**

 

* Constructor for DAO. Setup the database connection. */

 

public RentalPropertyDAO(String driverName, String dbUrl, String user, String pass)

 

throws  DAOException  {

 

try  {

 

//  Load  the  driver

 

log(“Loading driver: “ + driverName); Class.forName(driverName);

 

//  Get  a  connection

 

log(“Connecting to the database: “ + dbUrl); log(“User id: “ + user);

 

myConn  =  DriverManager.getConnection  (dbUrl,  user,  pass);

 

log(“DB  connection  successful  at  “  +  new  java.util.Date());

 

}

 

catch  (Exception  exc)  {

 

throw  new  DAOException(exc);

 

}

 

}

 

 

}

 

The class RentalPropertyDAO defines a data member for a java.sql.Connection object. This will serve as our connection to the database. For the sake of simplicity, we’re using a single connection. We could also utilize a database connection pool to increase the scalability of the application.

 

RentalPropertyDAO can be constructed by using the default constructor. In this case, the DAO will use default properties for the JDBC driver name, the JDBC database URL, and the user ID and password. This constructor shields the client code for knowing the details of the database implementation. The typical JDBC steps are followed to load a database driver and to obtain a connection to the database.

 

RentalPropertyDAO also provides a constructor, where the client program supplies the appropriate JDBC parameters. This constructor provides flexibility and would be typi-cally used in a distributed computing environment such as Remote Method Invocation (RMI) or Enterprise JavaBeans (EJB). A remote server object would instantiate the DAO using server-side parameters. The DAO would then be available remotely via a server-side proxy interface. In this scenario, the client application would simply look up the remote object and invoke its methods. The client object is not involved with the construc-tion of the DAO and therefore is shielded from the implementation details of JDBC dri-ver name, URL, and so on.

 

Once the RentalPropertyDAO Data Access Object is constructed, clients can retrieve data from the database by calling the getRentalProperties()method. The code for getRentalProperties() is shown here:

 

/**

 

         Get  a  list  of  rental  properties  from  the  database

 

 

 

         @return  a  list  of  RentalProperty  objects

 

         @exception  SQLException  thrown  for  SQL  errors

 

*/

 

public  RentalPropertyList  getRentalProperties()  throws  DAOException  {

 

RentalPropertyList theRentalPropertyList = new RentalPropertyList(); List theList = theRentalPropertyList.getList();

 

try  {

 

Statement  myStmt  =  myConn.createStatement();

 

String  rentalSql  =  “SELECT  prop_num,  name,  street_address,  “

+  “city,  state,  zip_code,  “

 

+ “size, sq, bed_count, bath_count, “ + “monthly_rent, voice_phone, “

 

      “fax_phone  FROM  rental_properties”;

 

ResultSet  myRs  =  myStmt.executeQuery(rentalSql);

 

RentalProperty  tempProperty  =  null;

 

// build a collection of JAXB RentalProperty objects while (myRs.next()) {

 

tempProperty = createRentalProperty(myRs); theList.add(tempProperty);

 

}

//  be  sure  to  validate  the  new  list

theRentalPropertyList.validate();

 

myRs.close();

 

myStmt.close();

 

}

 

catch  (Exception  exc)  {

 

throw  new  DAOException(exc);

 

}

 

return  theRentalPropertyList;

 

}

 

This method queries the database and returns a collection of RentalProperty objects.

 

After the SQL is executed, the method processes the result set to build a collection of RentalProperty objects. Because the early access version of JAXB does not support the code generation of constructors, we’ve created a simple constructor method in

 

RentalPropertyDAO. The code for the createRentalProperty()method is shown here:

 

/**

 

         Create  a  JAXB  RentalProperty  object  based  on  the  result  set.

 

         This  method  provides  the  mapping  between  database  schema  and  object

 

*/

 

protected RentalProperty createRentalProperty( ResultSet theRs) throws DAOException {

 

RentalProperty  theProperty  =  new  RentalProperty();

 

Address  theAddress  =  new  Address();

 

Contact  theContact  =  new  Contact();

 

try  {

 

//set the rental property number and name

theProperty.setPropId(theRs.getString(“prop_num”));

theProperty.setName(theRs.getString(“name”));

 

//set the address

 

theAddress.setStreet(theRs.getString(“street_address”));

 

theAddress.setCity(theRs.getString(“city”));

 

theAddress.setState(theRs.getString(“state”));

 

theAddress.setPostalCode(theRs.getString(“zip_code”));

 

theProperty.setAddress(theAddress);

 

//set the square footage, bedrooms, bath count and rent

 

theProperty.setSquareFootage(theRs.getDouble(“size_sq”));

 

theProperty.setBedrooms(theRs.getDouble(“bed_count”));

 

theProperty.setBath(theRs.getDouble(“bath_count”));

 

theProperty.setPrice(new BigDecimal(

theRs.getDouble(“monthly_rent”)));

// set the contact information

theContact.setPhone(theRs.getString(“voice_phone”));

theContact.setFax(theRs.getString(“fax_phone”));

theProperty.setContact(theContact);

 

}

 

catch  (SQLException  exc)  {

 

throw  new  DAOException(exc);

 

}

 

return  theProperty;

 

}

 

The createRentalProperty()method creates an instance of a RentalProperty object using the default constructor. It then populates the object based on information from the result set. This method actually handles the mapping between the database fields and the XML elements.

 

Listing 10.4 contains the complete code for RentalPropertyDAO.java.

 

LISTING 10.4  <install_dir>\ch10_xmldb\source_code\xmlunleashed\ch10\

 

RentalPropertyDAO.java

 

package  xmlunleashed.ch10;

 

import java.sql.DriverManager;

import java.sql.Connection;

import java.sql.Statement;

import java.sql.ResultSet;

import java.sql.SQLException;

 

import  java.math.BigDecimal;

 

import xmlunleashed.ch10.jaxb.RentalProperty;

import xmlunleashed.ch10.jaxb.RentalPropertyList;

import xmlunleashed.ch10.jaxb.Contact;

 

import  xmlunleashed.ch10.jaxb.Address;

 

 

/**

 

*  Data  Access  Object  (DAO)  for  the  rental_property  database.  <br>

 

*

 

*/

 

public  class  RentalPropertyDAO  {

 

/**

 

* The database connection */

 

protected  Connection  myConn;

/**

 

* Constructor for DAO. Setup the database connection. */

 

public RentalPropertyDAO(String driverName, String dbUrl, String user, String pass)

 

throws  DAOException  {

 

try  {

 

//  Load  the  driver

 

log(“Loading driver: “ + driverName);

Class.forName(driverName);

 

//  Get  a  connection

 

log(“Connecting to the database: “ + dbUrl);

log(“User id: “ + user);

 

myConn  =  DriverManager.getConnection  (dbUrl,  user,  pass);

 

log(“DB  connection  successful  at  “  +  new  java.util.Date());

 

}

 

catch  (Exception  exc)  {

 

throw  new  DAOException(exc);

 

}

 

}

 

/**

 

         Get  a  list  of  rental  properties  from  the  database

 

 

 

         @return  a  list  of  RentalProperty  objects

 

         @exception  SQLException  thrown  for  SQL  errors

 

*/

 

public  RentalPropertyList  getRentalProperties()  throws  DAOException  {

 

RentalPropertyList theRentalPropertyList = new RentalPropertyList();

java.util.List theList = theRentalPropertyList.getList();

 

try  {

 

Statement  myStmt  =  myConn.createStatement();

 

String  rentalSql  =  “SELECT  prop_num,  name,  street_address,  “

+  “city,  state,  zip_code,  “

 

+ “size, sq, bed_count, bath_count, “ + “monthly_rent, voice_phone, “

+  “fax_phone  FROM  rental_properties”;

 

ResultSet  myRs  =  myStmt.executeQuery(rentalSql);

 

RentalProperty  tempProperty  =  null;

// build a collection of JAXB RentalProperty objects

while (myRs.next()) {

 

tempProperty = createRentalProperty(myRs);

theList.add(tempProperty);

 

}

 

// be sure to validate the new list

theRentalPropertyList.validate();

 

myRs.close();

 

myStmt.close();

 

}

 

catch  (Exception  exc)  {

 

throw  new  DAOException(exc);

 

}

 

return  theRentalPropertyList;

 

}

 

/**

 

         Create  a  JAXB  RentalProperty  object  based  on  the  result  set.

 

         This  method  provides  the  mapping  between  database  schema  and  object

 

*/

 

protected RentalProperty createRentalProperty( ResultSet theRs) throws DAOException {

 

RentalProperty  theProperty  =  new  RentalProperty();

 

Address  theAddress  =  new  Address();

 

Contact  theContact  =  new  Contact();

 

try  {

 

//set the rental property number and name

theProperty.setPropId(theRs.getString(“prop_num”));

theProperty.setName(theRs.getString(“name”));

 

//set the address

 

theAddress.setStreet(theRs.getString(“street_address”));

 

theAddress.setCity(theRs.getString(“city”));

 

theAddress.setState(theRs.getString(“state”));

 

theAddress.setPostalCode(theRs.getString(“zip_code”));

 

theProperty.setAddress(theAddress);

//set the square footage, bedrooms, bath count and rent

theProperty.setSquareFootage(theRs.getDouble(“size_sq”));

theProperty.setBedrooms(theRs.getDouble(“bed_count”));

theProperty.setBath(theRs.getDouble(“bath_count”));

theProperty.setPrice(new BigDecimal(

theRs.getDouble(“monthly_rent”)));

// set the contact information

theContact.setPhone(theRs.getString(“voice_phone”));

theContact.setFax(theRs.getString(“fax_phone”));

theProperty.setContact(theContact);

 

}

 

catch  (SQLException  exc)  {

 

throw  new  DAOException(exc);

 

}

 

return  theProperty;

 

}

 

/**

 

* Utility method for logging */

 

protected void log(Object message) { System.out.println(“RentalPropertyDAO: “ + message);

 

}

 

}

Now that we have the DAO in place, a client program can easily retrieve information from the database. The RentalPropertyList collection contains JAXB RentalProperty objects. These objects are capable of producing an XML representation of their data thanks to the JAXB support. The XML data is available by calling the marshal() method.

 

 

Creating a Test Harness for RentalPropertyDAO

 

Before we move to the next section, let’s create a test harness for RentalPropertyDAO. A test harness is a small program that tests the basic functionality of the application. If designed properly, The test harness provides a way of producing predictable results from an application.

 

The TestApp program will construct the RentalPropertyDAO Data Access Object and then retrieve a list of RentalProperty objects by calling the method getRentalPropertyList(). The XML data is displayed by calling the marshal() method on RentalPropertyList.

 

Listing 10.5 contains the code for TestApp.java.

 

LISTING 10.5  <install_dir>\ch10_xmldb\source_code\TestApp.java

 

import xmlunleashed.ch10.RentalPropertyDAO;

import xmlunleashed.ch10.DAOException;

import  xmlunleashed.ch10.jaxb.RentalPropertyList;

 

import  java.io.  IOException;

 

/**

 

      Test  harness  for  the  RentalPropertyDAO.

 

*  Retrieves  a  rental  property  list  and  displays  the

 

      results  to  standard  out.

 

*/

 

public  class  TestApp  {

 

/**

 

* DAO data member */

 

protected  RentalPropertyDAO  myRentalDAO;

 

/**

 

* Constructs the RentalPropertyDAO */

 

public TestApp() throws DAOException { myRentalDAO = new RentalPropertyDAO();

 

}

 

/**

 

* Retrieves a rental property list and displays the results to standard out */

 

public void process() throws DAOException, IOException {

// Get the list of rental properties

 

RentalPropertyList  theList  =  myRentalDAO.getRentalProperties();

 

// Send the XML data to standard out. theList.marshal(System.out);

 

}

 

/**

 

* Main routine. Constructs the test app and runs the process. */

 

public static void main(String[] args) { try {

 

TestApp  myApp  =  new  TestApp();

 

myApp.process();

 

}

 

catch (Exception exc) { exc.printStackTrace();

 

}

 

}

 

}

When we run the test harness, it retrieves a collection of rental properties from the DAO. The test harness then displays an XML document similar to this one:

 

<?xml  version=”1.0”  encoding=”UTF-8”?>

 

<rental_property_list> <rental_property> <prop_id>1</prop_id> <name>The Meadows</name> <address>

 

<street>251 Eisenhower Blvd</street> <city>Houston</city> <state>TX</state> <postal_code>77033</postal_code>

 

</address> <square_footage>500.0</square_footage> <bedrooms>1.0</bedrooms> <bath>1.0</bath>

 

<price>600</price>

 

<contact> <phone>555-555-1212</phone> <fax>555-555-1414</fax>

 

</contact> </rental_property>

 

<rental_property>

 

 

</rental_property> </rental_property_list>

 

Developing a Servlet for HTTP Access

 

At this point, we have constructed the RentalPropertyDAO Data Access Object. This DAO is capable of retrieving information from a database and providing a collection of objects. Thanks to the JAXB framework, these objects can be marshaled into XML.

 

Now we need to provide an HTTP interface for RentalPropertyDAO so that a Web browser can interact with our system. Java servlets provides support for the HTTP proto-col. If you are interested in Web-based interaction, you should also read about the Web Services technology, which is covered later in this book.

 

In our solution, we’ll use a servlet to handle the requests to the DAO. In the servlet, we’ll call the appropriate method and return the result as an XML document. Figure 10.10 depicts the application interaction.

The servlet is responsible for creating an instance of RentalPropertyDAO. The servlet reads JDBC parameters from the web.xml configuration file and constructs RentalPropertyDAO accordingly. An excerpt from the web.xml file is shown here (make note of the definitions for the parameters driverName, dbUrl, user, and pass) :

 

<servlet> <servlet-name>RentalXMLServlet</servlet-name>

 

<servlet-class>xmlunleashed.ch10.RentalXMLServlet</servlet-class> <init-param>

 

<param-name>driverName</param-name> <param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>

 

</init-param> <init-param>

 

<param-name>dbUrl</param-name> <param-value>jdbc:odbc:RentalPropertyDSN</param-value>

 

</init-param> <init-param>

 

<param-name>user</param-name> <param-value>test</param-value>

 

</init-param> <init-param>

 

<param-name>pass</param-name> <param-value>test</param-value>

 

</init-param> <load-on-startup/>

 

</servlet>

 

The servlet reads the parameters and constructs the RentalPropertyDAO Data Access Object in the init() method. The code for the init() method is shown here:

 

/**

 

* Create an instance of the RentalPropertyDAO */

 

public  void  init()  throws  ServletException  {

 

retrieve database connection parameters String dbUrl = getInitParameter(“dbUrl”);

 

String driverName = getInitParameter(“driverName”); String user = getInitParameter(“user”);

 

String  pass  =  getInitParameter(“pass”);

 

         create  an  instance  of  the  RentalPropertyDAO

 

try  {

 

myRentalDAO  =  new  RentalPropertyDAO(driverName,  dbUrl,  user,  pass);

 

}

 

catch (Exception exc) { log(exc.toString());

 

throw  new  ServletException(exc);

 

}

 

}

 

The servlet handles HTTP GET requests, so we have to override the doGet() method. In this method, we set the content type of the response to text/xml. This informs the client that we are returning XML-formatted text data. Next, we set up ServletOutputStream.

 

Then we retrieve a list of rental properties from RentalPropertyDAO. The list is then marshaled to the ServletOutputStream object, out. Finally, the output stream is closed. The code for the doGet() method is shown here:

 

/**

 

         Perform  the  following  steps  for  GET  requests.

 

 

 

         <ol>

 

         <li>Retrieve  a  list  of  rental  properties  from  RentalPropertyDAO<li>

 

         <li>Marshal  the  list  as  an  XML  document<li>

 

         </ol>

 

*/

 

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

ServletOutputStream  out  =  null;

 

RentalPropertyList  theList  =  null;

 

try  {

 

Set the content type to text/xml response.setContentType(“text/xml”);

 

Retrieve the servlet output stream out = response.getOutputStream();

 

Retrieve a list of rental properties theList = myRentalDAO.getRentalProperties();

 

Marshal the list as an XML document theList.marshal(out);

 

}

 

catch (DAOException exc) { exc.getRootCause().printStackTrace();

 

throw  new  ServletException(exc.getRootCause());

 

}

 

catch (Exception exc) { log(exc.toString()); exc.printStackTrace();

throw  new  ServletException(exc);

}

 

finally { out.close();

 

}

 

}

 

Testing the Application

 

In order to test the application, you need to download and install the following important components.

 

Here’s what’s required to test the application:

 

   Sun Microsystems’ Software Development Kit (SDK) 1.3 (or higher). The SDK is available at Sun’s Web site, http://java.sun.com/j2se. Follow the installation instructions provided with the SDK.

 

   Apache Tomcat Server 4. Apache Tomcat 4 is the official reference implementation for JSP 1.2 and Java Servlets 2.3. If your application server already supports JSP 1.1 or higher, there’s no requirement to install Tomcat. Apache Tomcat 4 is avail-able from the Apache Web site, http://jakarta.apache.org/tomcat. Follow the installation instructions provided with the Tomcat server.

 

Microsoft Internet Explorer 6 or Netscape 6. In this section, you will need a browser that has client-side XML support. This is useful for viewing the raw XML output of our servlet.

Once Tomcat 4 is installed, we need to add a new Web application that points to the source code directory. This is accomplished by editing the file <tomcat_install_dir>\ conf\server.xml. Move to the section where the <Context> elements are listed and then add the following entry:

 

<Context        path=”/bookch10” docBase=”<install_dir>/ch10_xmldb/public_html” debug=”0”

 

reloadable=”true”  />

Be sure to update <install_dir> with the installation directory for the book’s source code. This configuration allows us to access the Web application named bookch10. This Web application’s document base is located at <install_dir>\ch10_xmldb\public_html.

 

Now, restart the Tomcat server to pick up the new configuration. By default, the Tomcat server is listening on port 8080. You can access files for the bookch10 Web application using the following URL:

 

http://localhost:8080/bookch10/test.jsp

 

The file test.jsp should display a welcome message and the current date.

 

Next, follow these steps to compile the source code:

 

     Open a Microsoft command prompt window.

 

     Move to the source code directory by typing this:

 

cd  <install_dir>\ch10_xmldb

 

This directory includes the batch file setpaths.bat. This file will place the follow-ing JAR files in the classpath: lib\servlet.jar, lib\jaxb-rt-1.0-ea.jar, and lib\jaxb-xjc-1.0-ea.jar.

 

3.    Set up the classpath by typing the following:

 

setpaths.bat

 

4.    Move to the source code directory by typing this:

 

cd  source_code

 

5.    Compile the code by typing this:

 

javac  -d  ..\public_html\WEB-INF\classes  *.java

 

If you are accustomed to using ANT, note that this directory also contains a

 

build.xml file.

 

Now we need to set up an ODBC Data Source Name (DSN) for Rent

This DSN should point to the file <install_dir>\ch10_xmldb\data\rental_ property.mdb.

 

Now we need to test RentalXMLServlet. In a Web browser, open http://localhost: 8080/bookch10/RentalXMLServlet.

 

If you are using Microsoft Internet Explorer 6, you will see the XML content shown in Figure 10.11.


If you are using Netscape 6, select the menu option View, Page Source. This will display the raw XML output as shown in Figure 10.12.


Great! We’ve developed RentalXMLServlet to provide an HTTP interface to RentalPropertyDAO. The end product is an XML model of the data stored in the database.

 

Now we can take this one step further by applying a style sheet to the data.

 

Converting the XML Data to HTML with XSLT

 

We can leverage the functionality of XSLT to convert the XML data to HTML. In partic-ular, we will convert the rental property list to an HTML table, as shown in Figure 10.13.


This section assumes you are familiar with XSLT. If not, then read Chapter 9.

 

The XSLT style sheet contains the HTML template along with the XSLT constructs to retrieve the data. Our style sheet defines an HTML table with instructions to create a table row for each rental property in the list. Listing 10.6 contains the code for rental_view.xsl.

 

LISTING 10.6  <install_dir>\ch10_xmldb\public_html\rental_view.xsl

 

<?xml version=”1.0”?> <xsl:stylesheet xmlns:xsl=

”http://www.w3.org/1999/XSL/Transform”  version=”1.0”>

<xsl:template match=”/rental_property_list”> <html><body>

 

<h3>Rental Properties</h3> <hr></hr>

 

<table border=”1” cellpadding=”5”> <tr>

 

<th>Name</th>

 

<th>Street</th> <th>City, State</th> <th>Square Footage</th> <th>Bedrooms</th> <th>Bath</th> <th>Price</th>

 

</tr>

 

<!— Perform loop for each rental property in the list —> <xsl:for-each select=”rental_property” >

 

<tr>

 

<td> <xsl:value-of  select=”name”  />  </td> 

<td> <xsl:value-of  select=”address/street”  /> </td>

<td> <xsl:value-of  select=”address/city”  />,

<xsl:value-of  select=”address/state”  />  </td> 

<td> <xsl:value-of  select=”square_footage”  />  </td>

<td> <xsl:value-of  select=”bedrooms”  />  </td>

<td> <xsl:value-of  select=”bath”  />  </td> 

<td> $  <xsl:value-of  select=”price”  /> </td>

</tr>  

</xsl:for-each> </table>

 

</body></html>

 

</xsl:template>

 

</xsl:stylesheet>

 

We’ll use the Apache-Jakarta custom tag, <jakarta:apply>, for XLST processing. Instead of specifying an XML document by filename, we need to refer to RentalXMLServlet. The <jakarta:apply> element supports the subelement <jakarta:include>, which refers to an XML resource to include. This includes the output of RentalXMLServlet. Listing 10.7 shows the code for rental_test.jsp.

 

LISTING 10.7  <install_dir>\ch10_xmldb\public_html\rental_view.jsp

 

<%@taglib  uri=”http://jakarta.apache.org/taglibs/xsl-1.0”  prefix=”jakarta”  %>

 

<jakarta:apply xsl=”rental_view.xsl”> <jakarta:include page=”/RentalXMLServlet”/>

</jakarta:apply>

Testing the JSP Page

 

To test this example, make sure the Tomcat server is running. In a Web browser, access the JSP page with the URL http://localhost:8080/bookch10/rental_view.jsp.

 

Your browser should resemble what’s shown in Figure 10.13 shown previously.


Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail
XML and Web Services : Building XML-Based Applications : Integrating XML with Databases : Modeling Databases in XML |


Privacy Policy, Terms and Conditions, DMCA Policy and Compliant

Copyright © 2018-2024 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.