001: /*
002: * JFox - The most lightweight Java EE Application Server!
003: * more details please visit http://www.huihoo.org/jfox or http://www.jfox.org.cn.
004: *
005: * JFox is licenced and re-distributable under GNU LGPL.
006: */
007: package org.jfox.ejb3.transaction;
008:
009: import java.sql.Connection;
010: import java.util.ArrayList;
011: import java.util.List;
012: import java.util.Iterator;
013: import javax.transaction.Transaction;
014: import javax.transaction.Status;
015: import javax.transaction.SystemException;
016:
017: import org.apache.log4j.Logger;
018:
019: /**
020: * 通过 ThreadLocal 关� Transaction,以� Transaction 使用的 Connection,
021: * 以便在 Transaction 结�的时候,释放connection,使得 connection �以被 pool 回收
022: *
023: * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
024: */
025: public class TxConnectionsThreadLocal {
026:
027: private static Logger logger = Logger
028: .getLogger(TxConnectionsThreadLocal.class);
029:
030: /**
031: * ThreadLocal ä¿?å˜ Thread => TransactionConnectionPair
032: */
033: private static ThreadLocal<TxConnectionWrapper> Thread2TxConn = new ThreadLocal<TxConnectionWrapper>();
034:
035: public static void setTransaction(Transaction transaction) {
036: logger.debug("Attach transaction to thread, transaction is: "
037: + transaction);
038:
039: TxConnectionWrapper txConnectionWrapper = Thread2TxConn.get();
040: if (txConnectionWrapper == null) { // 该线程还未�起新的事务
041: txConnectionWrapper = new TxConnectionWrapper(transaction);
042: Thread2TxConn.set(txConnectionWrapper);
043: } else { // 该线程已�有事务,但��起一个新的事务,新�起的事务接下�将是活动事务
044: txConnectionWrapper.addTransaction(transaction);
045: }
046: }
047:
048: public static void addConnection2Tx(Connection connection) {
049: logger
050: .debug("Attatch connection to transaction, connection is: "
051: + connection);
052: TxConnectionWrapper txConnectionWrapper = Thread2TxConn.get();
053:
054: if (txConnectionWrapper == null) {
055: logger
056: .warn("Attatch connection to transaction failed, no transaction!");
057: } else {
058: txConnectionWrapper.addConnection(connection);
059: }
060: }
061:
062: public static void releaseTxConnections() {
063: logger.debug("Release Transaction attatched connections.");
064: TxConnectionWrapper txConnectionWrapper = Thread2TxConn.get();
065: if (txConnectionWrapper == null) {
066: logger
067: .warn("Release attatched connections failed, current transaction is null.");
068: } else {
069: txConnectionWrapper.releaseCurrentTxConnections();
070: // 如果没有剩余的事务环境,清除 ThreadLocal ��
071: if (txConnectionWrapper.isEmpty()) {
072: logger
073: .debug("Remove thread local transaction binding.");
074: Thread2TxConn.remove();
075: }
076: }
077: }
078:
079: /**
080: * ä¿?å˜å’Œ Thread å…³è?”çš„ Transaction 以å?Š Connection
081: */
082: static class TxConnectionWrapper {
083: // 线程关�的事务链,最�一个事务��活动事务
084: List<Transaction> transactionChain = new ArrayList<Transaction>();
085:
086: // 线程关�的 TransactionConnectionPair
087: List<TransactionConnectionPair> txconns = new ArrayList<TransactionConnectionPair>();
088:
089: public TxConnectionWrapper(Transaction transaction) {
090: transactionChain.add(transaction);
091: }
092:
093: public void addTransaction(Transaction transaction) {
094: transactionChain.add(transaction);
095: }
096:
097: public void addConnection(Connection connection) {
098: // 当�事务�为活动事务
099: txconns.add(new TransactionConnectionPair(transactionChain
100: .get(transactionChain.size() - 1), connection));
101: }
102:
103: /**
104: * 释放当�活动事务关�所有 connection
105: */
106: public void releaseCurrentTxConnections() {
107: // æ ¹æ?®First Created, last commit 原则,活动事务为最å?Žä¸€ä¸ªäº‹åŠ¡
108: Transaction activeTransaction = transactionChain
109: .remove(transactionChain.size() - 1);
110:
111: try {
112: if (activeTransaction.getStatus() != Status.STATUS_COMMITTED
113: && activeTransaction.getStatus() != Status.STATUS_ROLLEDBACK) {
114: logger
115: .warn("Release connections attached non ended transaction!");
116: }
117: } catch (SystemException e) {
118: logger.error("Get transaction status exception.", e);
119: }
120:
121: Iterator<TransactionConnectionPair> it = txconns.iterator();
122: while (it.hasNext()) {
123: TransactionConnectionPair tcp = it.next();
124: if (tcp.transaction == activeTransaction) {
125: try {
126: it.remove();
127: tcp.connection.close();
128: } catch (Throwable e) {
129: logger
130: .warn(
131: "Connection close in release current transaction atteched connection with exception.",
132: e);
133: }
134: }
135: }
136: }
137:
138: public boolean isEmpty() {
139: return transactionChain.isEmpty();
140: }
141:
142: protected void finalize() throws Throwable {
143: super .finalize();
144: if (!txconns.isEmpty()) {
145: for (TransactionConnectionPair tcp : txconns) {
146: try {
147: tcp.connection.close();
148: } catch (Throwable e) {
149: logger
150: .warn(
151: " Connection close in finalize with exception.",
152: e);
153: }
154: }
155: }
156: }
157: }
158:
159: static class TransactionConnectionPair {
160: Transaction transaction;
161: Connection connection;
162:
163: public TransactionConnectionPair(Transaction transaction,
164: Connection connection) {
165: this .transaction = transaction;
166: this .connection = connection;
167: }
168: }
169:
170: public static void main(String[] args) {
171:
172: }
173: }
|