|
Technical Note
Connection Caching in OC4J 10g 10.1.3 Data Sources
Author: Frances Zhao
Published: July 2004
One of the most time-consuming operations in deploying J2EE applications is
establishing a connection to the database. Application servers commonly
offer connection caching, or pooling, to minimize the overhead
incurred for this task. (Although the terms "connection caching" and "pooling" have different meanings in JDBC, we will use the terms interchangeably here.)
In Oracle Application Server Containers for J2EE 10g (OC4J) 9.0.4, data sources employed
different connection caching mechanisms, depending on the type of data
sources. OC4J 10g 10.1.3, however, includes several key improvements in data
sources, one of which is a new connection caching mechanism that is uniform
across Oracle data sources and also offers integrated Real Application Clusters (RAC) failover support.
This mechanism leverages the new JDBC connection caching features
from Oracle Database 10g. (Note: OC4J 10g 10.0.3 was recently reversioned to 10.1.3, and the next public release will reflect this change. All references to version 10.1.3 here are applicable to the currently available 10.0.3 release.)
This Technical Note offers a close look at this
new feature, and illustrates how it is used in applications.
OC4J 10g 10.1.3 Data Sources: An Overview
OC4J 10g 10.1.3 has simplified the data source classification:
now there are only two types of data sources: managed data source
and native data source.
Managed data sources are data sources that are managed by OC4J.
Specifically, a managed data source is an OC4J-provided implementation
of the java.sql.DataSource interface that acts as a wrapper to a JDBC
driver or data source. J2EE components access managed data sources
via JNDI with no knowledge that the data source implementation is a wrapper.
OC4J provides critical system infrastructure, such as global transaction
management, connection caching, dynamic configuration via JMX, and error
handling, for managed data sources.
Native data sources also implement the java.sql.DataSource interface,
and are provided by JDBC-driver vendors such as Oracle and DataDirect. Native data sources are not wrapped by OC4J at all.
Key differences between managed and native data sources are summarized in the
following table:
|
Managed Data Source |
Native Data Source |
| Connections retrieved from a data source can participate in global transactions |
Yes
|
No
|
| Data
source makes use of OC4J's connection pool and statement caches |
Yes |
No
|
| Connection
returned from a data source rapped with an OC4J Connection Proxy |
Yes |
No
|
Connection Caching
Connection caching, generally implemented in the middle tier,
allows a single database connection to be shared among different applications.
The middle tier maintains a pool of pre-allocated physical database
connections that applications can use to interact with database servers.
When applications request a database connection, the middle tier
first looks in the pool to see if there are any available connections
that would satisfy the request; if so, the middle tier simply returns one
of those connections.
In a scenario where a connection is requested and the
connection cache does not have any free-pooled connection instances,
new pooled connection instances are created. A "free" pooled
connection instance is one that currently has no logical connection
instances associated with it; in other words, it is a pooled connection
instance whose physical connection is not being used.
When applications close the connections, the middle tier
would send the connections back to the pool, thereby avoiding the resource-intensive
task of opening a new database connection each time a connection request
is made.
The pooled connections in the cache all have some connection
properties or attributes (database name, server name, port
number, and so on). Most connection caches consist of a pool
of one or more connections to the same database for the same username.
Connection Caching in OC4J 10g 10.1.3 Data Sources
Connection caching in OC4J 10g 10.1.3 data sources leverages
all of the new caching features provided by Oracle Database 10g JDBCspecifically, features in the new Implicit Connection Cache.
Prior to Oracle Database 10g, Oracle JDBC's connection
cache interface was named OracleConnectionCache and its implementation
was named OracleConnectionCacheImpl. The cache only supported pooling
of physical connections to a particular database for a specified username.
In Oracle 10g JDBC, the OracleConnectionCache interface and the OracleConnectionCacheImpl
class are both deprecated, moving toward a more robust and performance-oriented
architecture. The new architecture was designed so that connection
caching can be transparently integrated into data sources.
Implicit Connection Cache is a new JDBC 3.0-compliant connection
cache implementation for data sources. It eliminates the need for
application developers to write their own cache implementations by
offering transparent access to the cache. It also provides support
for multiple users and the ability to request connections based on
user-defined attributes.
The Implicit Connection Cache works on the concepts
of physical and logical connections. It uses the standard OracleDataSource
APIs to get connections, and it services all connection requests from
the connection cache after caching is enabled by the underlying application.
The physical connections are the actual connections returned by the
database, whereas the logical connections can be thought of as handles
used by the cache to manipulate the physical connections.
Implicit connection caching also provides a new class, OracleConnectionCacheManager, so that applications can use its rich set of administrative
APIs to create, manage, and maintain the connection caches in an
efficient way. Applications
can manage their cache either through the single OracleConnectionCacheManager
instance, or through the OracleDataSource associated with the cache. These APIs are used extensively
in OC4J 10g 10.1.3.
A callback mechanism
is also provided for users to define cache behavior and determine
the exact connections retrieved from the cache via the user-defined
connection attributes.
The new connection caching mechanism also includes
integrated RAC failover support for Oracle databases. It provides the
ability to failover connections in the connection cache as quickly and efficiently
as the database itself, which is achieved by listening to the UP/DOWN RAC
failover events generated by the database. The event publish/subscribe mechanism
is provided by Oracle Notification Service(ONS). Such support only works
for the RAC database, since it supports generation of the desired failover
events.
Some of the advantages associated with the new
connection caching in OC4J 10g 10.1.3 data sources include:
- Driver independence
- Transparent access
to the connection cache
- Multiple users and passwords per cache
- Compliance to JDBC
3.0 standards
- Connection recycling
and refresh of stale connections
- Attribute-based
search for connections
- Multiple cache
enabled DataSource
- Connection cache
callback mechanism
- Integrated
support for RAC fast connection failover.
Applications can easily take advantage of
the new connection caching functionality in OC4J 10g 10.1.3 data sources.
The application simply configures the data source along with its
connection cache, gets a connection from that cache, uses that connection
to carry out some business logic, and returns the connection to the cache
after use. The application can also reinitialize some connection properties
using the OracleConnectionCacheManager. Basically, applications would still
use the data sources as they typically do, like data source setup and lookup.
In addition, applications would configure the connection caches that
they wish to use. For most applications, this goal is achieved declaratively
via simple configuration attribute changes on managed as well as native
data sources. For native data sources provided by Oracle
10g JDBC, this can also occur programmatically by calling specific connection-cache
management APIs. Again, it is worth noting that these APIs are the
very same APIs that OC4J uses in offering its own connection caching.
Configuring Connection Caches Declaratively
In OC4J 10g 10.1.3, specifying connection caching attributes is relatrively easy.
For most applications, such specification is done in the data-sources.xml
configuration file declaratively.
Managed Data Source
For managed data sources, configuring connection caches can be done
in two steps:
- Add a connection cache with the <connection-pool>
XML element in data-sources.xml to specify the details of its desired
attributes.
- Use the "connection-pool-name" attribute in each <managed-data-source>
XML element in the same file to specify the name of the connection
cache that this managed data source uses to pool its connections.
Step 2 is relatively simple, so let's focus only on Step 1. The <connection-pool> element has the following
attributes (each attribute is optional except when marked as 'Required'):
| Attribute Name |
Description |
Default |
| name |
(Required)
The name of the connection pool; must be unique
|
None
|
| min-connections |
The minimum
number of connections that the connection pool will maintain
|
0
|
| max-connections |
The maximum number of
connections that can be open at any given time; a value of 0 or less indicates
that there is no maximum limit.
|
0
|
initial-limit
|
Sets the size of the connection cache
when the cache is initially created or reinitialized. When this property
is set to a value greater than 0, that many connections are pre-created
and are ready for use. This property is typically used to reduce the "ramp-up" time in priming the cache to its optimal size.
|
0
|
used-connection-wait-timeout
|
The amount of time to wait (in seconds) for
a used connection to be released by a client. This attribute applies only when
the maximum number of connections have been retrieved from the data source
and are in use. In this case, when a client tries to borrow a connection
from the pool and all connections are in use, the connection pool will wait
for a connection to be released back to the pool.
|
60
|
inactivity-timeout
|
The amount of time (in seconds) that an unused
connection is inactive before it is removed from the pool
|
60
|
login-timeout
|
The maximum amount of time (in seconds) that
this data source will wait while attempting to connect to a database.
A value of zero specifies that the timeout is the default system timeout
if there is one; otherwise, it specifies that there is no timeout.
|
0
|
connection-retry-interval
|
The interval to wait (in seconds) before retrying
a failed connection attempt; used in conjunction with "max-connnect-attempts"
|
1
|
max-connect-attempts
|
The number of times to retry making a connection; used in conjunction with "connection-retry-interval"
|
3
|
| validate-connection |
Indicates whether a connection, when
borrowed from the pool, will be validated against the database. A
value of "true" indicates that when a connection is borrowed from the connection
pool, the statement, stated by "validate-connection-statement," is executed
to verify that the connection is valid. A value of "false" means that
no statement will be executed when a connection is borrowed from the pool. Used in conjunction with "validate-connection-statement."
|
false
|
validate-connection-statement
|
The SQL statement to execute when a connection
is borrowed from the pool; used in conjunction with "validate-connection"
|
None
|
| num-cached-statements |
The maximum number of statements that should
be cached for each connection. Any value greater than 0 automatically
enables statement caching for the data source.
|
0
|
time-to-live-timeout
|
The maximum time, in seconds, a used connection
may be active. When this timeout expires, the used connection is unconditionally
closed, the relevant statement handles are canceled, and the connection
is returned to the connection pool. A value of –1 means that the feature
is not enabled.
|
-1
|
abandoned-connection-timeout
|
Oracle databases only. Abandoned-connection-timeout
is similar to the inactivity-timeout, but on a logical connection. When
set, JDBC monitors SQL database activity on this logical connection (connection
borrowed from the cache by the user). For example, when a stmt.execute()
is invoked on this connection, a heart beat is registered to convey that
this connection is active. The heart beats are monitored only at places
(to lower the cost of monitoring), that result in database execute calls.
If a connection has been inactive for the specified amount of time, the underlying
PooledConnection is reclaimed and returned to the cache for reuse. The
default value is -1, meaning, this feature is not in effect.
|
-1
|
disable-server-connection-pooling
|
Determines whether or not to disable the application
server's connection pool. This attribute is available because some
JDBC drivers provide connection pooling inside the driver. When the JDBC
driver is Oracle and the driver is using the Implicit Connection Cache, then
this attribute will be ignored.
|
false
|
property-check-interval
|
Oracle databases only. The time interval (in
seconds) for the cache daemon thread to enforce the time out limits.
|
900
|
lower-threshold-limit
|
Oracle databases only. The lower threshold
limit on the connection pool. Defaults to 20% of the max-connections.
|
20%
|
In addition to the above attributes, each <connection-pool> element
must contain one <connection-factory> element, which defines the
connection factory used to create connections for the connection pool.
It has the following attributes (each attribute is optional except when
marked as 'Required'):
| Attribute Name |
Description |
Default |
| factory-class |
(Required)
Defines the fully-pathed class of the connection-factory implementation.
It must be an implementation of java.sql.Driver, javax.sql.DataSource,
javax.sql.ConnectionPoolDataSource, or javax.sql.XADataSource.
|
None
|
| url |
(Required)
The url to use to connect to the underlying database
|
None
|
| user |
The default
user to use to connect to the database
|
None |
password
|
The default password to use to connect to the
database
|
None
|
login-timeout
|
The maximum time (in seconds) to wait while
attempting to connect to a database. A value of zero specifies that
the timeout is the default system timeout if there is one; otherwise, it
specifies that there is no timeout.
|
0
|
Now let's look at some concrete examples:
Managed Data Source Using an XADataSource Connection Factory
<managed-data-source
jndi-name="jdbc/ManagedXADS"
description="Managed DataSource"
connection-pool-name="myConnectionPool"
name="ManagedXADS"/>
<connection-pool
name="myConnectionPool"
min-connections="10"
max-connections="30"
inactivity-timeout="30">
<connection-factory
factory-class="oracle.jdbc.xa.client.OracleXADataSource"
user="scott"
password="tiger"
url="jdbc:oracle:thin:@localhost:1521:oracle"/>
<property name="nativeXA" value="true"/>
</connection-factory>
</connection-pool>
Managed Data Source Using a DataSource Connection Factory
<managed-data-source
jndi-name="jdbc/ManagedDS" description="Managed DataSource"> connection-pool-name="myConnectionPool" name="ManagedDS"/>
<connection-pool
name="myConnectionPool"
min-connections="10"
max-connections="30"
inactivity-timeout="30">
<connection-factory
factory-class="oracle.jdbc.pool.OracleDataSource"
user="scott"
password="tiger"
url="jdbc:oracle:thin:@localhost:1521:oracle"/>
<property name="loginTimeout" value="30"/>
</connection-factory>
</connection-pool>
Native Data Source
For native Oracle data sources, configuring connection caches is
primarily done programmatically. (See the following section for more details.) Declarative
configuring of connection caches can also be done in two steps:
- Use "oracle.jdbc.pool.OracleDataSource" as the value for the "data-source-class"
attribute in each <native-data-source> XML element in data-sources.xml. This is the data source implementation in the Oracle 10g
JDBC drivers that comes with implicit connection caching.
- Specify in the <property> elements within <native-data-source> any cache-specific properties to control the connection cache's behavior.
For Step 2, the following property names can be used in the <property> element's specifications:
| Name |
Type |
Description |
| connectionCacheName |
String |
Name of cache; cannot
be changed after cache has been created. |
| connectionCachingEnabled |
Boolean |
Whether Implicit Connection
Caching is enabled |
| fastConnectionFailoverEnabled |
Boolean |
Whether RAC Fast Connection
Failover is enabled |
Here's a concrete example:
<native-data-source
name="nativeDataSource"
jndi-name="jdbc/nativeDS"
description="Native DataSource"
data-source-class="oracle.jdbc.pool.OracleDataSource"
user="scott"
password="tiger"
url="jdbc:oracle:thin:@localhost:1521:oracle">
<property name="connectionCacheName" value="ICC1"/>
<property name="connectionCachingEnabled" value="true"/>
<property name="fastConnectionFailoverEnabled" value="false"/>
</native-data-source>
Configuring Connection Caches Programmatically
Managed Data Source
When using managed data sources, connection caching is specified
declaratively via the data source configuration files. This was
explained in detail in "Configuring Connection Caches Declaratively."
Native Data Source
For native data sources provided by Oracle 10g JDBC, applications have the additional option to configure connection caching
programmatically. Because caching is uniform across Oracle data
sources in OC4J 10g 10.1.3, this is not much more difficult than the declarative
approach. With this option, applications further have two ways to
take advantage of connection caching: (1) rely on the implicit connection
caching behavior in OracleDataSource and set the connection cache properties
on the data source, or (2) directly use the connection cache manager OracleConnectionCacheManager
APIs.
For (1), the OracleDataSource class provides the following setter() and
getter() methods for connection caching properties:
- String getConnectionCacheName()
- void setConnectionCacheName(String
cacheName)
- java.util.Properties getConnectionCacheProperties()
- void setConnectionCacheProperties(java.util.Properties
cp)
Each of the connection cache property here corresponds
to one configuration attribute in the managed data source case in "Configuring Connection Caches Declaratively," although the exact property name may differ slightly.
For (2), the OracleConnectionManager provides
administrative APIs that applications can use to manage available connection
caches. Following is a list of some APIs. (For more detailed information
on both (1) and (2), please refer to the Oracle Database 10g JDBC Developer's
Guide and Reference.)
- static OracleConnectionCacheManager getCacheManagerInstance()
- void createCache(String cacheName, javax.sql.DataSource
ds, Properties cacheProperties)
- String createCache(javax.sql.DataSource ds, Properties cacheProperties)
- void removeCache(String cacheName, int mode)
- void refreshCache(String cacheName, int mode)
- java.util.properties getCacheProperties(String cacheName)
The following configureDataSource method shows
the ordinary setup of OracleDataSource that is associated with the
cache. It configures the Datasource with appropriate values of host name,
user name, password, and so on. It also loads some connection properties that are
are stored in the Connection.properties file:
private void configDataSource(OracleDataSource ods) {
......
/* Load the properties file to get the connection properties
* from the Connection.properties file
*/
Properties prop = this.loadParams("Connection");
ods.setDriverType("thin");
ods.setHostName("localhost");
ods.setNetworkProtocol("tcp");
ods.setPortNumber(1521);
ods.setUser("scott");
ods.setPassword("tiger");
ods.setServiceName("oracle");
ods.setConnectionProperties(prop);
......
}
The following code illustrates the approach (1) above.
The method configCachingInDataSource
enables the connection caching and also sets the cache name, which
uniquely identifies the connection cache. It then sets some connection
cache properties on the OracleDataSource, which will be passed on to the cache.
private void configCachingInDataSource(OracleDataSource ods)
throws SQLException
{
......
ods.setConnectionCachingEnabled(true); // Enable caching
ods.setConnectionCacheName(CACHE_NAME); // Set the cache name
Properties cacheProperties = new Properties();
cacheProperties.setProperty("MinLimit", "1"); // Set Min Limit for the Cache
cacheProperties.setProperty("MaxLimit", "15"); // Set Max Limit for the Cache
cacheProperties.setProperty("InitialLimit", "10"); // Set the Initial Limit
ods.setConnectionCacheProperties(cacheProperties);
}
The following code illustrates the approach (2) above: how a connection cache is created using the OracleConnectionCacheManager.
The createCache
method is used to create the cache, while taking the OracleDataSource cache name and
the cache Properties objects. Note that the connection cache properties
are set while creating the connection cache:
private void initializeConnectionCache() throws Exception {
..............
OracleDataSource ods = new OracleDataSource();
this.configureDataSource(ods);
ods.setConnectionCachingEnabled(true); // Enable caching
// Initialize the Connection Cache
OracleConnectionCacheManager connMgr =
OracleConnectionCacheManager.getConnectionCacheManagerInstance();
/* This object holds the properties of a cache and is passed to the
* ConnectionCacheManager while creating the cache.
*/
Properties cacheProperties = new Properties();
cacheProperties.setProperty("MinLimit", "1"); // Set Min Limit for the Cache
cacheProperties.setProperty("MaxLimit", "15"); // Set Max Limit for the Cache
cacheProperties.setProperty("InitialLimit", "10"); // Set the Initial Limit
/* Create the cache by passing the cache name, data source and the
* cache properties
*/
connMgr.createCache(CACHE_NAME, ods, properties);
Summary
Database connection cache is
a powerful part of the Oracle Application Server. With simplified
data source configuration and integrated connection cache management from
Oracle Database 10g, OC4J 10g 10.1.3 provides a scalable platform for building
distributed J2EE applications.
|