KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > jdbc > datasource > DataSourceTransactionManagerTests


1 /*
2  * Copyright 2002-2005 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.jdbc.datasource;
18
19 import java.sql.Connection JavaDoc;
20 import java.sql.DatabaseMetaData JavaDoc;
21 import java.sql.PreparedStatement JavaDoc;
22 import java.sql.SQLException JavaDoc;
23 import java.sql.Savepoint JavaDoc;
24
25 import javax.sql.DataSource JavaDoc;
26 import javax.transaction.Status JavaDoc;
27 import javax.transaction.UserTransaction JavaDoc;
28
29 import junit.framework.TestCase;
30 import org.easymock.MockControl;
31
32 import org.springframework.core.JdkVersion;
33 import org.springframework.dao.DataAccessResourceFailureException;
34 import org.springframework.jdbc.UncategorizedSQLException;
35 import org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor;
36 import org.springframework.transaction.CannotCreateTransactionException;
37 import org.springframework.transaction.IllegalTransactionStateException;
38 import org.springframework.transaction.PlatformTransactionManager;
39 import org.springframework.transaction.TransactionDefinition;
40 import org.springframework.transaction.TransactionStatus;
41 import org.springframework.transaction.TransactionSystemException;
42 import org.springframework.transaction.TransactionTimedOutException;
43 import org.springframework.transaction.UnexpectedRollbackException;
44 import org.springframework.transaction.jta.JtaTransactionManager;
45 import org.springframework.transaction.support.TransactionCallbackWithoutResult;
46 import org.springframework.transaction.support.TransactionSynchronizationManager;
47 import org.springframework.transaction.support.TransactionTemplate;
48
49 /**
50  * @author Juergen Hoeller
51  * @since 04.07.2003
52  */

53 public class DataSourceTransactionManagerTests extends TestCase {
54     
55     public void testTransactionCommitWithAutoCommitTrue() throws Exception JavaDoc {
56         doTestTransactionCommitRestoringAutoCommit(true, false, false);
57     }
58     
59     public void testTransactionCommitWithAutoCommitFalse() throws Exception JavaDoc {
60         doTestTransactionCommitRestoringAutoCommit(false, false, false);
61     }
62
63     public void testTransactionCommitWithAutoCommitTrueAndLazyConnection() throws Exception JavaDoc {
64         doTestTransactionCommitRestoringAutoCommit(true, true, false);
65     }
66
67     public void testTransactionCommitWithAutoCommitFalseAndLazyConnection() throws Exception JavaDoc {
68         doTestTransactionCommitRestoringAutoCommit(false, true, false);
69     }
70
71     public void testTransactionCommitWithAutoCommitTrueAndLazyConnectionAndStatementCreated() throws Exception JavaDoc {
72         doTestTransactionCommitRestoringAutoCommit(true, true, true);
73     }
74
75     public void testTransactionCommitWithAutoCommitFalseAndLazyConnectionAndStatementCreated() throws Exception JavaDoc {
76         doTestTransactionCommitRestoringAutoCommit(false, true, true);
77     }
78
79     private void doTestTransactionCommitRestoringAutoCommit(
80             boolean autoCommit, boolean lazyConnection, final boolean createStatement)
81             throws Exception JavaDoc {
82
83         MockControl dsControl = MockControl.createControl(DataSource JavaDoc.class);
84         DataSource JavaDoc ds = (DataSource JavaDoc) dsControl.getMock();
85         MockControl conControl = MockControl.createControl(Connection JavaDoc.class);
86         final Connection JavaDoc con = (Connection JavaDoc) conControl.getMock();
87
88         if (lazyConnection) {
89             ds.getConnection();
90             dsControl.setReturnValue(con, 1);
91             con.getAutoCommit();
92             conControl.setReturnValue(autoCommit, 1);
93             con.getTransactionIsolation();
94             conControl.setReturnValue(Connection.TRANSACTION_READ_COMMITTED, 1);
95             con.close();
96             conControl.setVoidCallable(1);
97         }
98
99         if (!lazyConnection || createStatement) {
100             ds.getConnection();
101             dsControl.setReturnValue(con, 1);
102             con.getAutoCommit();
103             conControl.setReturnValue(autoCommit, 1);
104             if (autoCommit) {
105                 // Must disable autocommit
106
con.setAutoCommit(false);
107                 conControl.setVoidCallable(1);
108             }
109             if (createStatement) {
110                 con.createStatement();
111                 conControl.setReturnValue(null, 1);
112             }
113             con.commit();
114             conControl.setVoidCallable(1);
115             con.isReadOnly();
116             conControl.setReturnValue(false, 1);
117             if (autoCommit) {
118                 // must restore autoCommit
119
con.setAutoCommit(true);
120                 conControl.setVoidCallable(1);
121             }
122             con.close();
123             conControl.setVoidCallable(1);
124         }
125
126         conControl.replay();
127         dsControl.replay();
128
129         final DataSource JavaDoc dsToUse = (lazyConnection ? new LazyConnectionDataSourceProxy(ds) : ds);
130         PlatformTransactionManager tm = new DataSourceTransactionManager(dsToUse);
131         TransactionTemplate tt = new TransactionTemplate(tm);
132         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
133         assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
134
135         tt.execute(new TransactionCallbackWithoutResult() {
136             protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
137                 assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
138                 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
139                 assertTrue("Is new transaction", status.isNewTransaction());
140                 assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
141                 assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
142                 Connection JavaDoc tCon = DataSourceUtils.getConnection(dsToUse);
143                 try {
144                     if (createStatement) {
145                         tCon.createStatement();
146                         assertEquals(con, new CommonsDbcpNativeJdbcExtractor().getNativeConnection(tCon));
147                     }
148                 }
149                 catch (SQLException JavaDoc ex) {
150                     throw new UncategorizedSQLException("", "", ex);
151                 }
152             }
153         });
154
155         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
156         assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
157
158         conControl.verify();
159         dsControl.verify();
160     }
161     
162     public void testTransactionRollbackWithAutoCommitTrue() throws Exception JavaDoc {
163         doTestTransactionRollbackRestoringAutoCommit(true, false, false);
164     }
165     
166     public void testTransactionRollbackWithAutoCommitFalse() throws Exception JavaDoc {
167         doTestTransactionRollbackRestoringAutoCommit(false, false, false);
168     }
169
170     public void testTransactionRollbackWithAutoCommitTrueAndLazyConnection() throws Exception JavaDoc {
171         doTestTransactionRollbackRestoringAutoCommit(true, true, false);
172     }
173
174     public void testTransactionRollbackWithAutoCommitFalseAndLazyConnection() throws Exception JavaDoc {
175         doTestTransactionRollbackRestoringAutoCommit(false, true, false);
176     }
177
178     public void testTransactionRollbackWithAutoCommitTrueAndLazyConnectionAndCreateStatement() throws Exception JavaDoc {
179         doTestTransactionRollbackRestoringAutoCommit(true, true, true);
180     }
181
182     public void testTransactionRollbackWithAutoCommitFalseAndLazyConnectionAndCreateStatement() throws Exception JavaDoc {
183         doTestTransactionRollbackRestoringAutoCommit(false, true, true);
184     }
185
186     private void doTestTransactionRollbackRestoringAutoCommit(
187             boolean autoCommit, boolean lazyConnection, final boolean createStatement) throws Exception JavaDoc {
188
189         MockControl dsControl = MockControl.createControl(DataSource JavaDoc.class);
190         DataSource JavaDoc ds = (DataSource JavaDoc) dsControl.getMock();
191         MockControl conControl = MockControl.createControl(Connection JavaDoc.class);
192         Connection JavaDoc con = (Connection JavaDoc) conControl.getMock();
193
194         if (lazyConnection) {
195             ds.getConnection();
196             dsControl.setReturnValue(con, 1);
197             con.getAutoCommit();
198             conControl.setReturnValue(autoCommit, 1);
199             con.getTransactionIsolation();
200             conControl.setReturnValue(Connection.TRANSACTION_READ_COMMITTED, 1);
201             con.close();
202             conControl.setVoidCallable(1);
203         }
204
205         if (!lazyConnection || createStatement) {
206             ds.getConnection();
207             dsControl.setReturnValue(con, 1);
208             con.getAutoCommit();
209             conControl.setReturnValue(autoCommit, 1);
210             if (autoCommit) {
211                 // Must disable autocommit
212
con.setAutoCommit(false);
213                 conControl.setVoidCallable(1);
214             }
215             if (createStatement) {
216                 con.createStatement();
217                 conControl.setReturnValue(null, 1);
218             }
219             con.rollback();
220             conControl.setVoidCallable(1);
221             con.isReadOnly();
222             conControl.setReturnValue(false, 1);
223             if (autoCommit) {
224                 // Must restore autocommit
225
con.setAutoCommit(true);
226                 conControl.setVoidCallable(1);
227             }
228             con.close();
229             conControl.setVoidCallable(1);
230         }
231
232         conControl.replay();
233         dsControl.replay();
234
235         final DataSource JavaDoc dsToUse = (lazyConnection ? new LazyConnectionDataSourceProxy(ds) : ds);
236         PlatformTransactionManager tm = new DataSourceTransactionManager(dsToUse);
237         TransactionTemplate tt = new TransactionTemplate(tm);
238         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
239         assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
240
241         final RuntimeException JavaDoc ex = new RuntimeException JavaDoc("Application exception");
242         try {
243             tt.execute(new TransactionCallbackWithoutResult() {
244                 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
245                     assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
246                     assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
247                     assertTrue("Is new transaction", status.isNewTransaction());
248                     Connection JavaDoc con = DataSourceUtils.getConnection(dsToUse);
249                     if (createStatement) {
250                         try {
251                             con.createStatement();
252                         }
253                         catch (SQLException JavaDoc ex) {
254                             throw new UncategorizedSQLException("", "", ex);
255                         }
256                     }
257                     throw ex;
258                 }
259             });
260             fail("Should have thrown RuntimeException");
261         }
262         catch (RuntimeException JavaDoc ex2) {
263             // expected
264
assertTrue("Correct exception thrown", ex2.equals(ex));
265         }
266
267         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
268         assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
269         conControl.verify();
270         dsControl.verify();
271     }
272
273     public void testTransactionRollbackOnly() throws Exception JavaDoc {
274         MockControl conControl = MockControl.createControl(Connection JavaDoc.class);
275         Connection JavaDoc con = (Connection JavaDoc) conControl.getMock();
276         MockControl dsControl = MockControl.createControl(DataSource JavaDoc.class);
277         final DataSource JavaDoc ds = (DataSource JavaDoc) dsControl.getMock();
278         conControl.replay();
279         dsControl.replay();
280
281         DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
282         tm.setTransactionSynchronization(DataSourceTransactionManager.SYNCHRONIZATION_NEVER);
283         TransactionTemplate tt = new TransactionTemplate(tm);
284         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
285         assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
286
287         TransactionSynchronizationManager.bindResource(ds, new ConnectionHolder(con));
288         final RuntimeException JavaDoc ex = new RuntimeException JavaDoc("Application exception");
289         try {
290             tt.execute(new TransactionCallbackWithoutResult() {
291                 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
292                     assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
293                     assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
294                     assertTrue("Is existing transaction", !status.isNewTransaction());
295                     throw ex;
296                 }
297             });
298             fail("Should have thrown RuntimeException");
299         }
300         catch (RuntimeException JavaDoc ex2) {
301             // expected
302
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
303             //ex2.printStackTrace();
304
assertEquals("Correct exception thrown", ex, ex2);
305         }
306         finally {
307             TransactionSynchronizationManager.unbindResource(ds);
308         }
309
310         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
311         conControl.verify();
312         dsControl.verify();
313     }
314
315     public void testParticipatingTransactionWithRollbackOnly() throws Exception JavaDoc {
316         MockControl conControl = MockControl.createControl(Connection JavaDoc.class);
317         Connection JavaDoc con = (Connection JavaDoc) conControl.getMock();
318         con.getAutoCommit();
319         conControl.setReturnValue(false, 1);
320         con.rollback();
321         conControl.setVoidCallable(1);
322         con.isReadOnly();
323         conControl.setReturnValue(false, 1);
324         con.close();
325         conControl.setVoidCallable(1);
326
327         MockControl dsControl = MockControl.createControl(DataSource JavaDoc.class);
328         final DataSource JavaDoc ds = (DataSource JavaDoc) dsControl.getMock();
329         ds.getConnection();
330         dsControl.setReturnValue(con, 1);
331         conControl.replay();
332         dsControl.replay();
333
334         PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
335         final TransactionTemplate tt = new TransactionTemplate(tm);
336         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
337         assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
338
339         try {
340             tt.execute(new TransactionCallbackWithoutResult() {
341                 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
342                     assertTrue("Is new transaction", status.isNewTransaction());
343                     tt.execute(new TransactionCallbackWithoutResult() {
344                         protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
345                             assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
346                             assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
347                             assertTrue("Is existing transaction", !status.isNewTransaction());
348                             status.setRollbackOnly();
349                         }
350                     });
351                     assertTrue("Is new transaction", status.isNewTransaction());
352                 }
353             });
354             fail("Should have thrown UnexpectedRollbackException");
355         }
356         catch (UnexpectedRollbackException ex) {
357             // expected
358
}
359
360         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
361         conControl.verify();
362         dsControl.verify();
363     }
364
365     public void testPropagationRequiresNewWithExistingTransaction() throws Exception JavaDoc {
366         MockControl conControl = MockControl.createControl(Connection JavaDoc.class);
367         Connection JavaDoc con = (Connection JavaDoc) conControl.getMock();
368         con.getAutoCommit();
369         conControl.setReturnValue(false, 2);
370         con.rollback();
371         conControl.setVoidCallable(1);
372         con.commit();
373         conControl.setVoidCallable(1);
374         con.isReadOnly();
375         conControl.setReturnValue(false, 2);
376         con.close();
377         conControl.setVoidCallable(2);
378
379         MockControl dsControl = MockControl.createControl(DataSource JavaDoc.class);
380         final DataSource JavaDoc ds = (DataSource JavaDoc) dsControl.getMock();
381         ds.getConnection();
382         dsControl.setReturnValue(con, 2);
383         conControl.replay();
384         dsControl.replay();
385
386         PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
387         final TransactionTemplate tt = new TransactionTemplate(tm);
388         tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
389         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
390         assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
391
392         tt.execute(new TransactionCallbackWithoutResult() {
393             protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
394                 assertTrue("Is new transaction", status.isNewTransaction());
395                 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
396                 assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
397                 assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
398                 tt.execute(new TransactionCallbackWithoutResult() {
399                     protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
400                         assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
401                         assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
402                         assertTrue("Is new transaction", status.isNewTransaction());
403                         assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
404                         assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
405                         status.setRollbackOnly();
406                     }
407                 });
408                 assertTrue("Is new transaction", status.isNewTransaction());
409                 assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
410                 assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
411             }
412         });
413
414         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
415         conControl.verify();
416         dsControl.verify();
417     }
418
419     public void testPropagationNotSupportedWithExistingTransaction() throws Exception JavaDoc {
420         MockControl conControl = MockControl.createControl(Connection JavaDoc.class);
421         Connection JavaDoc con = (Connection JavaDoc) conControl.getMock();
422         con.getAutoCommit();
423         conControl.setReturnValue(false, 1);
424         con.commit();
425         conControl.setVoidCallable(1);
426         con.isReadOnly();
427         conControl.setReturnValue(false, 1);
428         con.close();
429         conControl.setVoidCallable(1);
430
431         MockControl dsControl = MockControl.createControl(DataSource JavaDoc.class);
432         final DataSource JavaDoc ds = (DataSource JavaDoc) dsControl.getMock();
433         ds.getConnection();
434         dsControl.setReturnValue(con, 1);
435         conControl.replay();
436         dsControl.replay();
437
438         PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
439         final TransactionTemplate tt = new TransactionTemplate(tm);
440         tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
441         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
442         assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
443
444         tt.execute(new TransactionCallbackWithoutResult() {
445             protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
446                 assertTrue("Is new transaction", status.isNewTransaction());
447                 assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
448                 assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
449                 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
450                 tt.execute(new TransactionCallbackWithoutResult() {
451                     protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
452                         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
453                         assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
454                         assertTrue("Isn't new transaction", !status.isNewTransaction());
455                         assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
456                         assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
457                         status.setRollbackOnly();
458                     }
459                 });
460                 assertTrue("Is new transaction", status.isNewTransaction());
461                 assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
462                 assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
463             }
464         });
465
466         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
467         conControl.verify();
468         dsControl.verify();
469     }
470
471     public void testPropagationNeverWithExistingTransaction() throws Exception JavaDoc {
472         MockControl conControl = MockControl.createControl(Connection JavaDoc.class);
473         Connection JavaDoc con = (Connection JavaDoc) conControl.getMock();
474         con.getAutoCommit();
475         conControl.setReturnValue(false, 1);
476         con.rollback();
477         conControl.setVoidCallable(1);
478         con.isReadOnly();
479         conControl.setReturnValue(false, 1);
480         con.close();
481         conControl.setVoidCallable(1);
482
483         MockControl dsControl = MockControl.createControl(DataSource JavaDoc.class);
484         final DataSource JavaDoc ds = (DataSource JavaDoc) dsControl.getMock();
485         ds.getConnection();
486         dsControl.setReturnValue(con, 1);
487         conControl.replay();
488         dsControl.replay();
489
490         PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
491         final TransactionTemplate tt = new TransactionTemplate(tm);
492         tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
493         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
494         assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
495
496         try {
497             tt.execute(new TransactionCallbackWithoutResult() {
498                 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
499                     assertTrue("Is new transaction", status.isNewTransaction());
500                     tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
501                     tt.execute(new TransactionCallbackWithoutResult() {
502                         protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException JavaDoc {
503                             fail("Should have thrown IllegalTransactionStateException");
504                         }
505                     });
506                     fail("Should have thrown IllegalTransactionStateException");
507                 }
508             });
509         }
510         catch (IllegalTransactionStateException ex) {
511             // expected
512
}
513
514         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
515         conControl.verify();
516         dsControl.verify();
517     }
518
519     public void testTransactionWithIsolationAndReadOnly() throws Exception JavaDoc {
520         MockControl dsControl = MockControl.createControl(DataSource JavaDoc.class);
521         DataSource JavaDoc ds = (DataSource JavaDoc) dsControl.getMock();
522         MockControl conControl = MockControl.createControl(Connection JavaDoc.class);
523         final Connection JavaDoc con = (Connection JavaDoc) conControl.getMock();
524
525         ds.getConnection();
526         dsControl.setReturnValue(con, 1);
527         con.getTransactionIsolation();
528         conControl.setReturnValue(Connection.TRANSACTION_READ_COMMITTED, 1);
529         con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
530         conControl.setVoidCallable(1);
531         con.setReadOnly(true);
532         conControl.setVoidCallable(1);
533         con.getAutoCommit();
534         conControl.setReturnValue(true, 1);
535         con.setAutoCommit(false);
536         conControl.setVoidCallable(1);
537         con.commit();
538         conControl.setVoidCallable(1);
539         con.setAutoCommit(true);
540         conControl.setVoidCallable(1);
541         con.isReadOnly();
542         conControl.setReturnValue(false, 1);
543         con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
544         conControl.setVoidCallable(1);
545         con.close();
546         conControl.setVoidCallable(1);
547
548         conControl.replay();
549         dsControl.replay();
550
551         PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
552         TransactionTemplate tt = new TransactionTemplate(tm);
553         tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
554         tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
555         tt.setReadOnly(true);
556         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
557         tt.execute(new TransactionCallbackWithoutResult() {
558             protected void doInTransactionWithoutResult(TransactionStatus status) {
559                 assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
560                 assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
561                 // something transactional
562
}
563         });
564
565         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
566         conControl.verify();
567         dsControl.verify();
568     }
569
570     public void testTransactionWithLongTimeout() throws Exception JavaDoc {
571         doTestTransactionWithTimeout(10);
572     }
573
574     public void testTransactionWithShortTimeout() throws Exception JavaDoc {
575         doTestTransactionWithTimeout(1);
576     }
577
578     private void doTestTransactionWithTimeout(int timeout) throws Exception JavaDoc {
579         MockControl dsControl = MockControl.createControl(DataSource JavaDoc.class);
580         final DataSource JavaDoc ds = (DataSource JavaDoc) dsControl.getMock();
581         MockControl conControl = MockControl.createControl(Connection JavaDoc.class);
582         final Connection JavaDoc con = (Connection JavaDoc) conControl.getMock();
583         MockControl psControl = MockControl.createControl(PreparedStatement JavaDoc.class);
584         PreparedStatement JavaDoc ps = (PreparedStatement JavaDoc) psControl.getMock();
585
586         ds.getConnection();
587         dsControl.setReturnValue(con, 1);
588         con.getAutoCommit();
589         conControl.setReturnValue(true, 1);
590         con.setAutoCommit(false);
591         conControl.setVoidCallable(1);
592         con.prepareStatement("some SQL statement");
593         conControl.setReturnValue(ps, 1);
594         if (timeout > 1) {
595             ps.setQueryTimeout(timeout - 1);
596             psControl.setVoidCallable(1);
597             con.commit();
598         }
599         else {
600             con.rollback();
601         }
602         conControl.setVoidCallable(1);
603         con.setAutoCommit(true);
604         conControl.setVoidCallable(1);
605         con.isReadOnly();
606         conControl.setReturnValue(false, 1);
607         con.close();
608         conControl.setVoidCallable(1);
609
610         psControl.replay();
611         conControl.replay();
612         dsControl.replay();
613
614         PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
615         TransactionTemplate tt = new TransactionTemplate(tm);
616         tt.setTimeout(timeout);
617         assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
618
619         try {
620             tt.execute(new TransactionCallbackWithoutResult() {
621                 protected void doInTransactionWithoutResult(TransactionStatus status) {
622                     try {
623                         Thread.sleep(1500);
624                     }
625                     catch (InterruptedException JavaDoc ex) {
626                     }
627                     try {
628                         Connection JavaDoc con = DataSourceUtils.getConnection(ds);
629                         PreparedStatement JavaDoc ps = con.prepareStatement("some SQL statement");
630                         DataSourceUtils.applyTransactionTimeout(ps, ds);
631                     }
632                     catch (SQLException JavaDoc ex) {
633        &n