Once the application has obtained a reference to the ConnectionPool object, the getConnection() call can be used to obtain a Connection object which represents this database connection to the application. It is at this point that the Session Manager binds a database connection with a Connection object.
The getConnection() call requires an active implicit transaction context. The
getConnectionWithCoordinator()call can be used to explicitly specify a transaction using its Coordinator. For more information about
getConnectionWithCoordinator(), see
“Using explicit transaction contexts”.
The getConnection() method does the following:
The following code sample shows how to get a Connection object to represent a connection.
Any errors that happen during any of the steps will be returned as exceptions to getConnection() or
getConnectionWithCoordinator(). If any of these steps fail, the Session Manager will throw an exception rather than returning a Connection object.
You can get a connection for an explicit transaction context by using getConnectionWithCoordinator(). The
getConnectionWithCoordinator() method is used for the following reasons:
If you call getConnectionWithCoordinator() and pass in a Coordinator
reference, the Session Manager will use the Coordinator to perform all the tasks it normally would do with the implicit context. Instead of using an implicit VisiTransact-managed transaction, the Session Manager uses the explicitly-stated transaction Coordinator. The connection will be set with this transaction Coordinator until you release the connection.
The following code sample shows getConnectionWithCoordinator() passing transaction context via the Coordinator.
To use a connection represented by a Connection object, the application must obtain a native connection handle from the Connection object using the getNativeConnectionHandle() method. Subsequently, the application code talks to the database directly through this native connection handle. This native connection handle can then be used to do normal data access. In other words, you can do the work in the database API with which you are familiar.
The Session Manager automatically manages the database connection's thread requirements, if there are any. The isSupported() method may be used with the
thread_portable argument to determine whether connections may be used on other threads. In general, the connection returned by the
getConnection() method is only valid on the thread used to acquire it; the application may not use the connection handle on any other thread. There may be relaxed restrictions for some implementations. For more information about thread requirements for a specific database, see
“XA Session Manager for Oracle OCI, version 9i Client” and
“DirectConnect Session Manager for Oracle OCI, version 9i Client”.
Calling release() on a Connection object ends the association of the transaction with a particular connection. Releasing the Connection object does not close the underlying database connection; the connection is returned to the pool for re-use. After releasing a Connection object, the application may not use the native connection handle or Connection object again. If you decide to perform more work on this transaction, you can obtain another Connection object.
There are two methods available for releasing a connection: release() and
releaseAndDisconnect(). For usage, see the following table.
If you are implementing an IDL interface call, you must release() or
hold() the connection before returning from that call. Failure to do so will circumvent the Session Manager's ability to avoid lost connections due to unreliable clients, and to enforce threading restrictions imposed by some database implementations.
The release() call does not release the Connection object in the sense of the CORBA
_release method. It indicates to the ConnectionPool that the connection will no longer be needed by the application. The application will still need to de-allocate the Connection object. Because these are CORBA objects, you cannot call
delete() on them. To ensure the safest management of the Connection object, hold it in a
Connection_var. When the
Connection_var is destructed, everything gets cleaned up. For the ConnectionPool object, hold it in a
ConnectionPool_var.
If release() is not called on a Connection object, the default destructor releases the connection and marks the transaction RollbackOnly. This is an easy way to make sure that all abnormal exits from this method keep the transaction from proceeding. If the application can maintain transactional integrity without rolling back, its own exception handling should release the connection explicitly, marking it for success where appropriate.
If your application receives the ProfileError exception, there are two fields in the exception: a reason and an error code. You can look at these fields to see information about the error.
If your application receives the Error exception, you need to see how long the sequence of
ErrorInfos is by invoking the
exception.info.length() method on the
ErrorInfos sequence. Once you know the length, you can step through each
ErrorInfo in the sequence.
For more information about getAttribute() and
getProfileAttributes(), and for a list of the connection attributes common to all supported databases, see VISSessionManager module in the
VisiBroker for C++ API Reference.
To obtain information such as the version of the Session Manager, whether the hold() method is supported or not, or the database's threading policy, use the following methods:
There is another more subtle reason to use hold(). Some database connections are restricted in their use to a particular thread. Here is an example of what may happen:
Using hold() gives the Session Manager a chance to inform the application that making a second interface call to the same server may not be supported for some Session Manager implementations which do not allow the connection to be used on another thread.
Using hold() monopolizes the connection and affects performance; use
hold() only when it is necessary.
The timeout parameter specifies the time in seconds that the Session Manager should wait before timing out the connection and cleaning up its resources. As part of the cleanup process, the connection is returned to the ConnectionPool and the transaction is marked for rollback.
Your application can send multiple hold() requests with no intervening
resume() calls. If
hold() is called twice, the timer is reset with the new value at each call. For example, if you send
hold(60) at 8:42:30, it would expire at 8:43:30. However, if you subsequently invoke
hold(45) at 8:42:50, the timer would expire at 8:43:35 because it had been reset by the second
hold() call.
The resume() cancels the timer associated with the
hold() and guarantees that the Session Manager will not modify the underlying connection in any way that would cause conflicts with an active application. Calling
resume() when the Connection has not been placed in the hold state results in a
VISSessionManager::Error exception, but does not modify the transaction or connection state.
Between the hold() and
resume() calls, the application is not allowed to make any other calls on the Connection object or its associated native database handle. If the
hold() call timer expires in this interval, the Session Manager has the right to release the connection and mark the transaction for rollback. This is to ensure that Resources held in the application server by that transaction are not left forever if a client dies or never calls again.
The Session Manager automatically registers the XA Resource Director with the VisiTransact Transaction Service during the getConnection() call. The Resource Director is ready and waiting for transaction completion (commit or rollback). Once all of the work of the transaction is done and the application invokes
commit() or
rollback(), the VisiTransact Transaction Service calls the Resource Director to either commit or rollback the transaction. Depending on the circumstances, the Resource Director may coordinate recovery. The Resource Director handles all recovery between XA Resources (the databases) and the VisiTransact Transaction Service without administrator intervention.
The application must have already invoked release() or
releaseAndDisconnect() before the commit so that the connection can be freed up.