KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfox > jdbc > xa > PoolableXAConnection


1 /* JFox, the OpenSource J2EE Application Server
2  *
3  * Distributable under GNU LGPL license by gun.org
4  * more details please visit http://www.huihoo.org/jfox
5  */

6
7 package org.jfox.jdbc.xa;
8
9 import java.sql.Connection JavaDoc;
10 import java.sql.SQLException JavaDoc;
11 import javax.sql.ConnectionEvent JavaDoc;
12 import javax.sql.ConnectionEventListener JavaDoc;
13 import javax.sql.XAConnection JavaDoc;
14 import javax.transaction.Status JavaDoc;
15 import javax.transaction.Synchronization JavaDoc;
16 import javax.transaction.Transaction JavaDoc;
17 import javax.transaction.TransactionManager JavaDoc;
18 import javax.transaction.xa.XAResource JavaDoc;
19
20 import org.jfox.ioc.logger.Logger;
21 import org.jfox.jdbc.ClientConnection;
22 import org.jfox.pool.PoolableObject;
23
24 /**
25  * @author <a HREF="mailto:young_yy@hotmail.com">Young Yang</a>
26  */

27
28 public class PoolableXAConnection implements PoolableObject, XAConnection JavaDoc {
29     private XAConnection JavaDoc xaconn = null;
30     private XAResource JavaDoc xares = null;
31
32     // the underlying connection
33
private Connection JavaDoc underlying = null;
34
35     private ConnectionEventListener JavaDoc txConnListener = null;
36
37     Logger logger = Logger.getLogger(PoolableXAConnection.class.getName());
38
39     //如果 getConnection(user,pass) 与池中的 user pass 不同,则不缓存到池
40
private boolean poolable = true;
41     //如果在操作的时候发生了系统级错误,则该 XAConnection 将被销毁,不再缓存到池
42
private boolean errored = false;
43
44     private static TransactionManager JavaDoc tm = TxDataSource.getTransactionManager();
45     private Synchronization JavaDoc txSync = new XASynchronization();
46
47     private XAConnectionPool pool = null;
48
49     // 标志该对象已返回到池中,即使客户保留有引用,也不能再进行操作
50
private boolean passivated = true;
51
52     private String JavaDoc dbUrl = null;
53     private String JavaDoc user = null;
54     private String JavaDoc password = null;
55
56     private long startSleepTime = System.currentTimeMillis();
57
58
59     public PoolableXAConnection(XAConnection JavaDoc xaconn, int transactionIsolation, String JavaDoc dbUrl, String JavaDoc user, String JavaDoc password) {
60         this.xaconn = xaconn;
61         this.dbUrl = dbUrl;
62         this.user = user;
63         this.password = password;
64         try {
65             xares = xaconn.getXAResource();
66             underlying = xaconn.getConnection();
67             underlying.setAutoCommit(false);
68             logger.debug("set underlying connection transaction isolation: " + transactionIsolation);
69             underlying.setTransactionIsolation(transactionIsolation);
70         }
71         catch(SQLException JavaDoc e) {
72             throw new RuntimeException JavaDoc("can not init PoolableXAConnection, because getConnection failed.", e);
73         }
74         txConnListener = new TxConnectionListener();
75         xaconn.addConnectionEventListener(txConnListener);
76         txSync = new XASynchronization();
77     }
78
79     /**
80      * 在返回给用户使用之前,enlist XAResource
81      *
82      * @throws Exception
83      */

84     public void activate() throws Exception JavaDoc {
85         logger.debug("activate callback, tx status = " + tm.getStatus());
86         passivated = false;
87         if(tm.getStatus() != Status.STATUS_NO_TRANSACTION) {
88             Transaction JavaDoc tran = tm.getTransaction();
89             tran.enlistResource(xares);
90             tran.registerSynchronization(txSync);
91             XAConnectionManager.associate(tran, this, dbUrl, user, password);
92         }
93
94         startSleepTime = System.currentTimeMillis();
95     }
96
97     /**
98      * rollback 会调用 XASynchronization.afterCompletion(),解除事务和 XAConnection 的关联
99      * <p/>
100      * 如果还处在事务中,说明用户忘记了提交事务,那么将调用 rollback() ()
101      *
102      * @throws Exception
103      * @see XASynchronization#afterCompletion(int)
104      */

105     public void passivate() throws Exception JavaDoc {
106         logger.debug("passivate callback");
107         passivated = true;
108         int txStatus = tm.getStatus();
109         if(txStatus != Status.STATUS_NO_TRANSACTION) {
110             XAConnectionManager.disassociate(tm.getTransaction(), dbUrl, user, password);
111         }
112
113         startSleepTime = System.currentTimeMillis();
114     }
115
116     public boolean isAvailable() {
117         return poolable && !errored && !passivated;
118     }
119
120     public XAResource JavaDoc getXAResource() throws SQLException JavaDoc {
121         if(passivated) {
122             throw new SQLException JavaDoc("XAConnection have returned to pool, re-retrieve it for use");
123         }
124         return xares;
125     }
126
127     public void close() throws SQLException JavaDoc {
128         poolable = false;
129         underlying.close();
130         xaconn.close();
131     }
132
133     public Connection JavaDoc getConnection() throws SQLException JavaDoc {
134         if(passivated) {
135             throw new SQLException JavaDoc("XAConnection have returned to pool, re-retrieve it for use");
136         }
137         return new ClientConnection(underlying);
138     }
139
140     public void addConnectionEventListener(ConnectionEventListener JavaDoc listener) {
141         if(!passivated) {
142             xaconn.addConnectionEventListener(listener);
143         }
144     }
145
146     public void removeConnectionEventListener(ConnectionEventListener JavaDoc listener) {
147         if(!passivated) {
148             xaconn.removeConnectionEventListener(listener);
149         }
150     }
151
152     //标记该 PoolabeXAConnection 已经出错了,不再返回到池中
153
// TODO: 出错了,是否应该调用 xaconn.close ,调用的时候会出错的
154
private void markedError() {
155         logger.warn("xaconn error occurred, to be marked error");
156         errored = true;
157     }
158
159     /**
160      * 如果使用的是特别的 user 和 password 建立的 XAConnection,
161      * 将调用 notPoolable,以便不返回池
162      *
163      * @see XAConnectionFactory#makeObject(String, String)
164      */

165     void notPoolable() {
166         poolable = false;
167     }
168
169     void setPool(XAConnectionPool pool) {
170         this.pool = pool;
171     }
172
173     public long getSleepTime() {
174         return System.currentTimeMillis() - startSleepTime;
175     }
176
177     public static void main(String JavaDoc[] args) {
178
179     }
180
181     /**
182      * 完成两件事:
183      * 1。在用户调用 XAConnection.close 的时候,如果处在事务中,delist 该资源
184      * 2。在 XAConnection 出错的时候,标记该 PoolableXAConnection 不再返回池中
185      */

186     private class TxConnectionListener implements ConnectionEventListener JavaDoc {
187
188         public void connectionClosed(ConnectionEvent JavaDoc event) {
189             logger.debug("connection closed event: " + event);
190             /*
191              *有可能事务 commit 之后,有人再调用 conn.close(),
192              * 那么 由于该 PoolableXAConnection 已经返回池中,则直接返回
193              */

194             if(passivated) return;
195             XAConnection JavaDoc xaconn = (XAConnection JavaDoc) event.getSource();
196             Transaction JavaDoc trans = null;
197             try {
198                 if(tm.getStatus() != Status.STATUS_NO_TRANSACTION) {
199                     trans = tm.getTransaction();
200                     XAResource JavaDoc res = (XAResource JavaDoc) xaconn.getXAResource();
201                     if(res != null) {
202                         trans.delistResource(res, XAResource.TMSUCCESS);
203                         XAConnectionManager.disassociate(trans, dbUrl, user, password);
204                         // XAConnection 并没有关闭,还是有效的,所以应该返回池中
205
pool.restoreObject(PoolableXAConnection.this);
206                     }
207                     else {
208                         logger.warn("can not getXAResource from " + xaconn);
209                     }
210                 }
211             }
212             catch(Exception JavaDoc e) {
213                 throw new RuntimeException JavaDoc("TxConnectionListener.connectionClosed() error", e);
214             }
215         }
216
217         /**
218          * 标记该 PoolabeXAConnection 已经出错了,不再返回到池中
219          *
220          * @param event
221          */

222         public void connectionErrorOccurred(ConnectionEvent JavaDoc event) {
223             // 对于 Oracle,在调用 XAConnection.close 的时候,发出 error 事件
224
logger.debug("connection error occurred: " + event.getSQLException());
225             PoolableXAConnection.this.markedError();
226         }
227     }
228
229     class XASynchronization implements Synchronization JavaDoc {
230
231         public void beforeCompletion() {
232
233         }
234
235         /**
236          * 将 PoolableXAConnection 返回池中
237          * 由 passivate 接口负责解除事务和 XAConnection 之间的关联
238          *
239          * @param status
240          */

241         public void afterCompletion(int status) {
242             logger.debug("PoolableXAConnection.XASynchronization.afterCompletion " + status);
243             pool.restoreObject(PoolableXAConnection.this);
244
245         }
246     }
247
248 }
249
250
Popular Tags