js.transaction.TransactionManager Maven / Gradle / Ivy
package js.transaction;
import js.lang.Config;
import js.lang.ConfigException;
/**
* Transaction manager is a factory for transaction instances. Transaction manager is more a service provider interface
* used by containers to provide declarative transactions. Usually user space code has no need to interact with
* transaction manager directly. Anyway, implementation is encouraged to expose transaction manager as a Java service.
* Also implementation should be thread safe and reusable.
*
* Transaction manager is configurable via {@link #config(js.lang.Config)} method. Configuration object is
* implementation specific. When create transaction manager need to configure it. Since transaction manager instance
* creation is costly it is recommended to cache an reuse it; recommended way is to create application singleton.
*
*
* // implementation specific configuration
* Config config = new Config();
* config.setProperty(...);
* ...
* // get manager instance and configure it
* // manager instance should be cached and reused since is costly to create
* TransactionManager manager = ServiceLoader.load(TransactionManager.class).iterator().next();
* manager.config(config);
*
*
* When application exits transaction manager instance should be destroyed, see {@link #destroy()} in order to release
* external transactional resources.
*
* Manual Transaction
*
* As stated, user code should use declarative transactions provided by containers. Anyway, transaction manager provides
* means for programmatic transactions, see {@link #exec(WorkingUnit, Object...)}.
*
* Here is a sample transactional working unit executed programmatically.
*
*
* Address address = manager.exec(new WorkingUnit<Session, Address>()
* {
* public Address exec(Session session, Object... args) throws Exception
* {
* Person person = (Person)args[0];
* SQLQuery sql = session.createSQLQuery("SELECT * FROM address ...");
* ...
* return (Address)sql.uniqueResult();
* }
* }, person);
*
*
*
* Finally, for really special cases one can handle transactions manually but must follow next usage pattern. Note close
* from final block.
*
*
* Transaction t = manager.createTransaction();
* try {
* // execute transactional working unit
* t.commit();
* }
* catch(Exception e) {
* t.rollback();
* }
* finally {
* t.close();
* }
*
*
* @author Iulian Rotaru
* @version final
*/
public interface TransactionManager
{
/**
* Configure this transaction manager using a given configuration object. Configuration object is clearly dependent on
* specific implementation; it is implementation responsibility to ensure configuration object is valid, accordingly
* its internal rules. If validation fails implementation should throw {@link ConfigException}.
*
* Configuration object can be null, in which case implementation should use some default properties or collect
* configuration from specific means.
*
* @param config configuration object, possible null.
* @throws ConfigException if given configuration object is not valid.
*/
void config(Config config) throws ConfigException;
/**
* Create a new transaction instance. Creating a transaction instance begins the transactional scope and is mandatory
* to be concluded by close, as in sample code. Creating transactions and failing to close them will exhaust
* transactional resource.
*
* Also, although not mandatory, need to invoke commit or rollback at appropriate time.
*
*
* Transaction t = manager.createTransaction(); // begin transactional scope
* try {
* // execute component working unit
* t.commit();
* }
* catch(Exception e) {
* t.rollback();
* }
* finally {
* t.close(); // mandatory to close transactional scope
* }
*
*
* When create a transaction is possible to request a specific transactional schema. This limits the scope of
* transactional resource objects that can be accessed from transaction. If not provided created transaction used
* implicit / global schema. Depending on implementation, transactional schema can have alternative names, e.g. JPA
* name it persistence unit.
*
* @param schema optional transactional schema, null if not used.
* @return newly created transaction instance.
* @throws TransactionException if transaction creation fails.
*/
Transaction createTransaction(String schema);
/**
* Create a read-only transaction instance. This is a variant of {@link #createTransaction(String)} optimized for read-only
* transactions.
*
* @param schema optional transactional schema, null if not used.
* @return newly create transaction instance.
* @throws TransactionException if transaction creation fails.
*/
Transaction createReadOnlyTransaction(String schema);
/**
* Helper method used to execute a transactional block of code programmatically. In sample code below, working unit is
* executed inside transaction boundaries; user code should be aware of that and do not execute excessive long
* processing.
*
*
* Address address = (Address)TransactionManager.exec(new WorkingUnit()
* {
* public Object exec(Object... args) throws Exception
* {
* Person person = (Person)args[0];
* ...
* return new Address();
* }
* }, person);
*
*
* See {@link WorkingUnit} interface.
*
* When create a transaction is possible to request a specific transactional schema. This limits the scope of
* transactional resource objects that can be accessed from transaction. If not provided created transaction used
* implicit / global schema. Depending on implementation, transactional schema can have alternative names, e.g. JPA
* name it persistence unit.
*
* @param schema optional transactional schema, null if not used.
* @param workingUnit workingUnit to be executed transactional,
* @param args variable arguments list to be passed to {@link WorkingUnit#exec(Object, Object...)}.
* @param session object type.
* @param working unit returned type.
* @return the object returned by executed working unit.
* @throws TransactionException if working unit execution fails in some way. Note that the root cause is set to the
* actual working unit exception.
*/
T exec(String schema, WorkingUnit workingUnit, Object... args) throws TransactionException;
/**
* Convenient alternative of {@link #exec(String, WorkingUnit, Object...)} when use default / global transactional
* schema.
*
* @param workingUnit workingUnit to be executed transactional,
* @param args variable arguments list to be passed to {@link WorkingUnit#exec(Object, Object...)}.
* @param session object type.
* @param working unit returned type.
* @return the object returned by executed working unit.
* @throws TransactionException if working unit execution fails in some way. Note that the root cause is set to the
* actual working unit exception.
*/
T exec(WorkingUnit workingUnit, Object... args) throws TransactionException;
/** Release transactional resources. */
void destroy();
}