001: //jTDS JDBC Driver for Microsoft SQL Server and Sybase
002: //Copyright (C) 2004 The jTDS Project
003: //
004: //This library is free software; you can redistribute it and/or
005: //modify it under the terms of the GNU Lesser General Public
006: //License as published by the Free Software Foundation; either
007: //version 2.1 of the License, or (at your option) any later version.
008: //
009: //This library is distributed in the hope that it will be useful,
010: //but WITHOUT ANY WARRANTY; without even the implied warranty of
011: //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: //Lesser General Public License for more details.
013: //
014: //You should have received a copy of the GNU Lesser General Public
015: //License along with this library; if not, write to the Free Software
016: //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: //
018: package net.sourceforge.jtds.test;
019:
020: import java.sql.Connection;
021: import java.sql.ResultSet;
022: import java.sql.SQLException;
023: import java.sql.Statement;
024: import javax.sql.XAConnection;
025: import javax.sql.XADataSource;
026: import javax.transaction.xa.XAException;
027: import javax.transaction.xa.XAResource;
028: import javax.transaction.xa.Xid;
029:
030: import net.sourceforge.jtds.jdbc.Messages;
031: import net.sourceforge.jtds.jdbc.Driver;
032: import net.sourceforge.jtds.jdbcx.JtdsDataSource;
033: import net.sourceforge.jtds.jdbcx.JtdsXid;
034:
035: /**
036: * Test suite for XA Distributed Transactions. These tests are derived from
037: * examples found in the following article at
038: * <a href="http://archive.devx.com/java/free/articles/dd_jta/jta-2.asp">DevX</a>.
039: *
040: * @version $Id: XaTest.java,v 1.5 2004/12/03 16:52:09 alin_sinpalean Exp $
041: */
042: public class XaTest extends DatabaseTestCase {
043:
044: public XaTest(String name) {
045: super (name);
046: }
047:
048: /**
049: * Obtain an XADataSource.
050: *
051: * @return the <code>XADataSource.
052: * @throws SQLException if an error condition occurs
053: */
054: public XADataSource getDataSource() throws SQLException {
055: JtdsDataSource xaDS = new JtdsDataSource();
056: String user = props.getProperty(Messages.get(Driver.USER));
057: String pwd = props.getProperty(Messages.get(Driver.PASSWORD));
058: String host = props
059: .getProperty(Messages.get(Driver.SERVERNAME));
060: String port = props
061: .getProperty(Messages.get(Driver.PORTNUMBER));
062: String database = props.getProperty(Messages
063: .get(Driver.DATABASENAME));
064: String xaMode = props.getProperty(Messages
065: .get(Driver.XAEMULATION));
066: String tds = props.getProperty(Messages.get(Driver.TDS));
067: String serverType = props.getProperty(Messages
068: .get(Driver.SERVERTYPE));
069: int portn;
070: try {
071: portn = Integer.parseInt(port);
072: } catch (NumberFormatException e) {
073: portn = 1433;
074: }
075: xaDS.setServerName(host);
076: xaDS.setPortNumber(portn);
077: xaDS.setUser(user);
078: xaDS.setPassword(pwd);
079: xaDS.setDatabaseName(database);
080: xaDS.setXaEmulation(xaMode.equalsIgnoreCase("true"));
081: xaDS.setTds(tds);
082: xaDS.setServerType("2".equals(serverType) ? 2 : 1);
083: return xaDS;
084: }
085:
086: /**
087: * Test to demonstrate the XA_COMMIT function.
088: *
089: * @throws Exception if an error condition occurs
090: */
091: public void testXaCommit() throws Exception {
092: Connection con2 = null;
093: XAConnection xaCon = null;
094:
095: try {
096: dropTable("jTDS_XATEST");
097:
098: Statement stmt = con.createStatement();
099: stmt
100: .execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))");
101: assertNotNull(stmt
102: .executeQuery("SELECT * FROM jTDS_XATEST"));
103: stmt.close();
104:
105: XADataSource xaDS = getDataSource();
106: XAResource xaRes;
107: Xid xid;
108: xaCon = xaDS.getXAConnection();
109: xaRes = xaCon.getXAResource();
110: con2 = xaCon.getConnection();
111: stmt = con2.createStatement();
112: xid = new JtdsXid(new byte[] { 0x01 }, new byte[] { 0x02 });
113:
114: xaRes.start(xid, XAResource.TMNOFLAGS);
115: stmt
116: .executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')");
117: xaRes.end(xid, XAResource.TMSUCCESS);
118: int ret = xaRes.prepare(xid);
119: if (ret == XAResource.XA_OK) {
120: xaRes.commit(xid, false);
121: }
122: stmt.close();
123: stmt = con.createStatement();
124: ResultSet rs = stmt
125: .executeQuery("SELECT * FROM jTDS_XATEST");
126: assertNotNull(rs);
127: assertTrue(rs.next());
128: stmt.close();
129: } finally {
130: if (con2 != null) {
131: con2.close();
132: }
133: if (xaCon != null) {
134: xaCon.close();
135: }
136:
137: dropTable("jTDS_XATEST");
138: }
139: }
140:
141: /**
142: * Test to demonstrate the single phase XA_COMMIT function.
143: *
144: * @throws Exception if an error condition occurs
145: */
146: public void testXaOnePhaseCommit() throws Exception {
147: Connection con2 = null;
148: XAConnection xaCon = null;
149:
150: try {
151: dropTable("jTDS_XATEST");
152:
153: Statement stmt = con.createStatement();
154: stmt
155: .execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))");
156: assertNotNull(stmt
157: .executeQuery("SELECT * FROM jTDS_XATEST"));
158: stmt.close();
159:
160: XADataSource xaDS = getDataSource();
161: XAResource xaRes;
162: Xid xid;
163: xaCon = xaDS.getXAConnection();
164: xaRes = xaCon.getXAResource();
165: con2 = xaCon.getConnection();
166: stmt = con2.createStatement();
167: xid = new JtdsXid(new byte[] { 0x01 }, new byte[] { 0x02 });
168:
169: xaRes.start(xid, XAResource.TMNOFLAGS);
170: stmt
171: .executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')");
172: xaRes.end(xid, XAResource.TMSUCCESS);
173: xaRes.commit(xid, true);
174: stmt.close();
175: stmt = con.createStatement();
176: ResultSet rs = stmt
177: .executeQuery("SELECT * FROM jTDS_XATEST");
178: assertNotNull(rs);
179: assertTrue(rs.next());
180: stmt.close();
181: } finally {
182: if (con2 != null) {
183: con2.close();
184: }
185: if (xaCon != null) {
186: xaCon.close();
187: }
188:
189: dropTable("jTDS_XATEST");
190: }
191: }
192:
193: /**
194: * Test to demonstrate the use of the XA_ROLLBACK command.
195: *
196: * @throws Exception if an error condition occurs
197: */
198: public void testXaRollback() throws Exception {
199: Connection con2 = null;
200: XAConnection xaCon = null;
201:
202: try {
203: dropTable("jTDS_XATEST");
204:
205: Statement stmt = con.createStatement();
206: stmt
207: .execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))");
208: assertNotNull(stmt
209: .executeQuery("SELECT * FROM jTDS_XATEST"));
210: stmt.close();
211:
212: XADataSource xaDS = getDataSource();
213: XAResource xaRes;
214: Xid xid;
215: xaCon = xaDS.getXAConnection();
216: xaRes = xaCon.getXAResource();
217: con2 = xaCon.getConnection();
218: stmt = con2.createStatement();
219: xid = new JtdsXid(new byte[] { 0x01 }, new byte[] { 0x02 });
220:
221: xaRes.start(xid, XAResource.TMNOFLAGS);
222: stmt
223: .executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')");
224: xaRes.end(xid, XAResource.TMSUCCESS);
225: xaRes.rollback(xid);
226: stmt.close();
227: stmt = con.createStatement();
228: ResultSet rs = stmt
229: .executeQuery("SELECT * FROM jTDS_XATEST");
230: assertNotNull(rs);
231: assertFalse(rs.next());
232: stmt.close();
233: } finally {
234: if (con2 != null) {
235: con2.close();
236: }
237: if (xaCon != null) {
238: xaCon.close();
239: }
240:
241: dropTable("jTDS_XATEST");
242: }
243: }
244:
245: /**
246: * Demonstrate interleaving local transactions and distributed
247: * transactions.
248: *
249: * @throws Exception if an error condition occurs
250: */
251: public void testLocalTran() throws Exception {
252: if ("true".equalsIgnoreCase(props.getProperty(Messages
253: .get(Driver.XAEMULATION)))) {
254: // Emulation mode does not support suspending transactions.
255: return;
256: }
257: Connection con2 = null;
258: XAConnection xaCon = null;
259:
260: try {
261: dropTable("jTDS_XATEST");
262: dropTable("jTDS_XATEST2");
263:
264: Statement stmt = con.createStatement();
265: stmt
266: .execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))");
267: stmt
268: .execute("CREATE TABLE jTDS_XATEST2 (id int primary key, data varchar(255))");
269: assertNotNull(stmt
270: .executeQuery("SELECT * FROM jTDS_XATEST"));
271: assertNotNull(stmt
272: .executeQuery("SELECT * FROM jTDS_XATEST2"));
273: stmt.close();
274:
275: XADataSource xaDS = getDataSource();
276: XAResource xaRes;
277: Xid xid;
278: xaCon = xaDS.getXAConnection();
279: xaRes = xaCon.getXAResource();
280: con2 = xaCon.getConnection();
281: stmt = con2.createStatement();
282: xid = new JtdsXid(new byte[] { 0x01 }, new byte[] { 0x02 });
283:
284: xaRes.start(xid, XAResource.TMNOFLAGS);
285: stmt
286: .executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')");
287: xaRes.end(xid, XAResource.TMSUSPEND);
288: stmt
289: .executeUpdate("INSERT INTO jTDS_XATEST2 VALUES (1, 'TEST LINE')");
290: xaRes.start(xid, XAResource.TMRESUME);
291: stmt
292: .executeUpdate("INSERT INTO jTDS_XATEST VALUES (2, 'TEST LINE 2')");
293: xaRes.end(xid, XAResource.TMSUCCESS);
294: xaRes.rollback(xid);
295: stmt.close();
296: stmt = con.createStatement();
297: ResultSet rs = stmt
298: .executeQuery("SELECT * FROM jTDS_XATEST");
299: assertNotNull(rs);
300: assertFalse(rs.next());
301: rs = stmt.executeQuery("SELECT * FROM jTDS_XATEST2");
302: assertNotNull(rs);
303: assertTrue(rs.next());
304: stmt.close();
305: } finally {
306: if (con2 != null) {
307: con2.close();
308: }
309: if (xaCon != null) {
310: xaCon.close();
311: }
312:
313: dropTable("jTDS_XATEST");
314: dropTable("jTDS_XATEST2");
315: }
316: }
317:
318: /**
319: * Test to demonstrate the use of the XA_JOIN command.
320: *
321: * @throws Exception if an error condition occurs
322: */
323: public void testXAJoinTran() throws Exception {
324: if ("true".equalsIgnoreCase(props.getProperty(Messages
325: .get(Driver.XAEMULATION)))) {
326: // Emulation mode does not joining transactions.
327: return;
328: }
329: Connection con2 = null;
330: Connection con3 = null;
331: XAConnection xaCon = null;
332: XAConnection xaCon2 = null;
333:
334: try {
335: dropTable("jTDS_XATEST");
336: dropTable("jTDS_XATEST2");
337:
338: Statement stmt = con.createStatement();
339: stmt
340: .execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))");
341: stmt
342: .execute("CREATE TABLE jTDS_XATEST2 (id int primary key, data varchar(255))");
343: assertNotNull(stmt
344: .executeQuery("SELECT * FROM jTDS_XATEST"));
345: assertNotNull(stmt
346: .executeQuery("SELECT * FROM jTDS_XATEST2"));
347: stmt.close();
348:
349: XADataSource xaDS = getDataSource();
350: XAResource xaRes;
351: XAResource xaRes2;
352: Xid xid;
353: xaCon = xaDS.getXAConnection();
354: xaRes = xaCon.getXAResource();
355: xaCon2 = xaDS.getXAConnection();
356: xaRes2 = xaCon2.getXAResource();
357: con2 = xaCon.getConnection();
358: con3 = xaCon2.getConnection();
359: stmt = con2.createStatement();
360: Statement stmt2 = con3.createStatement();
361: xid = new JtdsXid(new byte[] { 0x01 }, new byte[] { 0x02 });
362:
363: xaRes.start(xid, XAResource.TMNOFLAGS);
364: stmt
365: .executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')");
366: assertTrue(xaRes.isSameRM(xaRes2));
367: xaRes2.start(xid, XAResource.TMJOIN);
368: stmt2
369: .executeUpdate("INSERT INTO jTDS_XATEST2 VALUES (1, 'TEST LINE 2')");
370: xaRes.end(xid, XAResource.TMSUCCESS);
371: xaRes2.end(xid, XAResource.TMSUCCESS);
372:
373: int ret = xaRes.prepare(xid);
374: if (ret == XAResource.XA_OK) {
375: xaRes.commit(xid, false);
376: }
377: stmt.close();
378: stmt2.close();
379: stmt = con.createStatement();
380: ResultSet rs = stmt
381: .executeQuery("SELECT * FROM jTDS_XATEST");
382: assertNotNull(rs);
383: assertTrue(rs.next());
384: rs = stmt.executeQuery("SELECT * FROM jTDS_XATEST2");
385: assertNotNull(rs);
386: assertTrue(rs.next());
387: stmt.close();
388: } finally {
389: if (con2 != null) {
390: con2.close();
391: }
392: if (con3 != null) {
393: con3.close();
394: }
395: if (xaCon != null) {
396: xaCon.close();
397: }
398: if (xaCon2 != null) {
399: xaCon2.close();
400: }
401:
402: dropTable("jTDS_XATEST");
403: dropTable("jTDS_XATEST2");
404: }
405: }
406:
407: /**
408: * Test to demonstrate the use of the XA_RECOVER command.
409: *
410: * @throws Exception if an error condition occurs
411: */
412: public void testXARecover() throws Exception {
413: XAConnection xaCon = null;
414:
415: try {
416: dropTable("jTDS_XATEST");
417:
418: Statement stmt = con.createStatement();
419: stmt
420: .execute("CREATE TABLE jTDS_XATEST (id int primary key, data varchar(255))");
421: assertNotNull(stmt
422: .executeQuery("SELECT * FROM jTDS_XATEST"));
423: stmt.close();
424:
425: XADataSource xaDS = getDataSource();
426: xaCon = xaDS.getXAConnection();
427: Connection con2 = xaCon.getConnection();
428: XAResource xaRes = xaCon.getXAResource();
429: stmt = con2.createStatement();
430: Xid xid;
431: xid = new JtdsXid(new byte[] { 0x01 }, new byte[] { 0x02 });
432:
433: xaRes.start(xid, XAResource.TMNOFLAGS);
434: stmt
435: .executeUpdate("INSERT INTO jTDS_XATEST VALUES (1, 'TEST LINE')");
436: xaRes.end(xid, XAResource.TMSUCCESS);
437: xaRes.prepare(xid);
438: stmt.close();
439: con2.close();
440: xaCon.close();
441: xaCon = xaDS.getXAConnection();
442: xaRes = xaCon.getXAResource();
443: Xid[] list = xaRes.recover(XAResource.TMSTARTRSCAN);
444: for (int i = 0; i < list.length; i++) {
445: //System.out.println("Xid="+list[i].toString());
446: try {
447: xaRes.rollback(list[i]);
448: } catch (XAException e) {
449: // System.out.println("Forgetting");
450: xaRes.forget(list[i]);
451: }
452: }
453: } finally {
454: if (xaCon != null) {
455: xaCon.close();
456: }
457:
458: dropTable("jTDS_XATEST");
459: }
460: }
461:
462: public static void main(String[] args) {
463: junit.textui.TestRunner.run(XaTest.class);
464: }
465: }
|