| 1 16 17 package org.springframework.orm.hibernate3; 18 19 import java.util.ArrayList ; 20 import java.util.List ; 21 22 import javax.transaction.RollbackException ; 23 import javax.transaction.Status ; 24 import javax.transaction.Synchronization ; 25 import javax.transaction.TransactionManager ; 26 import javax.transaction.UserTransaction ; 27 28 import junit.framework.TestCase; 29 import org.easymock.MockControl; 30 import org.hibernate.FlushMode; 31 import org.hibernate.HibernateException; 32 import org.hibernate.Query; 33 import org.hibernate.SessionFactory; 34 import org.hibernate.classic.Session; 35 import org.hibernate.engine.SessionFactoryImplementor; 36 import org.hibernate.engine.SessionImplementor; 37 38 import org.springframework.dao.DataAccessException; 39 import org.springframework.transaction.MockJtaTransaction; 40 import org.springframework.transaction.TransactionDefinition; 41 import org.springframework.transaction.TransactionStatus; 42 import org.springframework.transaction.UnexpectedRollbackException; 43 import org.springframework.transaction.jta.JtaTransactionManager; 44 import org.springframework.transaction.support.TransactionCallback; 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 HibernateJtaTransactionTests extends TestCase { 54 55 public void testParticipatingJtaTransactionWithWithRequiresNew() throws Exception { 56 MockControl utControl = MockControl.createControl(UserTransaction .class); 57 UserTransaction ut = (UserTransaction ) utControl.getMock(); 58 MockControl tmControl = MockControl.createControl(TransactionManager .class); 59 TransactionManager tm = (TransactionManager ) tmControl.getMock(); 60 MockControl tx1Control = MockControl.createControl(javax.transaction.Transaction .class); 61 javax.transaction.Transaction tx1 = (javax.transaction.Transaction ) tx1Control.getMock(); 62 MockControl sfControl = MockControl.createControl(SessionFactory.class); 63 final SessionFactory sf = (SessionFactory) sfControl.getMock(); 64 MockControl session1Control = MockControl.createControl(Session.class); 65 Session session1 = (Session) session1Control.getMock(); 66 MockControl session2Control = MockControl.createControl(Session.class); 67 Session session2 = (Session) session2Control.getMock(); 68 69 ut.getStatus(); 70 utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1); 71 ut.getStatus(); 72 utControl.setReturnValue(Status.STATUS_ACTIVE, 3); 73 ut.begin(); 74 utControl.setVoidCallable(2); 75 tm.suspend(); 76 tmControl.setReturnValue(tx1, 1); 77 tm.resume(tx1); 78 tmControl.setVoidCallable(1); 79 ut.commit(); 80 utControl.setVoidCallable(2); 81 82 sf.openSession(); 83 sfControl.setReturnValue(session1, 1); 84 sf.openSession(); 85 sfControl.setReturnValue(session2, 1); 86 session1.getSessionFactory(); 87 session1Control.setReturnValue(sf, 1); 88 session2.getSessionFactory(); 89 session2Control.setReturnValue(sf, 1); 90 session1.getFlushMode(); 91 session1Control.setReturnValue(FlushMode.AUTO, 1); 92 session2.getFlushMode(); 93 session2Control.setReturnValue(FlushMode.AUTO, 1); 94 session1.flush(); 95 session1Control.setVoidCallable(1); 96 session2.flush(); 97 session2Control.setVoidCallable(2); 98 session1.close(); 99 session1Control.setReturnValue(null, 1); 100 session2.close(); 101 session2Control.setReturnValue(null, 1); 102 103 utControl.replay(); 104 tmControl.replay(); 105 sfControl.replay(); 106 session1Control.replay(); 107 session2Control.replay(); 108 109 JtaTransactionManager ptm = new JtaTransactionManager(); 110 ptm.setUserTransaction(ut); 111 ptm.setTransactionManager(tm); 112 final TransactionTemplate tt = new TransactionTemplate(ptm); 113 tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); 114 115 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 116 tt.execute(new TransactionCallback() { 117 public Object doInTransaction(TransactionStatus status) { 118 SessionFactoryUtils.getSession(sf, true); 119 final SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf); 120 assertTrue("Has thread session", holder != null); 121 tt.execute(new TransactionCallback() { 122 public Object doInTransaction(TransactionStatus status) { 123 HibernateTemplate ht = new HibernateTemplate(sf); 124 ht.setFlushMode(HibernateTemplate.FLUSH_EAGER); 125 return ht.executeFind(new HibernateCallback() { 126 public Object doInHibernate(org.hibernate.Session session) { 127 assertTrue("Not enclosing session", session != holder.getSession()); 128 return null; 129 } 130 }); 131 } 132 }); 133 assertTrue("Same thread session as before", 134 holder.getSession() == SessionFactoryUtils.getSession(sf, false)); 135 return null; 136 } 137 }); 138 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 139 140 utControl.verify(); 141 tmControl.verify(); 142 sfControl.verify(); 143 session1Control.verify(); 144 session2Control.verify(); 145 } 146 147 public void testJtaTransactionCommit() throws Exception { 148 doTestJtaTransactionCommit(Status.STATUS_NO_TRANSACTION, false); 149 } 150 151 public void testJtaTransactionCommitWithReadOnly() throws Exception { 152 doTestJtaTransactionCommit(Status.STATUS_NO_TRANSACTION, true); 153 } 154 155 public void testJtaTransactionCommitWithExisting() throws Exception { 156 doTestJtaTransactionCommit(Status.STATUS_ACTIVE, false); 157 } 158 159 public void testJtaTransactionCommitWithExistingAndReadOnly() throws Exception { 160 doTestJtaTransactionCommit(Status.STATUS_ACTIVE, true); 161 } 162 163 private void doTestJtaTransactionCommit(int status, final boolean readOnly) throws Exception { 164 MockControl utControl = MockControl.createControl(UserTransaction .class); 165 UserTransaction ut = (UserTransaction ) utControl.getMock(); 166 MockControl sfControl = MockControl.createControl(SessionFactory.class); 167 final SessionFactory sf = (SessionFactory) sfControl.getMock(); 168 final MockControl sessionControl = MockControl.createControl(Session.class); 169 final Session session = (Session) sessionControl.getMock(); 170 final MockControl queryControl = MockControl.createControl(Query.class); 171 Query query = (Query) queryControl.getMock(); 172 173 ut.getStatus(); 174 utControl.setReturnValue(status, 1); 175 if (status == Status.STATUS_NO_TRANSACTION) { 176 ut.begin(); 177 utControl.setVoidCallable(1); 178 ut.getStatus(); 179 utControl.setReturnValue(Status.STATUS_ACTIVE, 1); 180 ut.commit(); 181 utControl.setVoidCallable(1); 182 } 183 184 final List list = new ArrayList (); 185 list.add("test"); 186 sf.openSession(); 187 sfControl.setReturnValue(session, 1); 188 session.getSessionFactory(); 189 sessionControl.setReturnValue(sf, 1); 190 session.createQuery("some query string"); 191 sessionControl.setReturnValue(query, 1); 192 if (readOnly) { 193 session.setFlushMode(FlushMode.NEVER); 194 sessionControl.setVoidCallable(1); 195 } 196 query.list(); 197 queryControl.setReturnValue(list, 1); 198 199 utControl.replay(); 200 sfControl.replay(); 201 sessionControl.replay(); 202 queryControl.replay(); 203 204 JtaTransactionManager ptm = new JtaTransactionManager(ut); 205 TransactionTemplate tt = new TransactionTemplate(ptm); 206 tt.setReadOnly(readOnly); 207 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 208 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 209 210 Object result = tt.execute(new TransactionCallback() { 211 public Object doInTransaction(TransactionStatus status) { 212 try { 213 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive()); 214 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 215 HibernateTemplate ht = new HibernateTemplate(sf); 216 ht.setExposeNativeSession(true); 217 ht.executeFind(new HibernateCallback() { 218 public Object doInHibernate(org.hibernate.Session sess) { 219 assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); 220 assertEquals(session, sess); 221 return null; 222 } 223 }); 224 ht = new HibernateTemplate(sf); 225 List htl = ht.executeFind(new HibernateCallback() { 226 public Object doInHibernate(org.hibernate.Session sess) { 227 assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); 228 return sess.createQuery("some query string").list(); 229 } 230 }); 231 assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); 232 sessionControl.verify(); 233 queryControl.verify(); 234 sessionControl.reset(); 235 try { 236 if (!readOnly) { 237 session.getFlushMode(); 238 sessionControl.setReturnValue(FlushMode.AUTO, 1); 239 session.flush(); 240 sessionControl.setVoidCallable(1); 241 } 242 session.close(); 243 sessionControl.setReturnValue(null, 1); 244 } 245 catch (HibernateException e) { 246 } 247 sessionControl.replay(); 248 return htl; 249 } 250 catch (Error err) { 251 err.printStackTrace(); 252 throw err; 253 } 254 } 255 }); 256 257 assertTrue("Correct result list", result == list); 258 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 259 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 260 261 utControl.verify(); 262 sfControl.verify(); 263 sessionControl.verify(); 264 } 265 266 public void testJtaTransactionCommitWithJtaTm() throws Exception { 267 doTestJtaTransactionCommitWithJtaTm(Status.STATUS_NO_TRANSACTION); 268 } 269 270 public void testJtaTransactionCommitWithJtaTmAndExisting() throws Exception { 271 doTestJtaTransactionCommitWithJtaTm(Status.STATUS_ACTIVE); 272 } 273 274 private void doTestJtaTransactionCommitWithJtaTm(int status) throws Exception { 275 MockControl utControl = MockControl.createControl(UserTransaction .class); 276 UserTransaction ut = (UserTransaction ) utControl.getMock(); 277 ut.getStatus(); 278 utControl.setReturnValue(status, 1); 279 if (status == Status.STATUS_NO_TRANSACTION) { 280 ut.begin(); 281 utControl.setVoidCallable(1); 282 ut.getStatus(); 283 utControl.setReturnValue(Status.STATUS_ACTIVE, 1); 284 ut.commit(); 285 utControl.setVoidCallable(1); 286 } 287 288 MockControl tmControl = MockControl.createControl(TransactionManager .class); 289 TransactionManager tm = (TransactionManager ) tmControl.getMock(); 290 MockJtaTransaction transaction = new MockJtaTransaction(); 291 tm.getStatus(); 292 tmControl.setReturnValue(Status.STATUS_ACTIVE, 6); 293 tm.getTransaction(); 294 tmControl.setReturnValue(transaction, 6); 295 296 MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class); 297 final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock(); 298 final MockControl sessionControl = MockControl.createControl(SessionImplementor.class); 299 final SessionImplementor session = (SessionImplementor) sessionControl.getMock(); 300 sf.getConnectionProvider(); 301 sfControl.setReturnValue(null, 2); 302 sf.getTransactionManager(); 303 sfControl.setReturnValue(tm, 1); 304 sf.openSession(); 305 sfControl.setReturnValue(session, 1); 306 307 utControl.replay(); 308 tmControl.replay(); 309 sfControl.replay(); 310 sessionControl.replay(); 311 312 JtaTransactionManager ptm = new JtaTransactionManager(ut); 313 TransactionTemplate tt = new TransactionTemplate(ptm); 314 final List l = new ArrayList (); 315 l.add("test"); 316 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 317 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 318 319 Object result = tt.execute(new TransactionCallback() { 320 public Object doInTransaction(TransactionStatus status) { 321 try { 322 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive()); 323 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 324 HibernateTemplate ht = new HibernateTemplate(sf); 325 ht.setExposeNativeSession(true); 326 List htl = ht.executeFind(new HibernateCallback() { 327 public Object doInHibernate(org.hibernate.Session sess) { 328 assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); 329 assertEquals(session, sess); 330 return l; 331 } 332 }); 333 ht = new HibernateTemplate(sf); 334 ht.setExposeNativeSession(true); 335 htl = ht.executeFind(new HibernateCallback() { 336 public Object doInHibernate(org.hibernate.Session sess) { 337 assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); 338 assertEquals(session, sess); 339 return l; 340 } 341 }); 342 assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); 343 sessionControl.verify(); 344 sessionControl.reset(); 345 try { 346 session.getFlushMode(); 347 sessionControl.setReturnValue(FlushMode.AUTO, 1); 348 session.flush(); 349 sessionControl.setVoidCallable(1); 350 session.close(); 351 sessionControl.setReturnValue(null, 1); 352 } 353 catch (HibernateException e) { 354 } 355 sessionControl.replay(); 356 return htl; 357 } 358 catch (Error err) { 359 err.printStackTrace(); 360 throw err; 361 } 362 } 363 }); 364 365 assertTrue("Correct result list", result == l); 366 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 367 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 368 369 utControl.verify(); 370 sfControl.verify(); 371 sessionControl.verify(); 372 } 373 374 public void testJtaTransactionWithFlushFailure() throws Exception { 375 MockControl utControl = MockControl.createControl(UserTransaction .class); 376 UserTransaction ut = (UserTransaction ) utControl.getMock(); 377 ut.getStatus(); 378 utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1); 379 ut.begin(); 380 utControl.setVoidCallable(1); 381 ut.rollback(); 382 utControl.setVoidCallable(1); 383 utControl.replay(); 384 385 MockControl sfControl = MockControl.createControl(SessionFactory.class); 386 final SessionFactory sf = (SessionFactory) sfControl.getMock(); 387 final MockControl sessionControl = MockControl.createControl(Session.class); 388 final Session session = (Session) sessionControl.getMock(); 389 sf.openSession(); 390 sfControl.setReturnValue(session, 1); 391 session.getSessionFactory(); 392 sessionControl.setReturnValue(sf, 1); 393 sfControl.replay(); 394 sessionControl.replay(); 395 396 JtaTransactionManager ptm = new JtaTransactionManager(ut); 397 TransactionTemplate tt = new TransactionTemplate(ptm); 398 final List l = new ArrayList (); 399 l.add("test"); 400 final HibernateException flushEx = new HibernateException("flush failure"); 401 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 402 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 403 404 try { 405 tt.execute(new TransactionCallback() { 406 public Object doInTransaction(TransactionStatus status) { 407 try { 408 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive()); 409 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 410 HibernateTemplate ht = new HibernateTemplate(sf); 411 ht.setExposeNativeSession(true); 412 List htl = ht.executeFind(new HibernateCallback() { 413 public Object doInHibernate(org.hibernate.Session sess) { 414 assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); 415 assertEquals(session, sess); 416 return l; 417 } 418 }); 419 ht = new HibernateTemplate(sf); 420 ht.setExposeNativeSession(true); 421 htl = ht.executeFind(new HibernateCallback() { 422 public Object doInHibernate(org.hibernate.Session sess) { 423 assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); 424 assertEquals(session, sess); 425 return l; 426 } 427 }); 428 assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf)); 429 sessionControl.verify(); 430 sessionControl.reset(); 431 try { 432 session.getFlushMode(); 433 sessionControl.setReturnValue(FlushMode.AUTO, 1); 434 session.flush(); 435 sessionControl.setThrowable(flushEx); 436 session.close(); 437 sessionControl.setReturnValue(null, 1); 438 } 439 catch (HibernateException e) { 440 } 441 sessionControl.replay(); 442 return htl; 443 } 444 catch (Error err) { 445 err.printStackTrace(); 446 throw err; 447 } 448 } 449 }); 450 } 451 catch (DataAccessException ex) { 452 assertTrue(flushEx == ex.getCause()); 454 } 455 456 assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf)); 457 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 458 459 utControl.verify(); 460 sfControl.verify(); 461 sessionControl.verify(); 462 } 463 464 public void testJtaTransactionRollback() throws Exception { 465 MockControl utControl = MockControl.createControl(UserTransaction .class); 466 UserTransaction ut = (UserTransaction ) utControl.getMock(); 467 ut.getStatus(); 468 utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1); 469 ut.begin(); 470 utControl.setVoidCallable(1); 471 ut.rollback(); 472 utControl.setVoidCallable(1); 473 utControl.replay(); 474 475 MockControl sfControl = MockControl.createControl(SessionFactory.class); 476 final SessionFactory sf = (SessionFactory) sfControl.getMock(); 477 final MockControl sessionControl = MockControl.createControl(Session.class); 478 final Session session = (Session) sessionControl.getMock(); 479 sf.openSession(); 480 sfControl.setReturnValue(session, 1); 481 session.getSessionFactory(); 482 sessionControl.setReturnValue(sf, 1); 483 sfControl.replay(); 484 sessionControl.replay(); 485 486 JtaTransactionManager ptm = new JtaTransactionManager(ut); 487 TransactionTemplate tt = new TransactionTemplate(ptm); 488 final List l = new ArrayList (); 489 l.add("test"); 490 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 491 492 Object result = tt.execute(new TransactionCallback() { 493 public Object doInTransaction(TransactionStatus status) { 494 try { 495 assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive()); 496 HibernateTemplate ht = new HibernateTemplate(sf); 497 List htl = ht.executeFind(new HibernateCallback() { 498 public Object doInHibernate(org.hibernate.Session session) { 499 return l; 500 } 501 }); 502 status.setRollbackOnly(); 503 sessionControl.verify(); 504 sessionControl.reset(); 505 try { 506 session.close(); 507 } 508 catch (HibernateException ex) { 509 } 510 sessionControl.setReturnValue(null, 1); 511 sessionControl.replay(); 512 return htl; 513 } 514 catch (Error err) { 515 err.printStackTrace(); 516 throw err; 517 } 518 } 519 }); 520 assertTrue("Correct result list", result == l); 521 522 assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); 523 utControl.verify(); 524 sfControl.verify(); 525 sessionControl.verify(); 526 } 527 528 public void testJtaTransactionCommitWithPreBound() throws Exception { 529 doTestJtaTransactionCommitWithPreBound(false, false, false); 530 } 531 532 public void testJtaTransactionCommitWithPreBoundAndReadOnly() throws Exception { 533 doTestJtaTransactionCommitWithPreBound(false, false, true); 534 } 535 536 public void testJtaTransactionCommitWithPreBoundAndFlushModeNever() throws Exception { 537 doTestJtaTransactionCommitWithPreBound(false, true, false); 538 } 539 540 public void testJtaTransactionCommitWithPreBoundAndFlushModeNeverAndReadOnly() throws Exception { 541 doTestJtaTransactionCommitWithPreBound(false, true, true); 542 } 543 544 public void testJtaTransactionCommitWithJtaTmAndPreBound() throws Exception { 545 doTestJtaTransactionCommitWithPreBound(true, false, false); 546 } 547 548 public void testJtaTransactionCommitWithJtaTmAndPreBoundAndReadOnly() throws Exception { 549 doTestJtaTransactionCommitWithPreBound(true, false, true); 550 } 551 552 public void testJtaTransactionCommitWithJtaTmAndPreBoundAndFlushModeNever() throws Exception { 553 doTestJtaTransactionCommitWithPreBound(true, true, false); 554 } 555 556 public void testJtaTransactionCommitWithJtaTmAndPreBoundAndFlushModeNeverAndReadOnly() throws Exception { 557 doTestJtaTransactionCommitWithPreBound(true, true, true); 558 } 559 560 protected void doTestJtaTransactionCommitWithPreBound( 561 boolean jtaTm, final boolean flushNever, final boolean readOnly) throws Exception { 562 563 MockControl utControl = MockControl.createControl(UserTransaction .class); 564 UserTransaction ut = (UserTransaction ) utControl.getMock(); 565 ut.getStatus(); 566 utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1); 567 ut.getStatus(); 568 utControl.setReturnValue(Status.STATUS_ACTIVE, 1); 569 ut.begin(); 570 utControl.setVoidCallable(1); 571 ut.commit(); 572 utControl.setVoidCallable(1); 573 574 MockControl tmControl = MockControl.createControl(TransactionManager .class); 575 TransactionManager tm = (TransactionManager ) tmControl.getMock(); 576 if (jtaTm) { 577 MockJtaTransaction transaction = new MockJtaTransaction(); 578 tm.getStatus(); 579 tmControl.setReturnValue(Status.STATUS_ACTIVE, 1); 580 tm.getTransaction(); 581 tmControl.setReturnValue(transaction, 1); 582 } 583 584 MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class); 585 final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock(); 586 final MockControl sessionControl = MockControl.createControl(SessionImplementor.class); 587 final SessionImplementor session = (SessionImplementor) sessionControl.getMock(); 588 sf.getConnectionProvider(); 589 sfControl.setReturnValue(null, 1); 590 sf.getTransactionManager(); 591 sfControl.setReturnValue((jtaTm ? tm : null), 1); 592 session.getFlushMode(); 593 if (flushNever) { 594 sessionControl.setReturnValue(FlushMode.NEVER, 1); 595 if (!readOnly) { 596 session.setFlushMode(FlushMode.AUTO); 597 sessionControl.setVoidCallable(1); 598 } 599 } 600 else { 601 sessionControl.setReturnValue(FlushMode.AUTO, 1); 602 } 603 604 utControl.replay(); 605 tmControl.replay(); 606 sfControl.replay(); 607 sessionControl.replay(); 608 609 TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); 610 try { 611 JtaTransactionManager ptm = new JtaTransactionManager(ut); 612 TransactionTemplate tt = new TransactionTemplate(ptm); 613 tt.setReadOnly(readOnly); 614 final List l = new ArrayList (); 615 l.add("test"); 616  
|