In the early days of jdbc, developers learned the ridiculous way of using Class.forName(jdbcDriverClassName) to register a driver,
followed by DriverManager.getConnection(jdbcUrl, props) to obtain a connection. This has been superseded by using a DataSource instance.
DataSource is a simple interface, but a rather ambiguous concept.
According to its javadoc there three implementation types:
- Type 1: A simple factory for Connection objects. In OSGI this is typically what you get from DataSourceFactory.getDataSource()
- Type 2: A facade to a Database connection pool. As database connections are expensive to create, most applications require connection pooling.
A DataSource instance is used as the application interface to the pool. When using a pool the semantics of Connection.close() are changed
from closing the database connection to returning the connection to pool. This can be accomplished in two ways:
- By maintaining a pool of PooledConnection objects provided by a PooledConnectionDataSource, and implement a ConnectionEventListener to return
the PooledConnection to the pool on Connection.close()
- By maintaining a pool of Connection objects provided by a type 1 DataSource, and return a wrapper on the pooled Connection object that changes close() semantics.
Most connection pools take the second approach. Our implementation in com.amplifino.nestor.jdbc.pools takes the first approach. If the driver does not implement PooledConnectionDataSource we adapt its DataSource to a PooledConnectionDataSource and use wrapping as in the second approach.
- Type 3: A facade to a Transactional Database connection pool. The DataSource is responsible for registering the connection's XAResource with the
currently executing transaction, if any. The pooling itself is similar as in type2, replacing PooledConnection with XAConnection and PooledConnectionDataSource
The DataSource has a few serious shortcomings:
- There is no standard way of configuring and creating a DataSource. In OSGI and for a type 1 DataSource one can use DataSourceFactory. For type 2 and type 3 datasources we propose a Declarative Service component that can be configured by Configuration Admin
- For type 2 and type 3 DataSource is missing an essential method: close() to release and close the connections in the pool. In OSGI we can address this by publishing type 2 and type 3 DataSource instance as an OSGI service, and empty the pool when the service is unregistered