FileDocCategorySizeDatePackage
DatabaseSessionImpl.javaAPI DocGlassfish v2 API30045Thu Jul 26 13:42:36 BST 2007oracle.toplink.essentials.internal.sessions

DatabaseSessionImpl

public class DatabaseSessionImpl extends AbstractSession implements DatabaseSession
Implementation of oracle.toplink.essentials.sessions.DatabaseSession The public interface should be used by public API, the implementation should be used internally.
see
oracle.toplink.essentials.sessions.DatabaseSession

Purpose: Define the implementation for a single user/single connection TopLink session.

Description: The session is the primary interface into TopLink, the application should do all of its reading and writing of objects through the session. The session also manages transactions and units of work. The database session is intended for usage in two-tier client-server applications. Although it could be used in a server situation, it is limitted to only having a single database connection and only allows a single open database transaction.

Responsibilities:

  • Connecting/disconnecting.
  • Reading and writing objects.
  • Transaction and unit of work support.
  • Identity maps and caching.

Fields Summary
private SequencingHome
sequencingHome
INTERNAL: sequencingHome for this session.
private ServerPlatform
serverPlatform
Used to store the server platform that handles server-specific functionality for Oc4j, WLS, etc.
private long
connectedTime
INTERNAL: connectedTime indicates the exact time this session was logged in.
protected boolean
isLoggedIn
INTERNAL Indicate if this session is logged in.
Constructors Summary
public DatabaseSessionImpl()
INTERNAL: Create and return a new default database session. Used for EJB SessionManager to instantiate a database session

        super();
        this.setServerPlatform(new NoServerPlatform(this));
    
public DatabaseSessionImpl(Login login)
PUBLIC: Create and return a new session. By giving the login information on creation this allows the session to initialize itself to the platform given in the login. This constructor does not return a connected session. To connect the session to the database login() must be sent to it. The login(userName, password) method may also be used to connect the session, this allows for the user name and password to be given at login but for the other database information to be provided when the session is created.

        this(new oracle.toplink.essentials.sessions.Project(login));
    
public DatabaseSessionImpl(Project project)
PUBLIC: Create and return a new session. This constructor does not return a connected session. To connect the session to the database login() must be sent to it. The login(userName, password) method may also be used to connect the session, this allows for the user name and password to be given at login but for the other database information to be provided when the session is created.

        super(project);
        this.setServerPlatform(new NoServerPlatform(this));
    
Methods Summary
public voidaddDescriptor(oracle.toplink.essentials.descriptors.ClassDescriptor descriptor)
PUBLIC: Add the descriptor to the session. All persistent classes must have a descriptor registered for them with the session. It is best to add the descriptors before login, if added after login the order in which descriptors are added is dependant on inheritice and references unless the addDescriptors method is used.

see
#addDescriptors(Vector)
see
#addDescriptors(oracle.toplink.essentials.sessions.Project)

        // Reset cached data, as may be invalid later on.
        this.lastDescriptorAccessed = null;

        getProject().addDescriptor(descriptor, this);
    
public voidaddDescriptors(java.util.Vector descriptors)
PUBLIC: Add the descriptors to the session. All persistent classes must have a descriptor registered for them with the session. This method allows for a batch of descriptors to be added at once so that TopLink can resolve the dependancies between the descriptors and perform initialization optimially.

        // Reset cached data, as may be invalid later on.
        this.lastDescriptorAccessed = null;

        getProject().addDescriptors(descriptors, this);
    
public voidaddDescriptors(oracle.toplink.essentials.sessions.Project project)
PUBLIC: Add the descriptors to the session from the Project. This can be used to combine the descriptors from multiple projects into a single session. This can be called after the session has been connected as long as there are no external dependencies.

        // Reset cached data, as may be invalid later on.
        this.lastDescriptorAccessed = null;

        getProject().addDescriptors(project, this);
    
public voidafterTransaction(boolean committed, boolean isExternalTransaction)
INTERNAL: Called after transaction is completed (committed or rolled back)

        SequencingCallback callback = getSequencingHome().getSequencingCallback();
        if (callback != null) {
            callback.afterTransaction(getAccessor(), committed);
        }
    
public voidconnect()
INTERNAL: Connect the session only.

        getAccessor().connect(getDatasourceLogin(), this);
    
public voiddisconnect()
INTERNAL: Disconnect the accessor only.

        getSequencingHome().onDisconnect();
        getAccessor().disconnect(this);
    
protected voidfinalize()
INTERNAL: Logout in case still connected.

        if (isConnected()) {
            logout();
        }
    
public longgetConnectedTime()
PUBLIC: Answer the time that this session got connected. This can help determine how long a session has been connected.

        return connectedTime;
    
public oracle.toplink.essentials.internal.databaseaccess.PlatformgetDatasourcePlatform()
INTERNAL: Return the database platform currently connected to. The platform is used for database specific behavior.

        // PERF: Cache the platform.
        if (platform == null) {
            if(isLoggedIn) {
                platform = getDatasourceLogin().getDatasourcePlatform();
            } else {
                return getDatasourceLogin().getDatasourcePlatform();
            }
        }
        return platform;
    
public java.util.MapgetDescriptors()
PUBLIC: Return all registered descriptors.

        return getProject().getDescriptors();
    
public oracle.toplink.essentials.internal.databaseaccess.DatabasePlatformgetPlatform()
INTERNAL: Return the database platform currently connected to. The platform is used for database specific behavior. NOTE: this must only be used for relational specific usage, it will fail for non-relational datasources.

        // PERF: Cache the platform.
        if (platform == null) {
            if(isLoggedIn) {
                platform = getDatasourceLogin().getPlatform();
            } else {
                return getDatasourceLogin().getPlatform();
            }
        }
        return (DatabasePlatform)platform;
    
protected oracle.toplink.essentials.sessions.LogingetReadLogin()
INTERNAL: Return the login for the read connection. Used by the platform autodetect feature

        return getDatasourceLogin();
    
public oracle.toplink.essentials.internal.sequencing.SequencinggetSequencing()
INTERNAL: Return the Sequencing object used by the session.

        return getSequencingHome().getSequencing();
    
public oracle.toplink.essentials.sequencing.SequencingControlgetSequencingControl()
PUBLIC: Return SequencingControl which used for sequencing setup and customization including management of sequencing preallocation.

        return getSequencingHome().getSequencingControl();
    
protected oracle.toplink.essentials.internal.sequencing.SequencingHomegetSequencingHome()
INTERNAL: Return SequencingHome which used to obtain all sequence-related interfaces for DatabaseSession

        if (sequencingHome == null) {
            setSequencingHome(SequencingFactory.createSequencingHome(this));
        }
        return sequencingHome;
    
public oracle.toplink.essentials.platform.server.ServerPlatformgetServerPlatform()
PUBLIC: Answer the server platform to handle server specific behaviour for WLS, Oc4j, etc. If the user wants a different external transaction controller class or to provide some different behaviour than the provided ServerPlatform(s), we recommend subclassing oracle.toplink.essentials.platform.server.ServerPlatformBase (or a subclass), and overriding: ServerPlatformBase.getExternalTransactionControllerClass() ServerPlatformBase.registerMBean() ServerPlatformBase.unregisterMBean() for the desired behaviour.

see
oracle.toplink.essentials.platform.server.ServerPlatformBase

        return serverPlatform;
    
public voidinitializeConnectedTime()
PUBLIC: Initialize the time that this session got connected. This can help determine how long a session has been connected.

        connectedTime = System.currentTimeMillis();
    
public voidinitializeDescriptorIfSessionAlive(oracle.toplink.essentials.descriptors.ClassDescriptor descriptor)
INTERNAL: A descriptor may have been added after the session is logged in. In this case the descriptor must be allowed to initialize any dependancies on this session. Normally the descriptors are added before login, then initialized on login.

        if (isConnected() && (descriptor.requiresInitialization())) {
            try {
                try {
                    descriptor.preInitialize(this);
                    descriptor.initialize(this);
                    descriptor.postInitialize(this);
                    getCommitManager().initializeCommitOrder();
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }

                if (getIntegrityChecker().hasErrors()) {
                    //CR#4011
                    handleException(new IntegrityException(getIntegrityChecker()));
                }
            } finally {
                clearIntegrityChecker();
            }
        }
    
public voidinitializeDescriptors()
INTERNAL: Allow each descriptor to initialize any dependancies on this session. This is done in two passes to allow the inheritence to be resolved first. Normally the descriptors are added before login, then initialized on login.

        // Assume all descriptors are CMP, if any are not their init will set this to false.
        getProject().setIsPureCMP2Project(true);
        // Must clone to avoid modification of the hashtable while enumerating.
        initializeDescriptors((Map)((HashMap)getDescriptors()).clone());
    
public voidinitializeDescriptors(java.util.Map descriptors)
INTERNAL: Allow each descriptor to initialize any dependancies on this session. This is done in two passes to allow the inheritence to be resolved first. Normally the descriptors are added before login, then initialized on login. The descriptors session must be used, not the broker.

        initializeSequencing();
        try {
            // First initialize basic properties (things that do not depend on anything else)
            Iterator iterator = descriptors.values().iterator();
            while (iterator.hasNext()) {
                ClassDescriptor descriptor = (ClassDescriptor)iterator.next();
                try {
                    AbstractSession session = getSessionForClass(descriptor.getJavaClass());
                    if (descriptor.requiresInitialization()) {
                        descriptor.preInitialize(session);
                    }

                    //check if inheritance is involved in aggregate relationship, and let the parent know the child descriptor
                    if (descriptor.isAggregateDescriptor() && descriptor.isChildDescriptor()) {
                        descriptor.initializeAggregateInheritancePolicy(session);
                    }
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }
            }

            // Second basic initialize mappings
            iterator = descriptors.values().iterator();
            while (iterator.hasNext()) {
                ClassDescriptor descriptor = (ClassDescriptor)iterator.next();
                try {
                    AbstractSession session = getSessionForClass(descriptor.getJavaClass());
                    if (descriptor.requiresInitialization()) {
                        descriptor.initialize(session);
                    }
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }
            }

            // Third initialize child dependencies
            iterator = descriptors.values().iterator();
            while (iterator.hasNext()) {
                ClassDescriptor descriptor = (ClassDescriptor)iterator.next();
                try {
                    AbstractSession session = getSessionForClass(descriptor.getJavaClass());
                    if (descriptor.requiresInitialization()) {
                        descriptor.postInitialize(session);
                    }
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }
            }

            try {
                getCommitManager().initializeCommitOrder();
            } catch (RuntimeException exception) {
                getIntegrityChecker().handleError(exception);
            }

            if (getIntegrityChecker().hasErrors()) {
                //CR#4011
                handleSevere(new IntegrityException(getIntegrityChecker()));
            }
        } finally {
            clearIntegrityChecker();
        }
    
public voidinitializeDescriptors(java.util.Vector descriptors)
INTERNAL: Allow each descriptor to initialize any dependancies on this session. This is done in two passes to allow the inheritence to be resolved first. Normally the descriptors are added before login, then initialized on login. The descriptors session must be used, not the broker.

        initializeSequencing();
        try {
            // First initialize basic properties (things that do not depend on anything else)
            for (Enumeration descriptorEnum = descriptors.elements();
                     descriptorEnum.hasMoreElements();) {
                try {
                    ClassDescriptor descriptor = (ClassDescriptor)descriptorEnum.nextElement();
                    AbstractSession session = getSessionForClass(descriptor.getJavaClass());
                    if (descriptor.requiresInitialization()) {
                        descriptor.preInitialize(session);
                    }

                    //check if inheritance is involved in aggregate relationship, and let the parent know the child descriptor
                    if (descriptor.isAggregateDescriptor() && descriptor.isChildDescriptor()) {
                        descriptor.initializeAggregateInheritancePolicy(session);
                    }
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }
            }

            // Second basic initialize mappings
            for (Enumeration descriptorEnum = descriptors.elements();
                     descriptorEnum.hasMoreElements();) {
                try {
                    ClassDescriptor descriptor = (ClassDescriptor)descriptorEnum.nextElement();
                    AbstractSession session = getSessionForClass(descriptor.getJavaClass());
                    if (descriptor.requiresInitialization()) {
                        descriptor.initialize(session);
                    }
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }
            }

            // Third initialize child dependencies
            for (Enumeration descriptorEnum = descriptors.elements();
                     descriptorEnum.hasMoreElements();) {
                try {
                    ClassDescriptor descriptor = (ClassDescriptor)descriptorEnum.nextElement();
                    AbstractSession session = getSessionForClass(descriptor.getJavaClass());
                    if (descriptor.requiresInitialization()) {
                        descriptor.postInitialize(session);
                    }
                } catch (RuntimeException exception) {
                    getIntegrityChecker().handleError(exception);
                }
            }

            try {
                getCommitManager().initializeCommitOrder();
            } catch (RuntimeException exception) {
                getIntegrityChecker().handleError(exception);
            }

            if (getIntegrityChecker().hasErrors()) {
                //CR#4011
                handleException(new IntegrityException(getIntegrityChecker()));
            }
        } finally {
            clearIntegrityChecker();
        }
    
public voidinitializeSequencing()
INTERNAL: Creates sequencing object

        getSequencingHome().onDisconnect();
        getSequencingHome().onConnect();
    
public booleanisDatabaseSession()
INTERNAL: Return if this session is a database session.

        return true;
    
public voidlogin()
PUBLIC: Connect to the database using the predefined login. The login must have been assigned when or after creating the session.

see
#login(Login)

        preConnectDatasource();
        connect();
        postConnectDatasource();
    
public voidlogin(java.lang.String userName, java.lang.String password)
PUBLIC: Connect to the database using the given user name and password. The additional login information must have been preset in the session's login attribute. This is the login that should be used if each user has their own id, but all users share the same database configuration.

        getDatasourceLogin().setUserName(userName);
        getDatasourceLogin().setPassword(password);
        login();
    
public voidlogin(oracle.toplink.essentials.sessions.Login login)
PUBLIC: Connect to the database using the given login. The login may also the preset and the login() protocol called. This is the login should only be used if each user has their own database configuration.

        setLogin(login);
        login();
    
public voidloginAndDetectDatasource()
PUBLIC: Connect to the database using the predefined login. Durring connection attempt to auto detect the required database platform. This method can be used in systems where for ease of use developers have TopLink autodetect the platform. To be safe, however, the platform should be configured directly. The login must have been assigned when or after creating the session.

        preConnectDatasource();
        Connection conn = null;
        try{
            conn = (Connection)getReadLogin().connectToDatasource(null);
            getLogin().setPlatformClassName(DBPlatformHelper.getDBPlatform(conn.getMetaData().getDatabaseProductName(), getSessionLog()));
        }catch (SQLException ex){
            DatabaseException dbEx =  DatabaseException.errorRetrieveDbMetadataThroughJDBCConnection();
            // Typically exception would occur if user did not provide correct connection
            // parameters. The root cause of exception should be propogated up
            dbEx.initCause(ex);
            throw dbEx;
        }finally{
            if (conn != null){
                try{
                    conn.close();
                }catch (SQLException ex){
                    DatabaseException dbEx =  DatabaseException.errorRetrieveDbMetadataThroughJDBCConnection();
                    // Typically exception would occur if user did not provide correct connection
                    // parameters. The root cause of exception should be propogated up
                    dbEx.initCause(ex);
                    throw dbEx;
                }
            }
        }
        connect();
        postConnectDatasource();
    
public voidlogout()
PUBLIC: Disconnect from the database.

exception
TopLinkException if a transaction is active, you must rollback any active transaction before logout.
exception
DatabaseException the database will also raise an error if their is an active transaction, or a general error occurs.

        // Reset cached data, as may be invalid later on.
        this.lastDescriptorAccessed = null;

        if (isInTransaction()) {
            throw DatabaseException.logoutWhileTransactionInProgress();
        }
        if (getAccessor() == null) {
            return;
        }

        disconnect();
        getIdentityMapAccessor().initializeIdentityMaps();
        isLoggedIn = false;
        log(SessionLog.INFO, null, "logout_successful", this.getName());
	   
        //unregister the MBean
        getServerPlatform().unregisterMBean();
    
protected voidpostConnectDatasource()
INTERNAL: This method includes all of the code that is issued after the datasource is connected to.

        initializeDescriptors();
        //added to process ejbQL query strings
        processEJBQLQueries();
        log(SessionLog.INFO, null, "login_successful", this.getName());
        getEventManager().postLogin(this);

        initializeConnectedTime();
        this.isLoggedIn = true;
        this.platform = null;
        
        //register the MBean
        getServerPlatform().registerMBean();
    
protected voidpreConnectDatasource()
INTERNAL: This method includes all of the code that is issued before the datasource is connected to.

        //Bug#3440544 Check if logged in already to stop the attempt to login more than once
        if (isLoggedIn) {
            throw ValidationException.alreadyLoggedIn(this.getName());
        }
        this.platform = null;
        if (isInProfile()) {
            getProfiler().initialize();
        }
        updateProfile(SessionProfiler.LoginTime, new Date(System.currentTimeMillis()));

        // Login and initialize
        getEventManager().preLogin(this);
        //setup the external transaction controller
        getServerPlatform().initializeExternalTransactionController();
        log(SessionLog.INFO, null, "topLink_version", DatasourceLogin.getVersion());
        if (getServerPlatform().getServerNameAndVersion() != null) {
            log(SessionLog.INFO, null, "application_server_name_and_version", getServerPlatform().getServerNameAndVersion());
        }
    
protected voidsetSequencingHome(oracle.toplink.essentials.internal.sequencing.SequencingHome sequencingHome)
INTERNAL: Set the SequencingHome object used by the session.

        this.sequencingHome = sequencingHome;
    
public voidsetServerPlatform(oracle.toplink.essentials.platform.server.ServerPlatform newServerPlatform)
PUBLIC: Set the server platform to handle server specific behaviour for WLS, Oc4j, etc This is not permitted after the session is logged in. If the user wants a different external transaction controller class or to provide some different behaviour than the provided ServerPlatform(s), we recommend subclassing oracle.toplink.essentials.platform.server.ServerPlatformBase (or a subclass), and overriding: ServerPlatformBase.getExternalTransactionControllerClass() ServerPlatformBase.registerMBean() ServerPlatformBase.unregisterMBean() for the desired behaviour.

see
oracle.toplink.essentials.platform.server.ServerPlatformBase

        if (this.isConnected()) {
            throw ValidationException.serverPlatformIsReadOnlyAfterLogin(newServerPlatform.getClass().getName());
        }
        this.serverPlatform = newServerPlatform;
    
public voidwriteAllObjects(java.util.Collection domainObjects)
PUBLIC: Write all of the objects and all of their privately owned parts in the database. The objects will be commited through a single transaction.

exception
DatabaseException if an error occurs on the database, these include constraint violations, security violations and general database erros.
exception
OptimisticLockException if the object's descriptor is using optimistic locking and the object has been updated or deleted by another user since it was last read.

        for (Iterator objectsEnum = domainObjects.iterator(); objectsEnum.hasNext();) {
            writeObject(objectsEnum.next());
        }
    
public voidwriteAllObjects(java.util.Vector domainObjects)
PUBLIC: Write all of the objects and all of their privately owned parts in the database. The objects will be commited through a single transaction.

exception
DatabaseException if an error occurs on the database, these include constraint violations, security violations and general database erros.
exception
OptimisticLockException if the object's descriptor is using optimistic locking and the object has been updated or deleted by another user since it was last read.

        for (Enumeration objectsEnum = domainObjects.elements(); objectsEnum.hasMoreElements();) {
            writeObject(objectsEnum.nextElement());
        }