Oracle® TopLink Developer's Guide 10g Release 3 (10.1.3.1.0) Part Number B28218-01 |
|
|
View PDF |
After you create and configure sessions, you can use the session manager to acquire a session instance at run time.
This section explains the following:
Oracle recommends that you export session instances from TopLink Workbench to one or more uniquely named sessions.xml
files and then use the session manager to load sessions from these sessions.xml
files.
The TopLink session manager enables developers to build a series of sessions that are maintained under a single entity. The session manager is a static utility class that loads TopLink sessions from the sessions.xml
file, caches the sessions by name in memory, and provides a single access point for TopLink sessions. The session manager supports the following session types:
Server Session
Database Session
SessionBroker
See Chapter 72, "Understanding TopLink Sessions" for detailed information on these available sessions.
The session manager has two main functions: it creates instances of the sessions and it ensures that only a single instance of each named session exists for any instance of a session manager.
This is particularly useful for EJB applications in that an enterprise bean can acquire the session manager and acquire the desired session from it.
When a client application requires a session, it requests the session from the TopLink session manager. The two main functions of the session manager are to instantiate TopLink sessions for the server, and to hold the sessions for the life of the application. The session manager instantiates database sessions, server sessions, or session brokers based on the configuration information in the sessions.xml
file.
The session manager instantiates sessions as follows:
The client application requests a session by name.
The session manager looks up the session name in the sessions.xml
file. If the session name exists, the session manager instantiates the specified session; otherwise, it throws an exception.
After instantiation, the session remains viable until the application is shut down.
Oracle does not recommend instantiating a session and passing it around as a global entity.
Oracle recommends that you acquire sessions from the session manager and perform all persistence operations using the unit of work acquired from the session.
Note that in the case of a server session or a session broker that contains server sessions, after you acquire the session you will acquire a client session from it. From a given server session (or session broker that contains server sessions), you can acquire as many client sessions as you have clients.
Each client can easily manage concurrent access and referential constraints by acquiring a unit of work from its client session and performing all persistence operations using the unit of work.
TopLink maintains only one instance of the session manager class. The singleton session manager maintains all the named TopLink sessions at run time. When an application requests a session by name, the session manager retrieves the specified session from the appropriate configuration file.
As Example 75-1 illustrates, to access the session manager instance, use the oracle.toplink.tools.sessionmanagement.SessionManager
method getManager
. You can then use the session manager instance to load TopLink sessions.
When the session manager loads a session that is not yet in its cache, the session manager creates an instance of the appropriate session type and configures it according to the sessions.xml
file configuration.
Note: To best use the methods associated with the session type that is being instantiated, cast the session that is returned from thegetSession method. This type must match the session type that is defined in the sessions.xml file for the named session. |
This section explains the following:
Loading a Session From sessions.xml With an Alternative Class Loader
Loading a Session From an Alternative Session Configuration File
If you have a single sessions configuration file (sessions.xml
) that contains all the session instances created from by TopLink Workbench, then you can load a session by name, as Example 75-2 illustrates.
Example 75-2 Acquiring a Named Session from Session Manager Using Defaults
/* Load a named session (mysession) defined in the sessions.xml file. */
SessionManager manager = SessionManager.getManager();
Session session = manager.getSession("mysession");
In this example, the following session manager default configuration applies:
Class loader–The thread-based class loader is used to find and load the sessions.xml
resource and resolve any classes referenced in the sessions.xml
and project.xml
files.
If you acquire the session in an application class, this will typically be the application's class loader, which is correct. In a J2EE application, it is best to specify this as the class loader from a class in the same JAR file that the sessions.xml
file is deployed in.
File–By default, the file named sessions.xml
in the root directory relative to the class loader is used.
If the file is named differently, or not in the root directory, the relative path must be specified. Relative resource paths in Java must use /
, not \
.
Session name–The name passed into the getSession
call.
This name must be unique for the entire application server, not just unique within the application.
Login–true
. The session will be connected by default.
If you must manually configure the session before login, set this option to false
(see "Loading a Session Without Logging In").
Refresh–false
. If already loaded, the same session will be returned.
Refresh should only be used, if it is known that the existing session is not being used, and the configuration has changed, such as in a J2EE environment redeployment scenario.
Verify class loader–false. The session manager will not refresh the session if the class loader changes.
This should normally be set to true
. It must be set to true
in a J2EE environment, if hot deployment or redeployment to a running application server is required (see "Refreshing a Session When the Class Loader Changes").
You can use an alternative class loader to load sessions. This is common when your TopLink application integrates with a J2EE container. The session manager uses the class loader to find and load the sessions.xml
resource and resolve any classes referenced in the sessions.xml
and project.xml
files.
In most cases, you use the class loader from the current thread context, as Example 75-3 illustrates. In this example, the session named mysession
is loaded from the first file in the application classpath named sessions.xml
using the class loader associated with the current thread context.
Example 75-3 Loading a Session Using the Current Thread Context Class Loader
/* Use the specified ClassLoader to load a session (mysession) defined in the sessions.xml file */ SessionManager manager = SessionManager.getManager(); Session session = manager.getSession( "mysession", // session name to load Thread.current().getContextClassLoader() // ClassLoader instance to use );
However, if your J2EE container does not support using the current thread context class loader, you can use the class loader from the current class, as Example 75-4 illustrates.
Example 75-4 Loading a Session Using the Current Class's Class Loader
/* Use the specified ClassLoader to load a session (mysession) defined in the sessions.xml file */ SessionManager manager = SessionManager.getManager(); Session session = manager.getSession( "mysession", // session name to load this.getClass().getClassLoader() // ClassLoader instance to use );
Note: Oracle Containers for J2EE supports the use of the class loader from the current thread. |
If your session instances are contained in multiple, uniquely named session configuration files (sessions.xml
files), then you must explicitly create an XMLSessionConfigLoader
object initialized with the name of the sessions.xml
file and pass that XMLSessionConfigLoader
into the SessionManager
method getSession
, as Example 75-5 illustrates.
The file path you specify is relative to the class loader root directory. Relative resource paths in Java must use the forward slash ( /
), not back slash ( \ )
.
In this example, the session named mysession
is loaded by the specified class loader from the first file in the application classpath named toplink-sessions.xml
.
Example 75-5 Loading a Session from an Alternative Configuration File
/* XMLSessionConfigLoader loads the toplink-sessions.xml file */
SessionManager manager = SessionManager.getManager();
manager.getSession(
new XMLSessionConfigLoader("toplink-sessions.xml"),
"mysession",
this.class.getClassLoader()
);
The XMLSessionConfigLoader
(see "Loading a Session From an Alternative Session Configuration File") lets you call a session using the SessionManager
method getSession
, without invoking the Session
method login
, as Example 75-6 shows. This lets you prepare a session for use and leave login to the application.
Example 75-6 Open Session with No Login
SessionManager manager = SessionManager.getManager(); Session session = manager.getSession( new XMLSessionConfigLoader(), // XMLSessionConfigLoader (sessions.xml file) "mysession", // session name YourApplicationClass.getClassLoader(), // class loader false, // do not log in session false); // do not refresh session
You can tell the session manager to refresh an existing session from the sessions.xml
file. Typically, this would only ever be used in a J2EE environment at redeployment time, or after a reset of a running server. You should only use this option when you know that the existing session is not being used.
Example 75-7 Forcing a Reparse of the sessions.xml File
//In this example, XMLSessionConfigLoader loads sessions.xml from the classpath SessionManager manager = SessionManager.getManager(); Session session = manager.getSession( new XMLSessionConfigLoader(), // XMLSessionConfigLoader (sessions.xml file) "mysession", // session name YourApplicationClass.getClassLoader(), // class loader true, // log in session true // refresh session );
In a non-CMP J2EE environment, if you require hot deployment or redeployment to a running application server, you must tell the session manager to refresh your session if the class loader changes, as Example 75-8 shows. This option makes the session manager refresh the session if the class loader changes, which occurs when the application is redeployed. When this option is set to true
, the same class loader must always be used to retrieve the session.
Example 75-8 Forcing a Reparse of the sessions.xml File
//In this example, XMLSessionConfigLoader loads sessions.xml from the classpath SessionManager manager = SessionManager.getManager(); Session session = manager.getSession( new XMLSessionConfigLoader(), // XMLSessionConfigLoader (sessions.xml file) "mysession", // session name YourApplicationClass.getClassLoader(), // class loader true, // log in session false, // do not refresh session when loaded true // do refresh session if class loader changes );
In a CMP J2EE environment, the TopLink runtime and CMP integration handles this for you automatically.
Before you can acquire a client session, you must first use the session manager to acquire a server session or a session broker that contains server sessions (see "Acquiring a Session From the Session Manager").
Table 75-1 summarizes the methods used to acquire various types of client sessions from a server session and a session broker session that contains server sessions.
Table 75-1 Method Used to Acquire a Client Session
Client Session | Server Session Method | Session Broker Session Method |
---|---|---|
Regular or Isolated |
|
|
Regular or Isolated |
|
not applicable |
Historical |
|
not applicable |
The acquireClientSession
method returns a session of type ClientSession
.
The acquireClientSessionBroker
method returns a session of type SessionBroker
.
In both cases, you should cast the returned object to type Session
and use it as you would any other session.
For more information, see the following:
"Acquiring a Client Session That Uses Exclusive Connections"
"Acquiring a Client Session That Uses Connection Properties"
"Acquiring a Client Session That Uses a Named Connection Pool"
"Acquiring a Client Session That Does Not Use Lazy Connection Allocation"
If in your TopLink project you configure all classes as isolated (see "Configuring Cache Isolation at the Project Level"), or one or more classes as isolated (see "Configuring Cache Isolation at the Descriptor Level"), then all client sessions that you acquire from a parent server session will be isolated client sessions (see "Isolated Client Sessions").
Using a ConnectionPolicy
, you can acquire an isolated client session that uses exclusive connections (see "Acquiring a Client Session That Uses Exclusive Connections"). This isolated client session can be configured with connection properties for use with the Oracle Virtual Private Database (VPD) feature (see "Acquiring a Client Session That Uses Connection Properties").
For more information about VPD, see "Isolated Client Sessions and Oracle Virtual Private Database (VPD)".
Example 75-9 illustrates how to configure a ConnectionPolicy
and use it to acquire a client session that uses exclusive connections.
Example 75-9 Acquiring a Client Session that Uses Connection Properties
ConnectionPolicy connectionPolicy = new ConnectionPolicy(); // Use an exclusive connection for the session connectionPolicy.setShouldUseExclusiveConnection(true); Session clientSession = server.acquireClientSession(connectionPolicy); // By default, an exclusive connection will be acquired lazily
An exclusive connection is allocated from a shared connection pool. The connection is dedicated to the client session that acquires it.
Note: Typically, the life cycle of a client session is the duration of a server request. However, if you are using JTA, it is the life cycle of a JTA transaction.You cannot hold the client session across the JTA transaction boundaries. If you are not using a unit of work in your transaction and you are configuring a client session to use an exclusive connection (see Chapter 77, "Configuring Exclusive Isolated Client Sessions for Virtual Private Database"), you must explicitly acquire and release the session when you are finished using it. Although client sessions have a finalizer that would release the session when it is garbage-collected, you must not rely on the finalizer and release the exclusive client session (or a non-lazy session) in the application to release the data source connection. Note that the requirement to release the session in not JTA-specific. If you are using a unit of work (see Chapter 99, "Using Advanced Unit of Work API"), you do not have to worry about releasing its client session as the unit of work always automatically releases it at the end of the JTA transaction. |
A named query can also use an exclusive connection (see "Configuring Named Query Advanced Options").
For more information, see the following:
Example 75-10 illustrates how to configure a ConnectionPolicy
and use it to acquire a client session that uses connection properties. In this example, the properties are used by the Oracle VPD feature (see "Isolated Client Sessions and Oracle Virtual Private Database (VPD)"). You can use connection properties for other application purposes.
Example 75-10 Acquiring an Isolated Session Using Connection Properties
ConnectionPolicy connectionPolicy = new ConnectionPolicy();
// Set VPD specific properties to be used in the events
connectionPolicy.setProperty("userLevel", new Integer(5));
Session clientSession = server.acquireClientSession(connectionPolicy);
For more information, see "Configuring Connection Policy".
Before you can acquire a client session that uses a named connection pool, you must configure your session with a named connection pool. For more information on named connection pools, see "Application-Specific Connection Pools". For more information on creating a named connection pool, see "Internal Connection Pool Creation Overview".
To acquire a client session that uses a named connection pool, use Server
method acquireClientSession
, passing in a ConnectionPolicy
configured with the desired connection pool. The acquired ClientSession
uses connections from the specified pool for writes (reads still go through the Server
read connection pool).
Example 75-11 illustrates how to configure a ConnectionPolicy
to specify a named connection pool named myConnectionPool
.
Example 75-11 Acquiring a Client Session that Uses a Named Connection Pool
// Assuming you created a connection pool named "myConnectionPool"
Session clientSession = server.acquireClientSession(
new ConnectionPolicy("myConnectionPool")
);
For more information, see "Configuring Connection Policy".
By default, the server session does not allocate a data source connection for a client session until a transaction starts (a lazy data source connection). Alternatively, you can acquire a client session that allocates a connection immediately.
Example 75-12 illustrates how to configure a ConnectionPolicy
to specify that lazy connection allocation is not used.
Example 75-12 Acquiring a Client Session that Does Not Use Lazy Connections
ConnectionPolicy connectionPolicy = new ConnectionPolicy(); connectionPolicy.setIsLazy(false); Session clientSession = server.acquireClientSession(connectionPolicy);
For more information, see "Configuring Connection Policy".
After you configure TopLink to access historical data (see "Historical Session Configuration Overview"), you can query historical data using any session type.
When you query historical data using a regular client session or database session, you must always set ObjectLevelReadQuery
method maintainCache
to false
in order to prevent old (historical) data from corrupting the session cache. However, you can query both current and historical object versions.
As a convenience, TopLink provides a historical session to simplify this process. When you query historical data using a historical session, you do not need to set ObjectLevelReadQuery
method maintainCache
to false
. However, you can query objects only as of the specified time.
Before you can acquire a historical session, you must first use the session manager to acquire a server session.
To acquire a historical session, use Server
method acquireHistoricalSession
passing in an AsOfClause
.
The AsOfClause
specifies a point in time that applies to all queries and expressions subsequently executed on the historical session. The historical session's cache is a read-only snapshot of object versions as of the specified time. Its cache is isolated from its parent server session's shared object cache.
Before you can use a session, you must first log in to the session using Session
method login
.
By default, when you load a session using the session manager, TopLink automatically logs in to the session using the zero-argument login
method. For information on loading a session without automatically logging into the session, see "Loading a Session Without Logging In".
If you load a session without logging in, you can choose from the following signatures of the login
method:
login()
: Use the Login, user name, and password defined in the corresponding sessions.xml
file.
login(Login login)
: Override the Login
defined in the corresponding sessions.xml
file with the specified Login
.
login(String username, String password)
: Override the user name and password defined in the corresponding sessions.xml
file with the specified user name and password.
When you log in to a session broker, the session broker logs in all contained sessions and initializes the descriptors in the sessions. After login, the session broker appears and functions as a regular session. TopLink handles the multiple database access transparently.
For more information on using session API, for caching, see "Understanding the Cache".
For more information on using session API for queries, see "Understanding TopLink Queries".
For more information on using session API for transactions, see "Understanding TopLink Transactions".
When you are finished using a database or server session, you must log out of the session using Session
method logout
.
When logging out of a session broker session logs out of all sessions registered with the session broker.
When you are finished using a client session, you must release the session and any connections allocated to it using Session
method release
.
Although TopLink provides a finalizer to release sessions, this is a last resort. Oracle recommends that you always log out of your sessions.
Although Oracle recommends that you export all session instances from TopLink Workbench to one or more sessions.xml
files, alternatively, you can manually create a session in your application and, as Example 75-13 illustrates, manually store it in the session manager using SessionManager
method addSession
. Then, you can acquire a session by name using the SessionManager
method getSession
.
Note: TheaddSession method is not necessary if you are loading sessions from a session configuration file. |
Example 75-13 Storing Sessions Manually in the Session Manager
// create and log in to the session programmatically Session theSession = project.createDatabaseSession(); theSession.login(); // store the session in the SessionManager instance SessionManager manager = SessionManager.getManager(); manager.addSession("mysession", theSession); // retrieve the session Session session = SessionManager.getManager().getSession("mysession");
You can destroy sessions individually by name or destroy all sessions.
Note: You should only do this when a J2EE application is un-deployed, or when the entire application is shut down and only when it is known that the session is no longer in use. You should log out of a session before destroying it (see "Logging Out of a Session"). If you do not log out of a session, the session manager will at the time you use it to destroy a session. |
To destroy one session instance by name, use SessionManager
method destroySession
, as Example 75-14 illustrates. If the specified session is not in the session manager cache, a ValidationException
is thrown.
Example 75-14 Destroying a Session in the Session Manager
SessionManager manager = SessionManager.getManager(); Server server = (Server) manager.getSession("myserversession"); … // Destroy session by name. If the session named myserversession is not in the // session manager cache, throw a ValidationException manager.destroySession("myserversession");
To destroy all session instances, use the SessionManager
method destoryAllSessions
, as Example 75-15 illustrates.
Example 75-15 Destroying All Sessions in the Session Manager
SessionManager manager = SessionManager.getManager();
Server server = (Server) manager.getSession("myserversession");
SessionBroker broker = (SessionBroker) manager.getSession("mysessionbroker");
…
// Destroy all sessions stored in the session manager
manager.destroyAllSessions();