package org.castor.persist;
import java.sql.Connection;
import java.util.Iterator;
import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.DbMetaInfo;
import org.exolab.castor.jdo.PersistenceException;
import org.exolab.castor.jdo.QueryException;
import org.exolab.castor.jdo.TransactionAbortedException;
import org.exolab.castor.mapping.AccessMode;
import org.exolab.castor.mapping.xml.NamedNativeQuery;
import org.exolab.castor.persist.ClassMolder;
import org.exolab.castor.persist.LockEngine;
import org.exolab.castor.persist.OID;
import org.exolab.castor.persist.ObjectLock;
import org.exolab.castor.persist.QueryResults;
import org.exolab.castor.persist.TxSynchronizable;
import org.exolab.castor.persist.spi.CallbackInterceptor;
import org.exolab.castor.persist.spi.Identity;
import org.exolab.castor.persist.spi.InstanceFactory;
import org.exolab.castor.persist.spi.PersistenceQuery;
/**
* A transaction context is required in order to perform operations against the
* database. The transaction context is mapped to an API transaction or an XA
* transaction. The only way to begin a new transaction is through the creation
* of a new transaction context. A transaction context is created from an
* implementation class directly or through
* {@link org.exolab.castor.persist.XAResourceImpl}.
*
* @author <a href="arkin@intalio.com">Assaf Arkin </a>
* @author <a href="mailto:ralf DOT joachim AT syscon DOT eu">Ralf Joachim</a>
* @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
* @author <a href="mailto:gblock AT ctoforaday DOT COM">Gregory Block</a>
* @version $Revision$ $Date: 2006-04-22 11:05:30 -0600 (Sat, 22 Apr 2006) $
* @since 1.0
*/
public interface TransactionContext {
/**
* Register a listener which wants to synchronize its state to the state of the
* transaction.
*
* @param synchronizable The TxSynchronizable implementation to register.
*/
void addTxSynchronizable(final TxSynchronizable synchronizable);
/**
* Unregister a listener which wants to synchronize its state to the state of the
* transaction.
*
* @param synchronizable The TxSynchronizable implementation to unregister.
*/
void removeTxSynchronizable(final TxSynchronizable synchronizable);
/**
* Enable or disable autoStore. If enabled, all new objects, which are reachable
* from other object that are queried, loaded, created in the transaction, will be
* created when the transaction is committed.
*
* @param autoStore When set to <code>true</code> autoStore will be enabled.
*
* @deprecated Please use the 'cascading' attribute of the field mapping instead.
*/
void setAutoStore(final boolean autoStore);
/**
* Test if autoStore option is enabled or not.
*
* @return <code>true</code> if autoStore option is enabled.
*
* @deprecated Please use the 'cascading' attribute of the field mapping instead.
*/
boolean isAutoStore();
/**
* Overrides the default callback interceptor by a custom interceptor for this
* database source.
* <p>
* The interceptor is a callback that notifies data objects on persistent state
* events.
* <p>
* If callback interceptor is not overriden, events will be sent to data object
* that implements the org.exolab.castor.jdo.Persistent interface.
*
* @param callback The callback interceptor, disabled if null.
*/
void setCallback(final CallbackInterceptor callback);
/**
* Overrides the default instance factory by a custom one for this database
* source.
* <p>
* The factory is used to obatain a new instance of data object when it is
* needed during loading.
*
* @param factory The instanceFactory to be used, disable if null.
*/
void setInstanceFactory(final InstanceFactory factory);
/**
* Sets the timeout of this transaction. The timeout is specified in seconds.
*
* @param timeout The timeout for this transaction in seconds.
*/
void setTransactionTimeout(final int timeout);
/**
* Returns the timeout of this transaction. The timeout is specified in seconds.
*
* @return The timeout of this transaction in seconds.
*/
int getTransactionTimeout();
/**
* Sets the timeout waiting to acquire a lock. The timeout is specified in
* seconds.
*
* @param timeout The timeout waiting to acquire a lock in seconds.
*/
void setLockTimeout(final int timeout);
/**
* Returns the timeout waiting to acquire a lock. The timeout is specified in
* seconds.
*
* @return The timeout waiting to acquire a lock in seconds.
*/
int getLockTimeout();
/**
* Sets the status of the current transaction to the given one.
*
* @param status The status to set for this transaction.
*/
void setStatus(final int status);
/**
* Returns the status of this transaction.
*
* @return The status of this transaction.
*/
int getStatus();
/**
* Indicates which lock this transaction is waiting for. When a transaction
* attempts to acquire a lock it must indicate which lock it attempts to
* acquire in order to perform dead-lock detection. This method is called by
* {@link ObjectLock} before entering the temporary lock-acquire state.
*
* @param lock The lock which this transaction attempts to acquire
*/
void setWaitOnLock(final ObjectLock lock);
/**
* Returns the lock which this transaction attempts to acquire.
*
* @return The lock which this transaction attempts to acquire
*/
ObjectLock getWaitOnLock();
/**
* Return an open connection for the specified engine. Only one connection should
* be created for a given engine in the same transaction.
*
* @param engine The persistence engine.
* @return An open connection.
* @throws PersistenceException An error occured talking to the persistence engine.
*/
Connection getConnection(final LockEngine engine) throws PersistenceException;
/**
* Returns meta-data related to the RDBMS used.
*
* @param engine LockEngine instance used.
* @return A DbMetaInfo instance describing various features of the underlying
* RDBMS.
* @throws PersistenceException An error occured talking to the persistence engine.
*/
DbMetaInfo getConnectionInfo(final LockEngine engine) throws PersistenceException;
Object fetch(final ClassMolder molder,
final Identity identity, final AccessMode suggestedAccessMode)
throws PersistenceException;
/**
* Load an object for use within the transaction. Multiple access to the same
* object within the transaction will return the same object instance (except
* for read-only access).
* <p>
* This method is similar to {@link #fetch} except that it will load the object
* only once within a transaction and always return the same instance.
* <p>
* If the object is loaded for read-only then no lock is acquired and updates
* to the object are not reflected at commit time. If the object is loaded for
* read-write then a read lock is acquired (unless timeout or deadlock detected)
* and the object is stored at commit time. The object is then considered
* persistent and may be deleted or upgraded to write lock. If the object is
* loaded for exclusive access then a write lock is acquired and the object is
* synchronized with the persistent copy.
* <p>
* Attempting to load the object twice in the same transaction, once with
* exclusive lock and once with read-write lock will result in an exception.
*
* @param identity The object's identity.
* @param proposedObject The object to fetch (single instance per transaction).
* @param suggestedAccessMode The access mode (see {@link AccessMode}) the values
* in persistent storage.
* @return object being loaded.
* @throws PersistenceException Timeout or deadlock occured attempting to acquire
* lock on object. The object was not found in persistent storage. An error
* reported by the persistence engine.
*/
Object load(final Identity identity,
final ProposedEntity proposedObject, final AccessMode suggestedAccessMode)
throws PersistenceException;
/**
* Load an object for use within the transaction. Multiple access to the same
* object within the transaction will return the same object instance (except
* for read-only access).
* <p>
* In addition to {@link #load(Identity,ProposedEntity,AccessMode)}
* a QueryResults can be specified.
*
* @param identity The object's identity.
* @param proposedObject The object to fetch (single instance per transaction).
* @param suggestedAccessMode The access mode (see {@link AccessMode}) the values
* in persistent storage.
* @param results The QueryResult that the data to be loaded from.
* @return object being loaded.
* @throws PersistenceException Timeout or deadlock occured attempting to acquire
* lock on object. The object was not found in persistent storage. An error
* reported by the persistence engine.
*/
Object load(final Identity identity,
final ProposedEntity proposedObject, final AccessMode suggestedAccessMode,
final QueryResults results)
throws PersistenceException;
/**
* Perform a query using the query mechanism with the specified access mode. The
* query is performed in this transaction, and the returned query results can
* only be used while this transaction is open. It is assumed that the query
* mechanism is compatible with the persistence engine.
*
* @param engine The persistence engine.
* @param query A query against the persistence engine.
* @param accessMode The access mode.
* @param scrollable The db cursor mode.
* @return A query result iterator
* @throws PersistenceException An error reported by the persistence engine or
* an invalid query.
*/
QueryResults query(final LockEngine engine, final PersistenceQuery query,
final AccessMode accessMode, final boolean scrollable)
throws PersistenceException;
/**
* Walk a data object tree starting from the specified object, and mark all
* objects to be created.
*
* @param molder The class persistence molder.
* @param object The object to persist.
* @param rootObjectOID The OID of the root object to start walking.
* @throws PersistenceException An object with this identity already exists in
* persistent storage. The class is not persistent capable. An error
* reported by the persistence engine.
*/
void markCreate(final ClassMolder molder,
final Object object, final OID rootObjectOID)
throws PersistenceException;
/**
* Creates a new object in persistent storage. The object will be persisted
* only if the transaction commits. If an identity is provided then duplicate
* identity check happens in this method, if no identity is provided then
* duplicate identity check occurs when the transaction completes and the
* object is not visible in this transaction.
*
* @param molder The molder of the creating class.
* @param object The object to persist.
* @param depended The master object's OID if exist.
* @throws PersistenceException An object with this identity already exists in
* persistent storage. The class is not persistent capable. An error
* reported by the persistence engine.
*/
void create(final ClassMolder molder, final Object object, final OID depended)
throws PersistenceException;
/**
* Update a new object in persistent storage and returns the object's OID. The
* object will be persisted only if the transaction commits. If an identity is
* provided then duplicate identity check happens in this method, if no identity
* is provided then duplicate identity check occurs when the transaction
* completes and the object is not visible in this transaction.
* <p>
* Update will also mark objects to be created if the TIMESTAMP equals to
* NO_TIMESTAMP.
*
* @param molder The object's molder.
* @param object The object to persist.
* @param depended The master objects of the specified object to be created if
* exisit.
* @return true if the object is marked to be created.
* @throws PersistenceException An object with this identity already exists in
* persistent storage. The class is not persistent capable. Dirty checking
* mechanism may immediately report that the object was modified in the
* database during the long transaction. An error reported by the
* persistence engine.
*/
boolean markUpdate(final ClassMolder molder,
final Object object, final OID depended)
throws PersistenceException;
/**
* Update a new object in persistent storage and returns the object's OID. The
* object will be persisted only if the transaction commits. If an identity is
* provided then duplicate identity check happens in this method, if no identity
* is provided then duplicate identity check occurs when the transaction
* completes and the object is not visible in this transaction.
* <p>
* Update will also mark objects to be created if the TIMESTAMP equals to
* NO_TIMESTAMP.
*
* @param molder The object's molder.
* @param object The object to persist.
* @param depended The master objects of the specified object to be created if
* exisit.
* @throws PersistenceException An object with this identity already exists in
* persistent storage. The class is not persistent capable. Dirty checking
* mechanism may immediately report that the object was modified in the
* database during the long transaction. An error reported by the persistence
* engine.
*/
void update(final ClassMolder molder, final Object object,
final OID depended)
throws PersistenceException;
/**
* Deletes the object from persistent storage. The deletion will take effect
* only if the transaction is committed, but the object is no longer viewable
* for the current transaction and locks for access from other transactions
* will block until this transaction completes. A write lock is acquired in
* order to assure the object can be deleted.
*
* @param object The object to delete from persistent storage.
* @throws PersistenceException The object has not been queried or created in this
* transaction. Timeout or deadlock occured attempting to acquire lock on
* object. An error reported by the persistence engine.
*/
void delete(Object object) throws PersistenceException;
/**
* Acquire a write lock on the object. Read locks are implicitly available
* when the object is queried. A write lock is only granted for objects that
* are created or deleted or for objects loaded in exclusive mode - this
* method can obtain such a lock explicitly. If the object already has a
* write lock in this transaction or a read lock in this transaction but no
* read lock in any other transaction, a write lock is obtained. If this
* object has a read lock in any other transaction this method will block
* until the other transaction will release its lock. If the specified
* timeout has elapsed or a deadlock has been detected, an exception will be
* thrown but the current lock will be retained.
*
* @param object The object to lock.
* @param timeout Timeout waiting to acquire lock, specified in seconds, zero
* for no waiting, negative to use the default timeout for this transaction.
* @throws PersistenceException The object has not been queried or created in this
* transaction. Timeout or deadlock occured attempting to acquire lock on
* object. An error reported by the persistence engine.
*/
void writeLock(final Object object, final int timeout)
throws PersistenceException;
void markModified(final Object object,
final boolean updatePersist,
final boolean updateCache);
/**
* Prepares the transaction prior to committing it. Indicates whether the
* transaction is read-only (i.e. no modified objects), can commit, or an error
* has occured and the transaction must be rolled back. This method performs
* actual storage into the persistence storage. Multiple calls to this method
* can be done, and do not release locks, allowing <tt>checkpoint</tt> to occur.
* An IllegalStateException is thrown if transaction is not in the proper state
* to perform this operation.
*
* @return True if the transaction can commit, false if the transaction is
* read only
* @throws TransactionAbortedException The transaction has been aborted due to
* inconsistency, duplicate object identity, error with the persistence
* engine or any other reason.
*/
boolean prepare() throws TransactionAbortedException;
/**
* Commits all changes and closes the transaction releasing all locks on all
* objects. All objects are now transient. Must be called after a call to
* {@link #prepare} has returned successfully. Throws an IllegalStateException
* when called without calling {@link #prepare} first.
*
* @throws TransactionAbortedException The transaction has been aborted due to
* inconsistency, duplicate object identity, error with the persistence
* engine or any other reason.
*/
void commit() throws TransactionAbortedException;
/**
* Rolls back all changes and closes the transaction releasing all locks on
* all objects. All objects are now transient, if they were queried in this
* transaction. This method may be called at any point during the transaction.
* Throws an IllegalStateException if transaction is not in the proper state
* to perform this operation.
*/
void rollback();
/**
* Closes all Connections. Must be called before the end of the transaction
* in EJB environment or after commit in standalone case. Throws an
* IllegalStateException if this method has been called after the end of the
* transaction.
*
* @throws TransactionAbortedException The transaction has been aborted due to
* inconsistency, duplicate object identity, error with the persistence
* engine or any other reason.
*/
void close() throws TransactionAbortedException;
/**
* Expose an enumeration of the commited object entries to allow TxSynchronizable
* to iterate through the objects.
*
* @return Iterator of modifiable (read-write) object entries.
*/
Iterator iterateReadWriteObjectsInTransaction();
/**
* Returns true if the object is marked as created in this transaction. Note
* that this does not find objects in the 'transitional' state of creating.
* Primarily intended to be used by tests.
*
* @param object The object to test the state of in this transaction.
* @return <code>true</code> if the object is marked as created within this
* transaction.
*/
boolean isCreated(final Object object);
/**
* Retrieves the state of the object in this transaction. Specifically, in
* this case, that the object requires a cache update.
*
* @param object The object to test the state of in this transaction.
* @return <code>true</code> if the object is recorded in this transaction with
* the requested state.
*/
boolean isUpdateCacheNeeded(final Object object);
/**
* Retrieves the state of the object in this transaction. Specifically, in
* this case, that the object requires a persistence update.
*
* @param object The object to test the state of in this transaction.
* @return <code>true</code> if the object is recorded in this transaction with
* the requested state.
*/
boolean isUpdatePersistNeeded(final Object object);
/**
* Returns true if the object is persistent in this transaction.
*
* @param object The object.
* @return <code>true</code> if persistent in transaction.
*/
boolean isPersistent(final Object object);
/**
* Returns true if the object has been previously queried/loaded/updated/created in
* this transaction.
*
* @param object The object to investigate.
* @return <code>true</code> if recorded in this transaction.
*/
boolean isRecorded(final Object object);
boolean isDepended(final OID master, final Object dependent);
/**
* Returns true if the transaction is open.
*
* @return <code>true</code> if the transaction is open.
*/
boolean isOpen();
/**
* Returns true if and only if the specified object is loaded or created in this
* transaction and is deleted.
*
* @param object The object to test the state of in this transaction.
* @return <code>true</code> if the object is deleted.
*/
boolean isDeleted(final Object object);
boolean isDeletedByOID(final OID oid);
/**
* Check to see whether this transaction considers an object to have been marked
* read-only.
*
* @param object The object to test for read-only status
* @return <code>true</code> if the object is marked read-only in this transaction;
* otherwise, <code>false</code>.
*/
boolean isReadOnly(final Object object);
boolean isCached(final ClassMolder molder, final Class cls, final Identity identity)
throws PersistenceException;
/**
* Expire object from the cache. Objects expired from the cache will be
* read from persistent storage, as opposed to being read from the
* cache, during subsequent load/query operations.
*
* @param molder The class persistence molder.
* @param identity The object's identity.
* @throws PersistenceException If identity is null or any problem that happens
* during expiration of cache values.
*/
void expireCache(final ClassMolder molder, final Identity identity)
throws PersistenceException;
/**
* Get the current application ClassLoader.
*
* @return the current ClassLoader's instance. <code>null</code> if none
* has been provided
*/
ClassLoader getClassLoader();
Database getDatabase();
/**
* Returns true if the object given is locked.
*
* @param cls Class instance of the object to be investigated.
* @param identity Identity of the object to be investigated.
* @param lockEngine Current LcokEngine instance
* @return True if the object in question is locked.
*/
boolean isLocked(Class cls, Identity identity, LockEngine lockEngine);
/**
* Creates an OQL query based upon a named query as defined in the
* mapping file.
*
* @param molder Specific class molder.
* @param name Name of the (named) query to create.
* @return An OQL query
* @throws QueryException If the named query can not be found
*/
String getNamedQuery(ClassMolder molder, String name) throws QueryException;
/**
* Returns a NamedNativeQuery instance query based upon a named query as defined in the
* mapping file.
*
* @param molder Specific class molder.
* @param name Name of the (named) query to create.
* @return A NamedNativeQuery instance.
* @throws QueryException If the named query can not be found.
*/
NamedNativeQuery getNamedNativeQuery(ClassMolder molder, String name) throws QueryException;
}