Create your own type 3 JDBC driver, Part 1

Connect your Java applications to databases—the easy way

1 2 3 Page 2
Page 2 of 3
public
                                       ResultSet executeQuery(String sqlQuery)
                                       throws SQLException
                                       {
                                       try
                                       {
                                       IRemoteResultSet remoteRsInstance =
                                       (IRemoteResultSet) remoteStmt.executeQuery(sqlQuery);
                                       JWResultSet localRsInstance = new
                                       JWResultSet(remoteRsInstance);
                                       return (ResultSet)localRsInstance;
                                       }
                                       catch(RemoteException ex)
                                       {
                                       throw(new SQLException(ex.getMessage()));
                                       }
                                       }
                                       
                                    

Figure 4 shows the class diagram depicting the relationship between the Statement and ResultSet classes on the client and middle tiers.

Figure 4. The class diagram for the Statement and ResultSet classes. Click on thumbnail to view full-size image.

Next, we see JWResultSet.

The JWResultSet class

The com.jw.client.JWResultSet class implements the JDBC ResultSet interface. It references the remote server ResultSet interface and acts as a wrapper over the remote ResultSet stub for providing the JDBC ResultSet interface. The JWStatement.executeQuery() method, which returns the JWResultSet object reference to the client program, creates JWResultSet. The client then calls any method provided by the JDBC ResultSet interface on the returned JWResultSet object reference. The JWResultSet object internally forwards the request to the remote server ResultSet for processing. For example, when the client calls rs.next() (where rs is a reference of JWResultSet object), the next() method internally calls RemoteResultSet.getNextRow(), which returns an array of the row data. That row data is stored in the JWResultSet as the current row. When the client calls the rs.getString(1) method, the data is picked from the row data and returned:

public class JWResultSet implements java.sql.ResultSet
                                       {
                                       // The current ResultSet data row 
                                       private   Object[]   row;
                                       ...
                                       public boolean next() throws SQLException
                                       {
                                       try
                                       {
                                       // Get the current data row from remote ResultSet
                                       // All the getXXX methods will get data from local 'row'
                                       
                                       row = remoteResultSet.getNextRow();
                                       }
                                       catch(Exception ex)
                                       {
                                       return false;      
                                       }   
                                       
                                       if(row == null)
                                       {
                                       return false;
                                       }
                                       
                                       return true;
                                       }   
                                       }
                                       
                                    

The middle-tier classes

The middle-tier package, com.jw.server, includes the following classes:

  • com.jw.server.RemoteDriverImpl: The Driver class that retrieves the database connection and also acts as the RMI server
  • com.jw.server.RemoteConnectionImpl: The Connection class that retrieves the JDBC Statement
  • com.jw.server.RemoteStatementImpl: The Statement class that retrieves the ResultSet
  • com.jw.server.RemoteResultSetImpl: The ResultSet class

Let's examine each in more detail.

RemoteDriverImpl

RemoteDriverImpl acts as the RMI server (by extending UnicastRemoteObject) and provides the getConnection() method to the JDBC driver's client tier. (Figure 2 shows RemoteDriverImpl's other class and interface relationships.) RemoteDriverImpl implements com.jw.server.IRemoteDriver, an interface that extends Remote and provides the getConnection() method. The getConnection() method creates a JDBC Connection and returns it as an IRemoteConnection reference.

Since RemoteDriverImpl is the JDBC driver server's RMI server, it reads the ODBC data source name (DSN), username, and password from DriverSettings.properties files deployed in the server tier. These values create a JDBC Connection. Moreover, RemoteDriverImpl registers itself with the Naming service as "RemoteDriver," so that the driver's JDBC client layer can connect to the server using the Naming.lookup() method. Then it loads the JDBC-ODBC Bridge to create the database connections:

public static void main(String args[])
                                       {
                                       System.setSecurityManager(new RMISecurityManager());
                                       try
                                       {
                                       // Get the data source name, data source user, data source
                                       // Password and log level 
                                       ResourceBundle settingsBundle = ResourceBundle.getBundle(
                                       "DriverSettings");
                                       DSN = settingsBundle.getString("DSN");
                                       dsUser = settingsBundle.getString("User");
                                       dsPassword = settingsBundle.getString("Password");
                                       
                                       // Create a RemoteDriverImpl instance to register with naming service
                                       RemoteDriverImpl serverInstance = new RemoteDriverImpl();
                                       Naming.rebind("RemoteDriver",serverInstance);         
                                       
                                       // Load the JDBC-ODBC Bridge driver
                                       Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                                       }
                                       ...
                                       }
                                       
                                    

The getConnection() method creates a JDBC-ODBC connection, then returns a reference to the remote interface of the RemoteConnectionImpl object holding the JDBC-ODBC connection:

   
                                       public IRemoteConnection getConnection() 
                                       throws RemoteException,SQLException
                                       {
                                       String URL="jdbc:odbc:"+DSN;
                                       Connection sqlCon = 
                                       DriverManager.getConnection(URL,dsUser,dsPassword);
                                       RemoteConnectionImpl ConnectionInstance = 
                                       new RemoteConnectionImpl(sqlCon);
                                       return (IRemoteConnection)ConnectionInstance;
                                       }
                                       
                                    

Now let's see RemoteConnectionImpl.

RemoteConnectionImpl

The RemoteConnectionImpl class extends the UnicastRemoteObject class and implements the IRemoteConnection interface. (Figures 2 and 3 show RemoteConnectionImpl's class and interface relationships.) The IRemoteConnection interface provides methods to create JDBC statements and close the database connection. The RemoteConnectionImpl class also encapsulates the JDBC Connection object passed to it in its constructor.

The createStatement() method creates the JDBC-ODBC statement and returns the RemoteStatementImpl object's reference that holds the JDBC-ODBC statement:

public IRemoteStatement createStatement() throws RemoteException,SQLException
                                                                              {
                                                                                 RemoteStatementImpl StmtImplInstance =  new 
                                                                              RemoteStatementImpl(sqlConnection.createStatement());
                                                                                 return  (IRemoteStatement)StmtImplInstance;
                                                                              }
                                                                           
                                    

Next, the closeConnection() method simply closes the JDBC Connection object it encapsulates by calling the close() method:

public void closeConnection() throws RemoteException,SQLException
                                                                              {
                                                                                 sqlConnection.close();   
                                                                              }   
                                                                           
                                    

Let's now examine class RemoteStatementImpl.

RemoteStatementImpl

The RemoteStatementImpl class—shown in Figures 3 and 4—extends the UnicastRemoteObject class and implements the IRemoteStatement interface. The IRemoteStatement interface provides methods to create the JDBC ResultSet and close the statement object. The RemoteStatementImpl class also encapsulates the JDBC Statement object passed to it in its constructor.

The executeQuery() method creates a JDBC-ODBC ResultSet, then returns a reference to the remote interface of the RemoteResultSetImpl object holding the JDBC-ODBC ResultSet:

public
                                                                              IRemoteResultSet executeQuery(String Query) throws RemoteException,SQLException
                                                                              {
                                                                                 ResultSet rs = sqlStatment.executeQuery(Query);
                                                                                 RemoteResultSetImpl remoteRs = new RemoteResultSetImpl(rs);
                                                                                 return (IRemoteResultSet)remoteRs;
                                                                              }
                                                                           
                                    

The close() method simply closes the JDBC Statement object:

public
                                       void
                                                                              close() throws RemoteException, SQLException
                                                                              {
                                                                                 sqlStatment.close();
                                                                              }
                                                                           
                                    

Lastly, here is class RemoteResultSetImp.

RemoteResultSetImpl

The RemoteResultSetImpl class extends the UnicastRemoteObject class and implements the IRemoteResultSet interface. (Figure 4 shows its class and interface relationships.) The IRemoteResultSet interface's methods retrieve JDBC ResultSet rows and close the ResultSet object. The RemoteResultSetImpl class also encapsulates the JDBC ResultSet object passed to it in its constructor.

The getNextRow() method returns one ResultSet row in an array of Objects to the client JWResultSet. It returns null if ResultSet does not have any more rows:

public Object[] getNextRow() throws RemoteException,SQLException
                                                                              {
                                                                                 // Return null if all data has already been iterated
                                                                                 if(sqlRs.next() == false)
                                                                                    return null;
                                                                                 // Prepare the data row in an array of Objects
                                                                                 Object []row = new Object[colNum];
                                                                                 for(int i = 1; i <= colNum; i++)
                                                                                 {
                                                                                    row[i-1] = sqlRs.getString(i);
                                                                                 }
                                                                                 return row;
                                                                              }
                                                                           
                                    

The close() method closes the JDBC ResultSet object:

public void close()
                                                                              throws RemoteException,SQLException
                                                                              {
                                                                                 sqlRs.close();
                                                                              }
                                                                           
                                    

That's all there is to the middle-tier classes.

Related:
1 2 3 Page 2
Page 2 of 3