| 1 16 17 package org.springframework.jdbc.datasource; 18 19 import java.sql.Connection ; 20 import java.sql.DatabaseMetaData ; 21 import java.sql.PreparedStatement ; 22 import java.sql.SQLException ; 23 import java.sql.Savepoint ; 24 25 import javax.sql.DataSource ; 26 import javax.transaction.Status ; 27 import javax.transaction.UserTransaction ; 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 53 public class DataSourceTransactionManagerTests extends TestCase { 54 55 public void testTransactionCommitWithAutoCommitTrue() throws Exception { 56 doTestTransactionCommitRestoringAutoCommit(true, false, false); 57 } 58 59 public void testTransactionCommitWithAutoCommitFalse() throws Exception { 60 doTestTransactionCommitRestoringAutoCommit(false, false, false); 61 } 62 63 public void testTransactionCommitWithAutoCommitTrueAndLazyConnection() throws Exception { 64 doTestTransactionCommitRestoringAutoCommit(true, true, false); 65 } 66 67 public void testTransactionCommitWithAutoCommitFalseAndLazyConnection() throws Exception { 68 doTestTransactionCommitRestoringAutoCommit(false, true, false); 69 } 70 71 public void testTransactionCommitWithAutoCommitTrueAndLazyConnectionAndStatementCreated() throws Exception { 72 doTestTransactionCommitRestoringAutoCommit(true, true, true); 73 } 74 75 public void testTransactionCommitWithAutoCommitFalseAndLazyConnectionAndStatementCreated() throws Exception { 76 doTestTransactionCommitRestoringAutoCommit(false, true, true); 77 } 78 79 private void doTestTransactionCommitRestoringAutoCommit( 80 boolean autoCommit, boolean lazyConnection, final boolean createStatement) 81 throws Exception { 82 83 MockControl dsControl = MockControl.createControl(DataSource .class); 84 DataSource ds = (DataSource ) dsControl.getMock(); 85 MockControl conControl = MockControl.createControl(Connection .class); 86 final Connection con = (Connection ) 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 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 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 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 { 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 tCon = DataSourceUtils.getConnection(dsToUse); 143 try { 144 if (createStatement) { 145 tCon.createStatement(); 146 assertEquals(con, new CommonsDbcpNativeJdbcExtractor().getNativeConnection(tCon)); 147 } 148 } 149 catch (SQLException 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 { 163 doTestTransactionRollbackRestoringAutoCommit(true, false, false); 164 } 165 166 public void testTransactionRollbackWithAutoCommitFalse() throws Exception { 167 doTestTransactionRollbackRestoringAutoCommit(false, false, false); 168 } 169 170 public void testTransactionRollbackWithAutoCommitTrueAndLazyConnection() throws Exception { 171 doTestTransactionRollbackRestoringAutoCommit(true, true, false); 172 } 173 174 public void testTransactionRollbackWithAutoCommitFalseAndLazyConnection() throws Exception { 175 doTestTransactionRollbackRestoringAutoCommit(false, true, false); 176 } 177 178 public void testTransactionRollbackWithAutoCommitTrueAndLazyConnectionAndCreateStatement() throws Exception { 179 doTestTransactionRollbackRestoringAutoCommit(true, true, true); 180 } 181 182 public void testTransactionRollbackWithAutoCommitFalseAndLazyConnectionAndCreateStatement() throws Exception { 183 doTestTransactionRollbackRestoringAutoCommit(false, true, true); 184 } 185 186 private void doTestTransactionRollbackRestoringAutoCommit( 187 boolean autoCommit, boolean lazyConnection, final boolean createStatement) throws Exception { 188 189 MockControl dsControl = MockControl.createControl(DataSource .class); 190 DataSource ds = (DataSource ) dsControl.getMock(); 191 MockControl conControl = MockControl.createControl(Connection .class); 192 Connection con = (Connection ) 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 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 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 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 ex = new RuntimeException ("Application exception"); 242 try { 243 tt.execute(new TransactionCallbackWithoutResult() { 244 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 245 assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse)); 246 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive()); 247 assertTrue("Is new transaction", status.isNewTransaction()); 248 Connection con = DataSourceUtils.getConnection(dsToUse); 249 if (createStatement) { 250 try { 251 con.createStatement(); 252 } 253 catch (SQLException ex) { 254 throw new UncategorizedSQLException("", "", ex); 255 } 256 } 257 throw ex; 258 } 259 }); 260 fail("Should have thrown RuntimeException"); 261 } 262 catch (RuntimeException ex2) { 263 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 { 274 MockControl conControl = MockControl.createControl(Connection .class); 275 Connection con = (Connection ) conControl.getMock(); 276 MockControl dsControl = MockControl.createControl(DataSource .class); 277 final DataSource ds = (DataSource ) 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 ex = new RuntimeException ("Application exception"); 289 try { 290 tt.execute(new TransactionCallbackWithoutResult() { 291 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 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 ex2) { 301 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 303 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 { 316 MockControl conControl = MockControl.createControl(Connection .class); 317 Connection con = (Connection ) 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 .class); 328 final DataSource ds = (DataSource ) 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 { 342 assertTrue("Is new transaction", status.isNewTransaction()); 343 tt.execute(new TransactionCallbackWithoutResult() { 344 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 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 } 359 360 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 361 conControl.verify(); 362 dsControl.verify(); 363 } 364 365 public void testPropagationRequiresNewWithExistingTransaction() throws Exception { 366 MockControl conControl = MockControl.createControl(Connection .class); 367 Connection con = (Connection ) 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 .class); 380 final DataSource ds = (DataSource ) 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 { 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 { 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 { 420 MockControl conControl = MockControl.createControl(Connection .class); 421 Connection con = (Connection ) 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 .class); 432 final DataSource ds = (DataSource ) 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 { 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 { 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 { 472 MockControl conControl = MockControl.createControl(Connection .class); 473 Connection con = (Connection ) 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 .class); 484 final DataSource ds = (DataSource ) 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 { 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 { 503 fail("Should have thrown IllegalTransactionStateException"); 504 } 505 }); 506 fail("Should have thrown IllegalTransactionStateException"); 507 } 508 }); 509 } 510 catch (IllegalTransactionStateException ex) { 511 } 513 514 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 515 conControl.verify(); 516 dsControl.verify(); 517 } 518 519 public void testTransactionWithIsolationAndReadOnly() throws Exception { 520 MockControl dsControl = MockControl.createControl(DataSource .class); 521 DataSource ds = (DataSource ) dsControl.getMock(); 522 MockControl conControl = MockControl.createControl(Connection .class); 523 final Connection con = (Connection ) 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 } 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 { 571 doTestTransactionWithTimeout(10); 572 } 573 574 public void testTransactionWithShortTimeout() throws Exception { 575 doTestTransactionWithTimeout(1); 576 } 577 578 private void doTestTransactionWithTimeout(int timeout) throws Exception { 579 MockControl dsControl = MockControl.createControl(DataSource .class); 580 final DataSource ds = (DataSource ) dsControl.getMock(); 581 MockControl conControl = MockControl.createControl(Connection .class); 582 final Connection con = (Connection ) conControl.getMock(); 583 MockControl psControl = MockControl.createControl(PreparedStatement .class); 584 PreparedStatement ps = (PreparedStatement ) 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 ex) { 626 } 627 try { 628 Connection con = DataSourceUtils.getConnection(ds); 629 PreparedStatement ps = con.prepareStatement("some SQL statement"); 630 DataSourceUtils.applyTransactionTimeout(ps, ds); 631 } 632 catch (SQLException ex) { 633 &n
|