The JDBC Optional Package and JTA


The JDBC Core API provides access to the database from Java applications, as shown in Chapter 13. The JDBC Optional Package and JTA supplement the JDBC Core API to address the requirements of distributed applications. The new functionality that is provided by the JDBC Optional Package includes

  • The DataSource interface to be used instead of the DriverManager

  • Connection pooling

  • Distributed transactions

  • RowSets

Two very significant features provided by the database driver vendor and the application server are distributed transactions and connection pooling. These features enable the portability, robustness, and data durability required by enterprise applications. As a J2EE developer, it is essential to have a basic understanding of distributed transactions and connection pooling. You can then incorporate these features into your J2EE applications using the JDBC Optional Package and JTA.

The DataSource interface is implemented by a driver vendor. The particular implementation of the DataSource allows the middle- tier infrastructure to provide connection pooling and distributed transactions. The DataSource therefore is implemented in one of three manners:

  • Basic implementation ” Produces a standard Connection object.

  • Connection pooling implementation ” Produces a Connection object that participates in connection pooling. Requires a middle-tier connection pooling manager.

  • Distributed transaction implementation ” Produces a Connection object that may be used for distributed transactions. Requires a middle-tier distributed transaction manager and, almost always, a connection pooling manager.

The Java Transaction API provides functionality to allow an application to explicitly manage transaction boundaries. The interface that defines the methods for transaction management is the UserTransaction interface. Both the DataSource and UserTransaction objects are used directly by a server-side component of a J2EE application. This component is either a servlet or an Enterprise JavaBean. The objects that implement the DataSource or UserTransaction interface are registered with a naming service. The Java application obtains an instance of these objects using the JNDI API.

The API for the JDBC Optional Package is in the javax.sql package. The API for JTA is in the javax.transaction and javax.transaction.xa packages. The package names follow the Java naming convention, indicating that they are standard extensions to the Java programming language. They are included as part of the standard Java SDK 1.4 release. The server-side data source access provided by the JDBC Optional Package and the transaction management provided by JTA make these APIs essential features of the J2EE architecture.

Using the DataSource Interface

The DataSource interface is part of the JDBC Optional Package and is found in the javax.sql package. When used, the DataSource completely replaces the DriverManager and offers substantial benefits. As you saw in Chapter 13, the DriverManager requires you to register a JDBC driver and use the corresponding JDBC URL as the parameter to DriverManager.getConnection ( "JDBC_URL" ). You lose portability because the DriverManager does not allow you to be database independent. Therefore, you are not really isolated from the database.

The JDBC Optional Package solved this issue by using JNDI to search for a DataSource object within a naming and directory service. The DataSource acts as a connection factory by containing all the information necessary to create a Connection instance to a particular database. The naming and directory service is used to match a name to the DataSource . Now, all the application needs to do is look up the name to obtain the DataSource and then use the DataSource object to get a Connection to the database. The naming and directory service is administered independently, allowing modifications to the database connection information without your having to change Java source code. See the section, "Configuring the WebLogic JDBC DataSource," later in this chapter for further information on using the WebLogic Server Console to configure DataSources.

Your Java code to create a Connection now looks like this:

 
 Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup( "  MY_DATASOURCE_NAME  " ); Connection con = ds.getConnection(  DATABASE_USER  ", "  DATABASE_PASSWORD  ); 

Using Connection Pools

A simple, straightforward database application opens a connection to the database, executes an update, and closes the connection. This mode of operation does not scale well when there are many database accesses per minute. A serious performance degradation would be evident because connecting to the database is an expensive operation. JDBC provides a standardized solution to this problem through connection pooling. A cache of open database connections is maintained by a middle-tier connection pool manager. The application gets a Connection instance from the connection pool, uses it, and then returns it to the connection pool. The database connection is never closed until the connection pool manager is shut down.

The API for connection pooling allows the application to treat standard Connection objects and connection pooling objects identically. There is absolutely no difference in the API. The key to getting a Connection from a connection pool is the DataSource interface that is part of the JDBC Optional Package. Rather than get the Connection object from the DriverManager , you get the Connection object from a DataSource object. The remainder of your JDBC application is exactly the same because you are still working with a Connection object; it is the same Connection object that was introduced in Chapter 13. The DataSource object is retrieved from the application server by performing a JNDI lookup on the name of the DataSource . Each DataSource is associated with a connection pool as part of its configuration. The connection pools must therefore be configured before creating the DataSource . Refer to the section "Configuring a WebLogic Connection Pool" later in this chapter for further information.

Using a DataSource for Distributed Transactions

The basic concepts of distributed transactions were covered earlier in this chapter. The Connection objects that are obtained from a DataSource that is implemented to work with a middle-tier transaction manager can participate in distributed transactions. The WebLogic application server provides the transaction manager through its JTA driver. The J2EE application deployed on WebLogic Platform must therefore use the WebLogic JTA driver when distributed transactions are required. The application does not do anything special with the Connection object to enable it to participate in distributed transactions. In fact, there is a restriction that the application cannot call commit() , rollback() , or setAutoCommit() on a Connection object that is under the control of a middle-tier transaction manager. Otherwise, the Connection API is the same. The UserTransaction interface in JTA defines methods that allow the application to explicitly manage transaction boundaries. The DataSource must be configured as a Tx DataSource on WebLogic Platform if it is to be used for distributed transactions. Refer to the section "Configuring a WebLogic Tx DataSource" later in this chapter.

Using the RowSet Interface

The RowSet interface is part of the JDBC Optional Package and is found in the javax.sql package. It adds JavaBeans component model support to the JDBC API and acts as a wrapper for JDBC and DataSource operations. The RowSet interface extends java.sql.ResultSet , therefore fully inheriting the API of ResultSet . Following the JavaBeans specification, the RowSet interface provides setter and getter methods to configure its properties. The RowSet interface also supports the JavaBeans event model for user interface events. The event model that is dictated by JavaBeans is implemented by having the JavaBean notify listeners of significant events through an event listener interface. Any object can implement the RowSetListener interface and add itself as a listener to the RowSet JavaBean. The RowSetListener provides the interface, and the RowSetEvent class provides the information as to which event occurred. These types of events are notified by a RowSet :

  • Indicating that the RowSet cursor has moved

  • Indicating that a row has been inserted, updated, or deleted

  • Indicating that the entire contents of the RowSet have changed, meaning an execute() has been performed

The RowSet interface is implemented either by the JDBC driver vendor or a third party. The implementing class is a wrapper for a DataSource , PreparedStatement , and a ResultSet . The following example uses the ImaginaryRowSet class that comes with the mSQL-JDBC driver. The configuration of the RowSet is as follows :

 
 RowSet rs = new ImaginaryRowSet(); // create the RowSet object rs.setDataSourceName( "MY_DATASOURCE" ); // configure the DataSource rs.setUsername( "DATABASE_USER" ); // configure database user and password rs.setPassword( "DATABASE_PASSWORD" ); rs.setCommand( "SELECT * FROM books " + // configure the PreparedStatement "WHERE title = ?" ); 

To use the RowSet object, first bind parameters to the fields in the Prepared statement; then invoke the execute() method. Because RowSet inherits from ResultSet , retrieving the data is exactly the same as with a ResultSet . The only difference is that RowSet sends out event notification through the listener interface. The following example shows how to use the configured RowSet :

 
 rs.setString( "  MY_FAVORITE_BOOK  " ); rs.execute(); while( rs. next () ) System.out.println( "Book id is " + rs.getInt( "book_id" ) ) ; 

Using the UserTransaction Interface

The UserTransaction interface is part of JTA and is found in the javax.transaction package. As with the DataSource , the object that implements the UserTransaction is retrieved through JNDI from a naming and directory service. The name to look up is the full package name with the interface name, which is javax.transaction.UserInterface . The UserTransaction interface enables you to perform distributed transactions because the scope of the transaction is raised from the Connection object to the executing thread level.

Now you can start a transaction, locate and connect to as many DataSource s as necessary, execute resource operations, close the connections, and then commit the transaction. This capability is essential for most enterprise systems where you need control over the transaction boundaries. The one restriction is that the DataSource must be a distributed transaction implementation, as mentioned previously. The transactional DataSource is implemented by the TxDataSource class. The main point to remember is not to specify a pool driver when locating the DataSource . The section "Configuring WebLogic JDBC Tx DataSources" later in this chapter shows how to configure a TxDataSource using the WebLogic Server Console.

The following is an example of locating and using an instance of a UserTransaction :

 
 try { Context ctx = new InitialContext(); UserTransaction tx = (UserTransaction)ctx.lookup( "javax.transaction.UserTransaction" ); tx.begin(); // start transaction // locate DataSource, establish connection, execute operations, close connections tx.commit(); // commit transactions } catch( Exception x ) { System.err.println( "error has occurred" ); try { tx.rollback(); } catch( javax.transaction.SystemException se ) { } } 


BEA WebLogic Platform 7
BEA WebLogic Platform 7
ISBN: 0789727129
EAN: 2147483647
Year: 2003
Pages: 360

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net