Pooling and XA support in 1.0.0

Changes from 0.9.0

pax-jdbc-pool-* modules prior to version 1.0.0 create a pool and a pool-xa DataSourceFactory service. Unfortunately this confused many users. Another problem was that there was no error in the log when pax-jdbc-config did not find the correct DataSourceFactory. It just did not create a DataSource then.

In pax-jdbc 1.0.0 the pooling modules each expose an OSGi service with interface PooledDataSourceFactory. This service is meant to be used by pax-jdbc-config to wrap the DataSource. So the user always refers to the original DataSourceFactory service in the config and just adds the pool and xa config properties to enable pooling. This allows pax-jdbc-config to report when the pooling support or the TransactionManager is missing. We hope this makes it easier for users to get a fully enabled Datasource working.


There are several pooling modules in pax-jdbc:

NameModuleDescription
dbcp2pax-jdbc-pool-dbcpPooling and JTA support using dbcp2
ariespax-jdbc-pool-ariesPooling and JTA support using aries transaction jdbc
hikaripax-jdbc-pool-hikariPooling and JTA support using hikari

How it works

Each pooling module publishes an OSGi service with the interface PooledDataSourceFactory. This service allows to create a pooled and optionally XA enabled DataSource from a normal DataSourceFactory. While it is possible to use the pooling support programmatically the main purpose is to let the config support create pooled DataSources from config.

Keep in mind that the pooled XA DataSource will be published using the javax.sql.DataSource interface. So from the outside it will look like a normal DataSource. Inside it will take care that the connection is added to the TransactionManager as an XA resource.

Additonal config properties to enable pooling and XA

The new pooled DataSourceFactory OSGi service provided by pax-jdbc-pool adds the following properties while keeping the properties of the original DataSourceFactory.

KeyValueDefaultDescription
poolname of the pooling support to usenull (no pooling)Decide which pooling support to use. For example use pool=dbcp2 to use the dbcp2 support
xatrue / falsefalseSet xa=true to auto enlist as an XA resource. You will need a TransactionManager service to make this work

pax-jdbc-pool-dbcp2 configuration

When calling create you should supply the pooled DataSourceFactory with the same properties as the original one. In addition you can also set pooling properties that start with "pool.". These will be forwarded to the pooling library.

See http://commons.apache.org/proper/commons-dbcp/configuration.html.

KeyTypeDescription
jdbc.pool.blockWhenExhaustedboolean

Sets whether to block when the borrowObject() method is invoked when the pool is exhausted (the maximum number of "active" objects has been reached)

jdbc.pool.lifobooleanSets whether the pool has LIFO (last in, first out) behaviour with respect to idle objects - always returning the most recently used object from the pool, or as a FIFO (first in, first out) queue, where the pool always returns the oldest object in the idle object pool
jdbc.pool.maxIdleintReturns the cap on the number of "idle" instances in the pool
jdbc.pool.maxTotalintSets the cap on the number of objects that can be allocated by the pool (checked out to clients, or idle awaiting checkout) at a given time
jdbc.pool.maxWaitMillislongSets the maximum amount of time (in milliseconds) the borrowObject() method should block before throwing an exception when the pool is exhausted and getBlockWhenExhausted() is true
jdbc.pool.minEvictableIdleTimeMillislongSets the minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle object evictor (if any - see setTimeBetweenEvictionRunsMillis(long))
jdbc.pool.minIdleintSets the target for the minimum number of idle objects to maintain in the pool
jdbc.pool.numTestsPerEvictionRunintSets the maximum number of objects to examine during each run (if any) of the idle object evictor thread
jdbc.pool.softMinEvictableIdleTimeMillislongSets the minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle object evictor (if any - see setTimeBetweenEvictionRunsMillis(long)), with the extra condition that at least minIdle object instances remain in the pool
jdbc.pool.testOnBorrowbooleanSets whether objects borrowed from the pool will be validated before being returned from the borrowObject() method
jdbc.pool.testOnCreatebooleanSets whether objects created for the pool will be validated before being returned from the borrowObject() method
jdbc.pool.testOnReturnbooleanSets whether objects borrowed from the pool will be validated when they are returned to the pool via the returnObject() method
jdbc.pool.testWhileIdlebooleanReturns whether objects sitting idle in the pool will be validated by the idle object evictor (if any - see setTimeBetweenEvictionRunsMillis(long))
jdbc.pool.timeBetweenEvictionRunsMillislongSets the number of milliseconds to sleep between runs of the idle object evictor thread


The following properties will only work for pax-jdbc-pool >= 0.6.0

KeyTypeDescriptionDefault
jdbc.factory.cacheStatebooleanIf true, the pooled connection will cache the current readOnly and autoCommit settings when first read or written and on all subsequent writes. This removes the need for additional database queries for any further calls to the getter. If the underlying connection is accessed directly and the readOnly and/or autoCommit settings changed the cached values will not reflect the current state. In this case, caching should be disabled by setting this attribute to falsetrue
jdbc.factory.defaultAutoCommitbooleanThe default auto-commit state of connections created by this pool. If not set then the setAutoCommit method will not be calleddriver default
jdbc.factory.defaultCatalogStringSets the default "catalog" setting for borrowed Connectionsdriver default
jdbc.factory.defaultReadOnlybooleanThe default read-only state of connections created by this pool. If not set then the setReadOnly method will not be called. (Some drivers don't support read only mode, ex: Informix)driver default
jdbc.factory.defaultTransactionIsolationintThe default TransactionIsolation state of connections created by this pool. One of the following: (see javadoc for int values)
  • NONE
  • READ_COMMITTED
  • READ_UNCOMMITTED
  • REPEATABLE_READ
  • SERIALIZABLE
driver default
jdbc.factory.maxConnLifetimeMillislongThe maximum lifetime in milliseconds of a connection. After this time is exceeded the connection will fail the next activation, passivation or validation test. A value of zero or less means the connection has an infinite lifetime.-1
jdbc.factory.validationQueryStringThe SQL query that will be used to validate connections from this pool before returning them to the caller. If specified, this query MUST be an SQL SELECT statement that returns at least one row. If not specified, connections will be validation by calling the isValid() method.


Example config for pax-jdbc-pool-dbcp2 together with pax-jdbc-config

Create config in etc/org.ops4j.datasource-test.cfg:

osgi.jdbc.driver.name=H2
pool=dbcp2
xa=true
databaseName=test
user=sa
password=
dataSourceName=test2
jdbc.pool.maxTotal=8

Installation in karaf >= 3

Install the features

Installation
feature:repo-add mvn:org.ops4j.pax.jdbc/pax-jdbc-features/1.4.4/xml/features
feature:install transaction jndi pax-jdbc-h2 pax-jdbc-config pax-jdbc-pool-dbcp2

Check the created DataSource:

DataSource
karaf@root()> service:list javax.sql.DataSource

If the DataSource is not created the log should tell what is wrong.

Tracking errors

If you see a log message like:

Tracking pooling support with filter (&(objectClass=org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory)(pool=dbcp2)(xa=true))

This means that pax-jdbc-config found your DataSource config and detected that you require a pooling module dbcp2 and xa support. If the DataSource is not installed then this means that you have either not installed the pax-jdbc-pool-dbcp2 module or the transaction manager bundle.