The contents of this guide are the following:
The first possibility is the default, the database manager uses the Standard class which uses the standard wrapper. In this case, we need to have a JDBC 1.0 driver. This way is the common way to work with the new database Manager. But you can use the second possibility to extend the driver wrapper for special works with some database. It is the case with Informix and Sybase, these databases need some hacks to work. In these cases, the database manager uses a special class (Informix or Sybase) which uses the standard wrapper.
The third possibility is to extend the driver wrapper for the InstantDB database. In this case, the database manager uses an InstantDB hat to extend the standard wrapper. We obtain, then, a JDBC 2.0 driver when we uses the InstantDB database.
The last possibility is to use a JDBC 2.0 driver. Oracle has a JDBC 2.0 driver and you can use it with the database manager from Jonas. In this case, the database manager needs to work with some special extensions (hats), the XADataSource, XAConnection, XAPreparedStatement and XAStatement are extended to do the glue between the database manager from Jonas and the JDBC 2.0 driver from Oracle.
The next section explains what is a framework.
The "How to extend the driver wrapper" section explains the cases of Informix and Sybase, and describes the Jonas hats, need to do the glue between the database manager from Jonas and the driver wrapper or a JDBC 2.0 driver.
Transaction and Query timeout are set with the same execute statement but we want to be able to set different values for query and transaction timeout.
package org.enhydra.jdbc.sybase; import org.enhydra.jdbc.standard.*; import java.sql.*; import java.util.*; public class SybaseConnectionHandle extends StandardConnectionHandle { public SybaseConnectionHandle (SybasePooledConnection pooledCon, Hashtable preparedStatementCache) { super (pooledCon, preparedStatementCache); } // constructor synchronized public void setAutoCommit(boolean autoCommit) throws SQLException { preInvoke(); try { con.commit(); con.setAutoCommit(autoCommit); } catch (SQLException e) { catchInvoke(e); } } // method setAutoCommit } // class SybaseConnectionHandle
This extension only works with the Oracle 8.1.6 version and the classes12.zip file which contains the JDBC 2.0 driver from Oracle.
package org.objectweb.jonas.dbm; import oracle.jdbc.xa.client.OracleXADataSource; import org.objectweb.jonas.dbm.CommonDataSource; import java.sql.*; import javax.sql.*; import javax.naming.*; import javax.naming.spi.*; import java.util.Hashtable; public class JonasOracleXADataSource extends OracleXADataSource implements Referenceable, ObjectFactory,CommonDataSource { public JonasOracleXADataSource () throws SQLException{ super(); } // constructor public void setProperties(String url, String classname, String user, String password) throws SQLException { setURL(url); setUser(user); setPassword(password); } // method setProperties public Reference getReference() throws NamingException { // Note that we use getClass().getName() to provide the factory // class name. It is assumed that this class, and all of its // descendants are their own factories. Reference ref = new Reference(getClass().getName(), getClass().getName(), null); try { ref.add(new StringRefAddr("url", getURL())); } catch (SQLException ef) { throw new NamingException ("Exception JonasOracleXADataSource:getReference"); } ref.add(new StringRefAddr("user", getUser())); ref.add(new StringRefAddr("password", getPassword())); return ref; } // method getReference /** * Methods inherited from ObjectFactory */ public Object getObjectInstance(Object refObj, Name name, Context nameCtx, Hashtable env) throws Exception { Reference ref = (Reference)refObj; this.setURL((String)ref.get("url").getContent()); this.setUser((String)ref.get("user").getContent()); this.setPassword((String)ref.get("password").getContent()); return this; } // method getObjectInstance public void setTransactionManager(TransactionManager tm) {} public void setDebug(boolean debug) {} public void setLogWriter(PrintWriter logWriter) {} } // class JonasOracleXADataSourceThe JonasOracleXADataSource class is used in Jonas (Oracle1.properties) with the datasource.factory section :
datasource.factory org.objectweb.jonas.dbm.JonasOracleXADataSource
package org.objectweb.jonas.dbm; import java.sql.*; public interface CommonDataSource { public void setProperties(String url, String classname, String user, String password) throws SQLException; public void setTransactionManager(TransactionManager tm); public void setDebug(boolean debug); public void setLogWriter(PrintWriter logWriter); public void setMinCon(int min); public void setMaxCon(int max); } // interface CommonDataSourceThe setTransactionManager method is used to set up the transaction manager into the datasource. The setDebug method is used to set up if or not, the debug information will be displayed on the stream. The setLogWriter method is used to set up the logwriter object. The setMinCon method is used to set up the minimum of physical connection, and the setMaxCon method is used to set up the maximum of physical connection.
package org.objectweb.jonas.dbm.instantdb; import org.objectweb.jonas.dbm.CommonDataSource; import org.enhydra.jdbc.instantdb.IdbXADataSource; import java.sql.*; public class JonasIdbXADataSource extends IdbXADataSource implements CommonDataSource { public void setProperties(String url, String classname, String user, String password) throws SQLException { setUrl(url); try { setDriverName(classname); } catch (Exception e) { log("Exception JonasIdbXADataSource:setProperties "+e); throw new SQLException("Exception JonasIdbXADataSource:setProperties "); } setUser(user); setPassword(password); } // method setProperties } // class JonasIdbXADataSource
datasource.factory org.objectweb.jonas.dbm.Jonas[Driver]XADataSourceThe previous class must implement the CommonDataSource interface. This interface is used in the DataBaseServiceImpl class to bind into JNDI the factory of the data source :
try { CommonDataSource connect = (CommonDataSource)(Class.forName(xaFactory).newInstance()); connect.setProperties(url, dsd.getProperty(CLASS_NAME), dsd.getProperty(USER_NAME), dsd.getProperty(PASSWORD)); connect.setTransactionManager(TransactionServiceImpl.getInstance().getTransactionManager()); connect.setMinCon((new Integer(dsd.getProperty(MINCON, DEFAULT_MINCON))).intValue()); connect.setMaxCon((new Integer(dsd.getProperty(MAXCON, DEFAULT_MAXCON))).intValue()); connect.setDebug(debug); ds.setLogWriter(Trace.getLogWriter()); connect.setLogWriter(Trace.getLogWriter()); ds.std = (XADataSource)connect; ictx.rebind(xaName, connect); xadsList.put(xaName, connect); } catch ...
package org.enhydra.jdbc.informix; import org.enhydra.jdbc.standard.*; import java.sql.*; import java.util.*; public class InformixConnectionHandle extends StandardConnectionHandle { private int lockModeWait = 0; // The amound time to wait on a query or transaction public InformixConnectionHandle (InformixPooledConnection pooledCon, Hashtable preparedStatementCache) { super (pooledCon, preparedStatementCache); } // constructor public synchronized void setLockModeToWait(int seconds) throws SQLException { if (lockModeWait != seconds) { if (seconds >0) { execute("SET LOCK MODE TO WAIT " + seconds); } else if (seconds == 0) { execute("SET LOCK MODE TO NOT WAIT "); } else { execute("SET LOCK MODE TO WAIT "); } lockModeWait = seconds; } } // method setLockModeToWait public synchronized void execute (String sql) throws SQLException { Statement stat = createStatement(); stat.execute(sql); } // method execute } // class InformixConnectionHandle
package org.enhydra.jdbc.informix; import org.enhydra.jdbc.standard.*; import java.sql.*; import javax.sql.*; public class InformixConnectionPoolDataSource extends StandardConnectionPoolDataSource { /** * Create a pooled connection using the default username and password. */ public PooledConnection getPooledConnection () throws SQLException { log("InformixConnectionPoolDataSource:getPooledConnection(0) return a pooled connection"); return getPooledConnection (user, password); } // method getPooledConnection /** * Create a informix pooled connection using the supplied username and password. */ public PooledConnection getPooledConnection (String user, String password) throws SQLException { log("InformixConnectionPoolDataSource:getPooledConnection(2) return a pooled connection"); return new InformixPooledConnection ((ConnectionPoolDataSource)this, user, password); } // method getPooledConnection } // class InformixConnectionPoolDataSource
package org.enhydra.jdbc.informix; import org.enhydra.jdbc.standard.*; import java.sql.*; import javax.sql.*; public class InformixPooledConnection extends StandardPooledConnection { public InformixPooledConnection (ConnectionPoolDataSource dataSource, String user, String password) throws SQLException { super((StandardConnectionPoolDataSource)dataSource, user, password); } // constructor protected void newConnectionHandle() { connectionHandle = new InformixConnectionHandle (this, preparedStatements); } // method newConnectionHandle } // class InformixPooledConnection
package org.enhydra.jdbc.informix; import org.enhydra.jdbc.standard.*; import java.sql.*; public class InformixXAConnection extends StandardXAConnection { /** * Creates the first free connection. */ public InformixXAConnection (InformixXADataSource dataSource, String user, String password) throws SQLException { super (dataSource, user, password); // creates the first Connection object // Save the constructor parameters. this.dataSource = dataSource; curCon = new InformixXAStatefulConnection (dataSource, con);// wrap connection as a stateful connection // NOTE - the current connection is not made known to the data source // so it is not eligible for re-use. It only goes on the data source list // if it ever becomes associated with a global transaction. timerThread = new Thread (this); // create the backgroup thread to check for timeouts timerThread.start(); // start the timer thread timerThread.suspend(); // and suspend until some timeouts get set up dataSource.log("InformixXAConnection created"); } // constructor } // class InformixXAConnection
package org.enhydra.jdbc.informix; import org.enhydra.jdbc.standard.*; import java.sql.*; import javax.sql.*; public class InformixXADataSource extends StandardXADataSource { /** * Creates an XA connection using the default username and password. */ public XAConnection getXAConnection () throws SQLException { log("InformixXADataSource:getXAConnection(0) XA connection returned"); return getXAConnection (user, password); } // method getPooledConnection /** * Creates an XA connection using the supplied username and password. */ public XAConnection getXAConnection (String user, String password) throws SQLException { InformixXAConnection xac = new InformixXAConnection (this, user, password); connectionCount++; log("InformixXADataSource:getXAConnection(2) XA connection returned"); return xac; } // method getPooledConnection /** * Create a pooled connection using the default username and password. */ public PooledConnection getPooledConnection () throws SQLException { log("InformixConnectionPoolDataSource:getPooledConnection(0) return a pooled connection"); return getPooledConnection (user, password); } // method getPooledConnection /** * Create a informix pooled connection using the supplied username and password. */ public PooledConnection getPooledConnection (String user, String password) throws SQLException { log("InformixConnectionPoolDataSource:getPooledConnection(2) return a pooled connection"); return new InformixPooledConnection (this, user, password); } // method getPooledConnection } // class InformixXADataSource
package org.enhydra.jdbc.informix; import org.enhydra.jdbc.standard.*; import java.sql.*; import javax.transaction.Status; public class InformixXAStatefulConnection extends StandardXAStatefulConnection { /** * Creates a new stateful connection in the FREE state (NO_TRANSACTION) */ InformixXAStatefulConnection (InformixXADataSource dataSource, Connection con) { super((StandardXADataSource)dataSource, con); } // method InformixXAStatefulConnection } // class InformixXAStatefulConnection
package org.objectweb.jonas.dbm; import org.objectweb.jonas.dbm.CommonDataSource; import org.enhydra.jdbc.standard.StandardXADataSource; import java.sql.*; import javax.sql.*; import javax.naming.*; import javax.naming.spi.*; import java.util.Hashtable; public class JonasInformixXADataSource extends StandardXADataSource implements CommonDataSource { public StandardInformixXADataSource () throws SQLException { super(); } // constructor public void setProperties(String url, String classname, String user, String password) throws SQLException { setUrl(url); setUser(user); setPassword(password); try { setDriverName(classname); } catch (SQLException e) { log("Exception JonasInformixXADataSource:setProperties "+e); throw new SQLException("Exception JonasInformixXADataSource:setProperties "); } } // method setProperties } // class JonasInformixXADataSource