001: package EJB;
002:
003: import java.sql.Connection;
004: import java.util.*;
005:
006: import simpleorm.core.*;
007:
008: import javax.naming.Context;
009: import javax.naming.InitialContext;
010: import javax.naming.NamingException;
011: import javax.sql.DataSource;
012: import javax.transaction.RollbackException;
013: import javax.transaction.Status;
014: import javax.transaction.Synchronization;
015: import javax.transaction.SystemException;
016: import javax.transaction.Transaction;
017: import javax.transaction.TransactionManager;
018: import javax.transaction.UserTransaction;
019:
020: import com.borderfree.generic.domain.RawDBData;
021:
022: /**
023: * Specializes SConnection for use with JTA Transaction management.
024: * (We do not want references to J2EE classes to appear directly in SimpleORM,
025: * which should be kept...Simple.)
026: * (There is absolutely no need to use JTA and aberglas recommends against JTA.) <p>
027: *
028: * The main problems is that EJBs do not guarantee that the same thread will be used
029: * accross EJB calls. SimpleORM normally associates connections with threads.
030: *
031: * The basic idea is to associate connections with the JTA transaction object
032: * intead of the current thread.
033: * DatabaseORM then implements a Synchronization object that tracks JTA commits and rollbacks.
034: *
035: * This work is not part of the core SimpleORM package and is provided very much "as is".
036: * However, the hooks it uses into SimpleORM are fully supported, and it provides
037: * a pretty straightforward outline as to how to integrate SimpleORM with EJBs.
038: *
039: * @author Dan Hristodorescu
040: */
041: public class SConnectionEJB extends SConnection {
042:
043: /** Associates SConnection state to the current transaction. */
044: private static HashMap connectionToTransactions = new HashMap();
045:
046: /** No direct creation of Connections. */
047: protected SConnectionEJB() {
048: }
049:
050: static class EJBConnectionGetter extends
051: SConnection.ConnectionGetter {
052: /*
053: * Return connection associated with current thread or transaction,
054: * error if both.
055: */
056: protected SConnection getAConnection() {
057: SConnection threadCon = super .getAConnection();
058: SConnection transCon = SConnectionEJB
059: .getTransactionConnection();
060: if (threadCon == null)
061: return transCon;
062: else if (transCon == null)
063: return threadCon;
064: else
065: throw new SException.Error(
066: "Currently have both a thread connection "
067: + threadCon
068: + " and a transaction connection "
069: + transCon);
070: }
071: }
072:
073: static {
074: SConnection.connectionGetter = new EJBConnectionGetter();
075: }
076:
077: static SConnection getTransactionConnection() {
078: /*
079: Transaction tx = getTransaction();
080: SConnection conn = null;
081:
082: synchronized(connectionToTransactions)
083: {
084: conn = (SConnection) connectionToTransactions.get(tx);
085: }
086: return conn;
087: */
088: return null;
089: }
090:
091: /** overrides SConnection ot create an SConnectionEJB instead. */
092: public static void attach(SConfiguration conf, String connectionName) {
093: attach(conf, name);
094: }
095:
096: /** The JTA manager will do the commit. */
097: public boolean mustCommitBeforeDetaching() { // Overrides
098: return false;
099: }
100:
101: protected void rawAttach() { // Overriden in SConnectionEJB
102: Transaction tx = getTransaction();
103:
104: synchronized (connectionToTransactions) {
105: connectionToTransactions.put(tx, this );
106: }
107: }
108:
109: protected void rawDetach() { // Overrides
110: Transaction tx = getTransaction();
111: synchronized (connectionToTransactions) {
112: connectionToTransactions.remove(tx);
113: }
114: }
115:
116: public static Transaction getTransaction()
117: {
118: InitialContext initCtx = null;
119: Transaction tx = null;
120:
121: try
122: {
123: initCtx = new InitialContext();
124: TransactionManager txm = (TransactionManager)
125: initCtx.lookup("java:/TransactionManager");
126: tx = txm.getTransaction();
127: }
128: catch(Exception ex)
129: {
130: throw new IllegalStateException("Cannot lookup transaction manager: "
131: + ex.getClass().getName() + " - " + ex.getMessage());
132: }
133: finally
134: {
135: try
136: {
137: if (initCtx != null)
138: {
139: initCtx.close();
140: }
141: }
142: catch (NamingException ne)
143: {
144: }
145: }
146:
147: if(tx == null)
148: {
149: throw new IllegalStateException("No transaction manager, not
150: in EJB container or NOT_SUPPORTED transaction descriptor: Please use
151: JDBC");
152: }
153:
154: return tx;
155: }
156: }
|