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 throw new DataAccessResourceFailureException("", ex); 634 } 635 } 636 }); 637 if (timeout <= 1) { 638 fail("Should have thrown TransactionTimedOutException"); 639 } 640 } 641 catch (TransactionTimedOutException ex) { 642 if (timeout <= 1) { 643 } 645 else { 646 throw ex; 647 } 648 } 649 650 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 651 conControl.verify(); 652 dsControl.verify(); 653 psControl.verify(); 654 } 655 656 public void testTransactionAwareDataSourceProxy() throws Exception { 657 MockControl dsControl = MockControl.createControl(DataSource .class); 658 final DataSource ds = (DataSource ) dsControl.getMock(); 659 MockControl conControl = MockControl.createControl(Connection .class); 660 final Connection con = (Connection ) conControl.getMock(); 661 662 ds.getConnection(); 663 dsControl.setReturnValue(con, 1); 664 con.getAutoCommit(); 665 conControl.setReturnValue(true, 1); 666 con.setAutoCommit(false); 667 conControl.setVoidCallable(1); 668 con.commit(); 669 conControl.setVoidCallable(1); 670 con.setAutoCommit(true); 671 conControl.setVoidCallable(1); 672 con.isReadOnly(); 673 conControl.setReturnValue(false, 1); 674 con.close(); 675 conControl.setVoidCallable(1); 676 677 conControl.replay(); 678 dsControl.replay(); 679 680 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 681 TransactionTemplate tt = new TransactionTemplate(tm); 682 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 683 tt.execute(new TransactionCallbackWithoutResult() { 684 protected void doInTransactionWithoutResult(TransactionStatus status) { 685 assertEquals(con, DataSourceUtils.getConnection(ds)); 687 TransactionAwareDataSourceProxy dsProxy = new TransactionAwareDataSourceProxy(ds); 688 try { 689 assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection()); 690 assertEquals(con, new CommonsDbcpNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection())); 691 dsProxy.getConnection().close(); 693 } 694 catch (SQLException ex) { 695 throw new UncategorizedSQLException("", "", ex); 696 } 697 } 698 }); 699 700 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 701 conControl.verify(); 702 dsControl.verify(); 703 } 704 705 708 public void testTransactionWithExceptionOnBegin() throws Exception { 709 MockControl conControl = MockControl.createControl(Connection .class); 710 final Connection con = (Connection ) conControl.getMock(); 711 MockControl dsControl = MockControl.createControl(DataSource .class); 712 DataSource ds = (DataSource ) dsControl.getMock(); 713 ds.getConnection(); 714 dsControl.setReturnValue(con, 1); 715 con.getAutoCommit(); 716 conControl.setThrowable(new SQLException ("Cannot begin")); 717 con.close(); 718 conControl.setVoidCallable(); 719 conControl.replay(); 720 dsControl.replay(); 721 722 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 723 TransactionTemplate tt = new TransactionTemplate(tm); 724 try { 725 tt.execute(new TransactionCallbackWithoutResult() { 726 protected void doInTransactionWithoutResult(TransactionStatus status) { 727 } 729 }); 730 fail("Should have thrown CannotCreateTransactionException"); 731 } 732 catch (CannotCreateTransactionException ex) { 733 } 735 736 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 737 conControl.verify(); 738 } 739 740 public void testTransactionWithExceptionOnCommit() throws Exception { 741 MockControl conControl = MockControl.createControl(Connection .class); 742 final Connection con = (Connection ) conControl.getMock(); 743 MockControl dsControl = MockControl.createControl(DataSource .class); 744 DataSource ds = (DataSource ) dsControl.getMock(); 745 ds.getConnection(); 746 dsControl.setReturnValue(con, 1); 747 con.getAutoCommit(); 748 conControl.setReturnValue(false, 1); 750 con.commit(); 751 conControl.setThrowable(new SQLException ("Cannot commit"), 1); 752 con.isReadOnly(); 753 conControl.setReturnValue(false, 1); 754 con.close(); 755 conControl.setVoidCallable(1); 756 conControl.replay(); 757 dsControl.replay(); 758 759 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 760 TransactionTemplate tt = new TransactionTemplate(tm); 761 try { 762 tt.execute(new TransactionCallbackWithoutResult() { 763 protected void doInTransactionWithoutResult(TransactionStatus status) { 764 } 766 }); 767 fail("Should have thrown TransactionSystemException"); 768 } 769 catch (TransactionSystemException ex) { 770 } 772 773 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 774 conControl.verify(); 775 } 776 777 public void testTransactionWithExceptionOnCommitAndRollbackOnCommitFailure() throws Exception { 778 MockControl conControl = MockControl.createControl(Connection .class); 779 final Connection con = (Connection ) conControl.getMock(); 780 MockControl dsControl = MockControl.createControl(DataSource .class); 781 DataSource ds = (DataSource ) dsControl.getMock(); 782 ds.getConnection(); 783 dsControl.setReturnValue(con, 1); 784 con.getAutoCommit(); 785 conControl.setReturnValue(false); 787 con.commit(); 788 conControl.setThrowable(new SQLException ("Cannot commit"), 1); 789 con.rollback(); 790 conControl.setVoidCallable(1); 791 con.isReadOnly(); 792 conControl.setReturnValue(false, 1); 793 con.close(); 794 conControl.setVoidCallable(1); 795 conControl.replay(); 796 dsControl.replay(); 797 798 DataSourceTransactionManager tm = new DataSourceTransactionManager(ds); 799 tm.setRollbackOnCommitFailure(true); 800 TransactionTemplate tt = new TransactionTemplate(tm); 801 try { 802 tt.execute(new TransactionCallbackWithoutResult() { 803 protected void doInTransactionWithoutResult(TransactionStatus status) { 804 } 806 }); 807 fail("Should have thrown TransactionSystemException"); 808 } 809 catch (TransactionSystemException ex) { 810 } 812 813 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 814 conControl.verify(); 815 } 816 817 public void testTransactionWithExceptionOnRollback() throws Exception { 818 MockControl conControl = MockControl.createControl(Connection .class); 819 final Connection con = (Connection ) conControl.getMock(); 820 MockControl dsControl = MockControl.createControl(DataSource .class); 821 DataSource ds = (DataSource ) dsControl.getMock(); 822 ds.getConnection(); 823 dsControl.setReturnValue(con, 1); 824 con.getAutoCommit(); 825 conControl.setReturnValue(true, 1); 826 con.setAutoCommit(false); 828 conControl.setVoidCallable(1); 829 830 con.rollback(); 831 conControl.setThrowable(new SQLException ("Cannot rollback"), 1); 832 con.setAutoCommit(true); 833 conControl.setVoidCallable(1); 834 con.isReadOnly(); 835 conControl.setReturnValue(false, 1); 836 con.close(); 837 conControl.setVoidCallable(1); 838 conControl.replay(); 839 dsControl.replay(); 840 841 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 842 TransactionTemplate tt = new TransactionTemplate(tm); 843 try { 844 tt.execute(new TransactionCallbackWithoutResult() { 845 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 846 status.setRollbackOnly(); 847 } 848 }); 849 fail("Should have thrown TransactionSystemException"); 850 } 851 catch (TransactionSystemException ex) { 852 } 854 855 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 856 conControl.verify(); 857 } 858 859 public void testJtaTransactionCommit() throws Exception { 860 MockControl utControl = MockControl.createControl(UserTransaction .class); 861 UserTransaction ut = (UserTransaction ) utControl.getMock(); 862 ut.getStatus(); 863 utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1); 864 ut.getStatus(); 865 utControl.setReturnValue(Status.STATUS_ACTIVE, 1); 866 ut.begin(); 867 utControl.setVoidCallable(1); 868 ut.commit(); 869 utControl.setVoidCallable(1); 870 utControl.replay(); 871 872 MockControl conControl = MockControl.createControl(Connection .class); 873 Connection con = (Connection ) conControl.getMock(); 874 con.close(); 875 conControl.setVoidCallable(1); 876 877 MockControl dsControl = MockControl.createControl(DataSource .class); 878 final DataSource ds = (DataSource ) dsControl.getMock(); 879 ds.getConnection(); 880 dsControl.setReturnValue(con, 1); 881 conControl.replay(); 882 dsControl.replay(); 883 884 JtaTransactionManager ptm = new JtaTransactionManager(ut); 885 TransactionTemplate tt = new TransactionTemplate(ptm); 886 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 887 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 888 889 tt.execute(new TransactionCallbackWithoutResult() { 890 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 891 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 892 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive()); 893 assertTrue("Is new transaction", status.isNewTransaction()); 894 895 Connection con = DataSourceUtils.getConnection(ds); 896 assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); 897 DataSourceUtils.releaseConnection(con, ds); 898 899 con = DataSourceUtils.getConnection(ds); 900 assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); 901 DataSourceUtils.releaseConnection(con, ds); } 902 }); 903 904 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 905 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 906 conControl.verify(); 907 dsControl.verify(); 908 } 909 910 public void testTransactionWithPropagationSupports() throws Exception { 911 MockControl dsControl = MockControl.createControl(DataSource .class); 912 final DataSource ds = (DataSource ) dsControl.getMock(); 913 dsControl.replay(); 914 915 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 916 TransactionTemplate tt = new TransactionTemplate(tm); 917 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS); 918 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 919 920 tt.execute(new TransactionCallbackWithoutResult() { 921 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 922 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 923 assertTrue("Is not new transaction", !status.isNewTransaction()); 924 assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); 925 assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); 926 } 927 }); 928 929 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 930 dsControl.verify(); 931 } 932 933 public void testTransactionWithPropagationNotSupported() throws Exception { 934 MockControl dsControl = MockControl.createControl(DataSource .class); 935 final DataSource ds = (DataSource ) dsControl.getMock(); 936 dsControl.replay(); 937 938 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 939 TransactionTemplate tt = new TransactionTemplate(tm); 940 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); 941 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 942 943 tt.execute(new TransactionCallbackWithoutResult() { 944 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 945 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 946 assertTrue("Is not new transaction", !status.isNewTransaction()); 947 } 948 }); 949 950 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 951 dsControl.verify(); 952 } 953 954 public void testTransactionWithPropagationNever() throws Exception { 955 MockControl dsControl = MockControl.createControl(DataSource .class); 956 final DataSource ds = (DataSource ) dsControl.getMock(); 957 dsControl.replay(); 958 959 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 960 TransactionTemplate tt = new TransactionTemplate(tm); 961 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER); 962 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 963 964 tt.execute(new TransactionCallbackWithoutResult() { 965 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 966 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 967 assertTrue("Is not new transaction", !status.isNewTransaction()); 968 } 969 }); 970 971 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 972 dsControl.verify(); 973 } 974 975 public void testExistingTransactionWithPropagationNested() throws Exception { 976 if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_14) { 977 return; 978 } 979 980 MockControl dsControl = MockControl.createControl(DataSource .class); 981 final DataSource ds = (DataSource ) dsControl.getMock(); 982 MockControl conControl = MockControl.createControl(Connection .class); 983 Connection con = (Connection ) conControl.getMock(); 984 MockControl mdControl = MockControl.createControl(DatabaseMetaData .class); 985 DatabaseMetaData md = (DatabaseMetaData ) mdControl.getMock(); 986 MockControl spControl = MockControl.createControl(Savepoint .class); 987 Savepoint sp = (Savepoint ) spControl.getMock(); 988 989 con.getAutoCommit(); 990 conControl.setReturnValue(false, 1); 991 md.supportsSavepoints(); 992 mdControl.setReturnValue(true, 1); 993 con.getMetaData(); 994 conControl.setReturnValue(md, 1); 995 con.setSavepoint(); 996 conControl.setReturnValue(sp, 1); 997 con.releaseSavepoint(sp); 998 conControl.setVoidCallable(1); 999 con.commit(); 1000 conControl.setVoidCallable(1); 1001 con.isReadOnly(); 1002 conControl.setReturnValue(false, 1); 1003 con.close(); 1004 conControl.setVoidCallable(1); 1005 ds.getConnection(); 1006 dsControl.setReturnValue(con, 1); 1007 1008 spControl.replay(); 1009 mdControl.replay(); 1010 conControl.replay(); 1011 dsControl.replay(); 1012 1013 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 1014 final TransactionTemplate tt = new TransactionTemplate(tm); 1015 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); 1016 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1017 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 1018 1019 tt.execute(new TransactionCallbackWithoutResult() { 1020 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 1021 assertTrue("Is new transaction", status.isNewTransaction()); 1022 assertTrue("Isn't nested transaction", !status.hasSavepoint()); 1023 tt.execute(new TransactionCallbackWithoutResult() { 1024 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 1025 assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); 1026 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive()); 1027 assertTrue("Isn't new transaction", !status.isNewTransaction()); 1028 assertTrue("Is nested transaction", status.hasSavepoint()); 1029 } 1030 }); 1031 assertTrue("Is new transaction", status.isNewTransaction()); 1032 assertTrue("Isn't nested transaction", !status.hasSavepoint()); 1033 } 1034 }); 1035 1036 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1037 spControl.verify(); 1038 mdControl.verify(); 1039 conControl.verify(); 1040 dsControl.verify(); 1041 } 1042 1043 public void testExistingTransactionWithPropagationNestedAndRollback() throws Exception { 1044 if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_14) { 1045 return; 1046 } 1047 1048 MockControl dsControl = MockControl.createControl(DataSource .class); 1049 final DataSource ds = (DataSource ) dsControl.getMock(); 1050 MockControl conControl = MockControl.createControl(Connection .class); 1051 Connection con = (Connection ) conControl.getMock(); 1052 MockControl mdControl = MockControl.createControl(DatabaseMetaData .class); 1053 DatabaseMetaData md = (DatabaseMetaData ) mdControl.getMock(); 1054 MockControl spControl = MockControl.createControl(Savepoint .class); 1055 Savepoint sp = (Savepoint ) spControl.getMock(); 1056 1057 ds.getConnection(); 1058 dsControl.setReturnValue(con, 1); 1059 con.getAutoCommit(); 1060 conControl.setReturnValue(false, 1); 1061 md.supportsSavepoints(); 1062 mdControl.setReturnValue(true, 1); 1063 con.getMetaData(); 1064 conControl.setReturnValue(md, 1); 1065 con.setSavepoint(); 1066 conControl.setReturnValue(sp, 1); 1067 con.rollback(sp); 1068 conControl.setVoidCallable(1); 1069 con.commit(); 1070 conControl.setVoidCallable(1); 1071 con.isReadOnly(); 1072 conControl.setReturnValue(false, 1); 1073 con.close(); 1074 conControl.setVoidCallable(1); 1075 1076 spControl.replay(); 1077 mdControl.replay(); 1078 conControl.replay(); 1079 dsControl.replay(); 1080 1081 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 1082 final TransactionTemplate tt = new TransactionTemplate(tm); 1083 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); 1084 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1085 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 1086 1087 tt.execute(new TransactionCallbackWithoutResult() { 1088 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 1089 assertTrue("Is new transaction", status.isNewTransaction()); 1090 assertTrue("Isn't nested transaction", !status.hasSavepoint()); 1091 tt.execute(new TransactionCallbackWithoutResult() { 1092 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 1093 assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds)); 1094 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive()); 1095 assertTrue("Isn't new transaction", !status.isNewTransaction()); 1096 assertTrue("Is nested transaction", status.hasSavepoint()); 1097 status.setRollbackOnly(); 1098 } 1099 }); 1100 assertTrue("Is new transaction", status.isNewTransaction()); 1101 assertTrue("Isn't nested transaction", !status.hasSavepoint()); 1102 } 1103 }); 1104 1105 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1106 spControl.verify(); 1107 mdControl.verify(); 1108 conControl.verify(); 1109 dsControl.verify(); 1110 } 1111 1112 public void testExistingTransactionWithManualSavepoint() throws Exception { 1113 if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_14) { 1114 return; 1115 } 1116 1117 MockControl dsControl = MockControl.createControl(DataSource .class); 1118 final DataSource ds = (DataSource ) dsControl.getMock(); 1119 MockControl conControl = MockControl.createControl(Connection .class); 1120 Connection con = (Connection ) conControl.getMock(); 1121 MockControl mdControl = MockControl.createControl(DatabaseMetaData .class); 1122 DatabaseMetaData md = (DatabaseMetaData ) mdControl.getMock(); 1123 MockControl spControl = MockControl.createControl(Savepoint .class); 1124 Savepoint sp = (Savepoint ) spControl.getMock(); 1125 1126 con.getAutoCommit(); 1127 conControl.setReturnValue(false, 1); 1128 md.supportsSavepoints(); 1129 mdControl.setReturnValue(true, 1); 1130 con.getMetaData(); 1131 conControl.setReturnValue(md, 1); 1132 con.setSavepoint(); 1133 conControl.setReturnValue(sp, 1); 1134 con.releaseSavepoint(sp); 1135 conControl.setVoidCallable(1); 1136 con.commit(); 1137 conControl.setVoidCallable(1); 1138 con.isReadOnly(); 1139 conControl.setReturnValue(false, 1); 1140 con.close(); 1141 conControl.setVoidCallable(1); 1142 ds.getConnection(); 1143 dsControl.setReturnValue(con, 1); 1144 1145 spControl.replay(); 1146 mdControl.replay(); 1147 conControl.replay(); 1148 dsControl.replay(); 1149 1150 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 1151 final TransactionTemplate tt = new TransactionTemplate(tm); 1152 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); 1153 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1154 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 1155 1156 tt.execute(new TransactionCallbackWithoutResult() { 1157 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 1158 assertTrue("Is new transaction", status.isNewTransaction()); 1159 Object savepoint = status.createSavepoint(); 1160 status.releaseSavepoint(savepoint); 1161 assertTrue("Is new transaction", status.isNewTransaction()); 1162 } 1163 }); 1164 1165 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1166 spControl.verify(); 1167 mdControl.verify(); 1168 conControl.verify(); 1169 dsControl.verify(); 1170 } 1171 1172 public void testExistingTransactionWithManualSavepointAndRollback() throws Exception { 1173 if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_14) { 1174 return; 1175 } 1176 1177 MockControl dsControl = MockControl.createControl(DataSource .class); 1178 final DataSource ds = (DataSource ) dsControl.getMock(); 1179 MockControl conControl = MockControl.createControl(Connection .class); 1180 Connection con = (Connection ) conControl.getMock(); 1181 MockControl mdControl = MockControl.createControl(DatabaseMetaData .class); 1182 DatabaseMetaData md = (DatabaseMetaData ) mdControl.getMock(); 1183 MockControl spControl = MockControl.createControl(Savepoint .class); 1184 Savepoint sp = (Savepoint ) spControl.getMock(); 1185 1186 ds.getConnection(); 1187 dsControl.setReturnValue(con, 1); 1188 con.getAutoCommit(); 1189 conControl.setReturnValue(false, 1); 1190 md.supportsSavepoints(); 1191 mdControl.setReturnValue(true, 1); 1192 con.getMetaData(); 1193 conControl.setReturnValue(md, 1); 1194 con.setSavepoint(); 1195 conControl.setReturnValue(sp, 1); 1196 con.rollback(sp); 1197 conControl.setVoidCallable(1); 1198 con.commit(); 1199 conControl.setVoidCallable(1); 1200 con.isReadOnly(); 1201 conControl.setReturnValue(false, 1); 1202 con.close(); 1203 conControl.setVoidCallable(1); 1204 1205 spControl.replay(); 1206 mdControl.replay(); 1207 conControl.replay(); 1208 dsControl.replay(); 1209 1210 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 1211 final TransactionTemplate tt = new TransactionTemplate(tm); 1212 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); 1213 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1214 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 1215 1216 tt.execute(new TransactionCallbackWithoutResult() { 1217 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 1218 assertTrue("Is new transaction", status.isNewTransaction()); 1219 Object savepoint = status.createSavepoint(); 1220 status.rollbackToSavepoint(savepoint); 1221 assertTrue("Is new transaction", status.isNewTransaction()); 1222 } 1223 }); 1224 1225 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1226 spControl.verify(); 1227 mdControl.verify(); 1228 conControl.verify(); 1229 dsControl.verify(); 1230 } 1231 1232 public void testTransactionWithPropagationNested() throws Exception { 1233 MockControl conControl = MockControl.createControl(Connection .class); 1234 Connection con = (Connection ) conControl.getMock(); 1235 con.getAutoCommit(); 1236 conControl.setReturnValue(false, 1); 1237 con.commit(); 1238 conControl.setVoidCallable(1); 1239 con.isReadOnly(); 1240 conControl.setReturnValue(false, 1); 1241 con.close(); 1242 conControl.setVoidCallable(1); 1243 1244 MockControl dsControl = MockControl.createControl(DataSource .class); 1245 final DataSource ds = (DataSource ) dsControl.getMock(); 1246 ds.getConnection(); 1247 dsControl.setReturnValue(con, 1); 1248 conControl.replay(); 1249 dsControl.replay(); 1250 1251 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 1252 final TransactionTemplate tt = new TransactionTemplate(tm); 1253 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); 1254 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1255 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 1256 1257 tt.execute(new TransactionCallbackWithoutResult() { 1258 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 1259 assertTrue("Is new transaction", status.isNewTransaction()); 1260 } 1261 }); 1262 1263 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1264 conControl.verify(); 1265 dsControl.verify(); 1266 } 1267 1268 public void testTransactionWithPropagationNestedAndRollback() throws Exception { 1269 MockControl conControl = MockControl.createControl(Connection .class); 1270 Connection con = (Connection ) conControl.getMock(); 1271 con.getAutoCommit(); 1272 conControl.setReturnValue(false, 1); 1273 con.rollback(); 1274 conControl.setVoidCallable(1); 1275 con.isReadOnly(); 1276 conControl.setReturnValue(false, 1); 1277 con.close(); 1278 conControl.setVoidCallable(1); 1279 1280 MockControl dsControl = MockControl.createControl(DataSource .class); 1281 final DataSource ds = (DataSource ) dsControl.getMock(); 1282 ds.getConnection(); 1283 dsControl.setReturnValue(con, 1); 1284 conControl.replay(); 1285 dsControl.replay(); 1286 1287 PlatformTransactionManager tm = new DataSourceTransactionManager(ds); 1288 final TransactionTemplate tt = new TransactionTemplate(tm); 1289 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); 1290 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1291 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 1292 1293 tt.execute(new TransactionCallbackWithoutResult() { 1294 protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException { 1295 assertTrue("Is new transaction", status.isNewTransaction()); 1296 status.setRollbackOnly(); 1297 } 1298 }); 1299 1300 assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); 1301 conControl.verify(); 1302 dsControl.verify(); 1303 } 1304 1305 protected void tearDown() { 1306 assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty()); 1307 assertFalse(TransactionSynchronizationManager.isSynchronizationActive()); 1308 assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly()); 1309 assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); 1310 } 1311 1312} 1313 | Popular Tags |