A ManagedConnection object is always in one of three states: DoesNotExist, InFreePool,
or InUse.
Before a connection is created, it must be in the DoesNotExist
state. After a connection is created, it can be in either the InUse
or the InFreePool state, depending on whether it is allocated to an
application.
Between these three states are
transitions. These transitions
are controlled by
guarding conditions. A guarding condition
is one in which
true indicates when you can take the transition
into another legal state. For example, you can make the transition
from the InFreePool state to InUse state only if:
- the application has called the data source or connection factory
getConnection() method (the getConnection condition)
- a free connection is available in the pool with matching properties
(the freeConnectionAvailable condition)
- and one of the two following conditions are true:
- the getConnection() request is on behalf of a resource reference
that is marked unsharable
- the getConnection() request is on behalf of a resource reference
that is marked shareable but no shareable connection in use has the
same properties.
This transition description follows:
InFreePool > InUse:
getConnection AND
freeConnectionAvailable AND
NOT(shareableConnectionAvailable)
Here is a list of guarding conditions and descriptions.
Table 1. Guarding conditions. Here is a list of guarding
conditions and descriptions.Condition |
Description |
ageTimeoutExpired |
Connection is older then its ageTimeout
value. |
close |
Application calls close method
on the Connection object. |
fatalErrorNotification |
A connection has just experienced
a fatal error. |
freeConnectionAvailable |
A connection with matching properties
is available in the free pool. |
getConnection |
Application calls getConnection
method on a data source or connection factory object. |
markedStale |
Connection is marked as stale,
typically in response to a fatal error notification. |
noOtherReferences |
There is only one connection handle
to the managed connection, and the Transaction Service is not holding
a reference to the managed connection. |
noTx |
No transaction is in force. |
poolSizeGTMin |
Connection pool size is greater
than the minimum pool size (minimum number of connections) |
poolSizeLTMax |
Pool size is less than the maximum
pool size (maximum number of connections) |
shareableConnectionAvailable |
The getConnection() request is
for a shareable connection, and one with matching properties is in
use and available to share. |
TxEnds |
The transaction has ended. |
unshareableConnectionRequest |
The getConnection() request is
for an unshareable connection. |
unusedTimeoutExpired |
Connection is in the free pool
and not in use past its unused timeout value. |
Getting connections
The first
set of transitions covered are those in which the application requests
a connection from either a data source or a connection factory. In
some of these scenarios, a new connection to the database results.
In others, the connection might be retrieved from the connection pool
or shared with another request for a connection.
Every connection
begins its life cycle in the DoesNotExist state. When an application
server starts, the connection pool does not exist. Therefore, there
are no connections. The first connection is not created until an application
requests its first connection. Additional connections are created
as needed, according to the guarding condition.
getConnection AND
NOT(freeConnectionAvailable) AND
poolSizeLTMax AND
(NOT(shareableConnectionAvailable) OR
unshareableConnectionRequest)
This transition specifies that a connection object is
not created unless the following conditions occur:
- The application calls the getConnection() method on the data source
or connection factory
- No connections are available in the free pool (NOT(freeConnectionAvailable))
- The pool size is less than the maximum pool size (poolSizeLTMax)
- If the request is for a sharable connection and there is no sharable
connection already in use with the same sharing properties (NOT(shareableConnectionAvailable))
OR the request is for an unsharable connection (unshareableConnectionRequest)
All connections begin in the DoesNotExist state and are
only created when the application requests a connection. The pool
grows from 0 to the maximum number of connections as applications
request new connections. The pool is not created with the minimum
number of connections when the server starts.
If the request
is for a sharable connection and a connection with the same sharing
properties is already in use by the application, the connection is
shared by two or more requests for a connection. In this case, a new
connection is not created. For users of the JDBC API these sharing
properties are most often userid/password and transaction
context; for users of the Resource Adapter Common Client Interface
(CCI) they are typically ConnectionSpec, Subject, and transaction
context.
The transition from the InFreePool state to the
InUse state is the most common transition when the application requests
a connection from the pool.
InFreePool>InUse:
getConnection AND
freeConnectionAvailable AND
(unshareableConnectionRequest OR
NOT(shareableConnectionAvailable))
This transition states
that a connection is placed in use from the free pool if:
- the application has issued a getConnection() call
- a connection is available for use in the connection pool (freeConnectionAvailable),
- and one of the following is true:
- the request is for an unsharable connection (unsharableConnectionRequest)
- no connection with the same sharing properties is already in use
in the transaction. (NOT(sharableConnectionAvailable)).
Any connection request that a connection from the free
pool can fulfill does not result in a new connection to the database.
Therefore, if there is never more than one connection used at a time
from the pool by any number of applications, the pool never grows
beyond a size of one. This number can be less than the minimum number
of connections specified for the pool. One way that a pool grows to
the minimum number of connections is if the application has multiple
concurrent requests for connections that must result in a newly created
connection.
The idea of connection sharing is seen in the transition
on the InUse state.
InUse>InUse:
getConnection AND
ShareableConnectionAvailable
This transition indicates
that if an application requests a shareable connection (getConnection)
with the same sharing properties as a connection that is already
in use (ShareableConnectionAvailable), the existing connection is
shared.
The same user (
user name and
password,
or
subject, depending on authentication choice) can share connections
but only within the same transaction and only when all of the sharing
properties match. For JDBC connections, these properties include the
isolation
level, which is configurable on the resource-reference (IBM® WebSphere® extension) to data source default.
For a resource adapter factory connection, these properties include
those specified on the ConnectionSpec object. Because a transaction
is normally associated with a single thread, you should
never share
connections across threads.
Note: It is possible to see
the same connection on multiple threads at the same time, but this
situation is an error state usually caused by an application programming
error.
Returning connections
All of
the transitions discussed previously involve getting a connection
for application use. With that goal, the transitions result in a connection
closing, and either returning to the free pool or being destroyed.
Applications should explicitly close connections (note: the connection
that the user gets back is really a connection handle) by calling
close() on the connection object. In most cases, this action results
in the following transition:
InUse>InFreePool:
(close AND
noOtherReferences AND
NoTx AND
UnshareableConnection)
OR
(ShareableConnection AND
TxEnds)
Conditions that cause the transition from the InUse
state are:
- If the application or the container calls close() (producing
the close condition) and there are no references (the noOtherReferences
condition) either by the application (in the application sharing condition)
or by the transaction manager (in the NoTx condition, meaning that
the transaction manager holds a reference when the connection is enlisted
in a transaction), the connection object returns to the free pool.
- If the connection was enlisted in a transaction but the transaction
manager ends the transaction (the txEnds condition), and the connection
was a shareable connection (the ShareableConnection condition), the
connection closes and returns to the pool.
When the application calls close() on a connection,
it is returning the connection to the pool of free connections; it
is not closing the connection to the data store. When the
application calls close() on a currently shared connection, the connection
is not returned to the free pool. Only after the application
drops the last reference to the connection, and the transaction is
over, is the connection returned to the pool. Applications using unsharable
connections must take care to close connections in a timely manner.
Failure to do so can starve out the connection pool, making it impossible
for any application running on the server to get a connection.
When
the application calls close() on a connection enlisted in a transaction,
the connection is not returned to the free pool. Because the transaction
manager must also hold a reference to the connection object, the connection
cannot return to the free pool until the transaction ends. Once a
connection is enlisted in a transaction, you cannot use it in any
other transaction by any other application until after the transaction
is complete.
There is a case where an application calling close()
can result in the connection to the data store closing and bypassing
the connection return to the pool. This situation happens if one of
the connections in the pool is considered stale. A connection is considered
stale if you can no longer use it to contact the data store. For example,
a connection is marked stale if the data store server is shut down.
When a connection is marked as stale, the entire pool is cleaned out
by default because it is very likely that all of the connections are
stale for the same reason (or you can set your configuration to clean
just the failing connection). This cleansing includes marking all
of the currently InUse connections as stale so they are destroyed
upon closing. The following transition states the behavior on a call
to close() when the connection is marked as stale:
InUse>DoesNotExist:
close AND
markedStale AND
NoTx AND
noOtherReferences
This transition states that if the application
calls close() on the connection and the connection is marked as stale
during the pool cleansing step (markedStale), the connection object
closes to the data store and is not returned to the pool.
Finally,
you can close connections to the data store and remove them from the
pool.
This transition states that there are three cases in
which a connection is removed from the free pool and destroyed.
- If a fatal error notification is received from the resource adapter
(or data source). A fatal error notification (FatalErrorNotification)
is received from the resource adaptor when something happens to the
connection to make it unusable. All connections currently in the free
pool are destroyed.
- If the connection is in the free pool for longer than the unused
timeout period (UnusedTimeoutExpired) and the pool size is greater
than the minimum number of connections (poolSizeGTMin), the connection
is removed from the free pool and destroyed. This mechanism enables
the pool to shrink back to its minimum size when the demand for connections
decreases.
- If an age timeout is configured and a given connection is older
than the timeout. This mechanism provides a way to recycle connections
based on age.