1 /* 2 * Copyright 2002-2008 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.orm.hibernate3; 18 19 import java.lang.reflect.AccessibleObject; 20 import java.lang.reflect.Method; 21 import java.sql.SQLException; 22 23 import junit.framework.TestCase; 24 import org.aopalliance.intercept.Interceptor; 25 import org.aopalliance.intercept.Invocation; 26 import org.aopalliance.intercept.MethodInvocation; 27 import org.easymock.MockControl; 28 import org.hibernate.FlushMode; 29 import org.hibernate.HibernateException; 30 import org.hibernate.SessionFactory; 31 import org.hibernate.classic.Session; 32 import org.hibernate.exception.ConstraintViolationException; 33 34 import org.springframework.beans.factory.BeanFactory; 35 import org.springframework.dao.DataIntegrityViolationException; 36 import org.springframework.transaction.support.TransactionSynchronizationManager; 37 38 /** 39 * @author Juergen Hoeller 40 * @since 05.03.2005 41 */ 42 public class HibernateInterceptorTests extends TestCase { 43 testInterceptorWithNewSession()44 public void testInterceptorWithNewSession() throws HibernateException { 45 MockControl sfControl = MockControl.createControl(SessionFactory.class); 46 SessionFactory sf = (SessionFactory) sfControl.getMock(); 47 MockControl sessionControl = MockControl.createControl(Session.class); 48 Session session = (Session) sessionControl.getMock(); 49 sf.openSession(); 50 sfControl.setReturnValue(session, 1); 51 session.getSessionFactory(); 52 sessionControl.setReturnValue(sf); 53 session.flush(); 54 sessionControl.setVoidCallable(1); 55 session.close(); 56 sessionControl.setReturnValue(null, 1); 57 sfControl.replay(); 58 sessionControl.replay(); 59 60 HibernateInterceptor interceptor = new HibernateInterceptor(); 61 interceptor.setSessionFactory(sf); 62 try { 63 interceptor.invoke(new TestInvocation(sf)); 64 } 65 catch (Throwable t) { 66 fail("Should not have thrown Throwable: " + t.getMessage()); 67 } 68 69 sfControl.verify(); 70 sessionControl.verify(); 71 } 72 testInterceptorWithNewSessionAndFlushNever()73 public void testInterceptorWithNewSessionAndFlushNever() throws HibernateException { 74 MockControl sfControl = MockControl.createControl(SessionFactory.class); 75 SessionFactory sf = (SessionFactory) sfControl.getMock(); 76 MockControl sessionControl = MockControl.createControl(Session.class); 77 Session session = (Session) sessionControl.getMock(); 78 sf.openSession(); 79 sfControl.setReturnValue(session, 1); 80 session.getSessionFactory(); 81 sessionControl.setReturnValue(sf); 82 session.setFlushMode(FlushMode.MANUAL); 83 sessionControl.setVoidCallable(1); 84 session.close(); 85 sessionControl.setReturnValue(null, 1); 86 sfControl.replay(); 87 sessionControl.replay(); 88 89 HibernateInterceptor interceptor = new HibernateInterceptor(); 90 interceptor.setFlushModeName("FLUSH_NEVER"); 91 interceptor.setSessionFactory(sf); 92 try { 93 interceptor.invoke(new TestInvocation(sf)); 94 } 95 catch (Throwable t) { 96 fail("Should not have thrown Throwable: " + t.getMessage()); 97 } 98 99 sfControl.verify(); 100 sessionControl.verify(); 101 } 102 testInterceptorWithNewSessionAndFilter()103 public void testInterceptorWithNewSessionAndFilter() throws HibernateException { 104 MockControl sfControl = MockControl.createControl(SessionFactory.class); 105 SessionFactory sf = (SessionFactory) sfControl.getMock(); 106 MockControl sessionControl = MockControl.createControl(Session.class); 107 Session session = (Session) sessionControl.getMock(); 108 sf.openSession(); 109 sfControl.setReturnValue(session, 1); 110 session.getSessionFactory(); 111 sessionControl.setReturnValue(sf); 112 session.enableFilter("myFilter"); 113 sessionControl.setReturnValue(null, 1); 114 session.flush(); 115 sessionControl.setVoidCallable(1); 116 session.close(); 117 sessionControl.setReturnValue(null, 1); 118 sfControl.replay(); 119 sessionControl.replay(); 120 121 HibernateInterceptor interceptor = new HibernateInterceptor(); 122 interceptor.setSessionFactory(sf); 123 interceptor.setFilterName("myFilter"); 124 try { 125 interceptor.invoke(new TestInvocation(sf)); 126 } 127 catch (Throwable t) { 128 fail("Should not have thrown Throwable: " + t.getMessage()); 129 } 130 131 sfControl.verify(); 132 sessionControl.verify(); 133 } 134 testInterceptorWithThreadBound()135 public void testInterceptorWithThreadBound() { 136 MockControl sfControl = MockControl.createControl(SessionFactory.class); 137 SessionFactory sf = (SessionFactory) sfControl.getMock(); 138 MockControl sessionControl = MockControl.createControl(Session.class); 139 Session session = (Session) sessionControl.getMock(); 140 session.getSessionFactory(); 141 sessionControl.setReturnValue(sf, 1); 142 session.isOpen(); 143 sessionControl.setReturnValue(true, 1); 144 sfControl.replay(); 145 sessionControl.replay(); 146 147 TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); 148 HibernateInterceptor interceptor = new HibernateInterceptor(); 149 interceptor.setSessionFactory(sf); 150 try { 151 interceptor.invoke(new TestInvocation(sf)); 152 } 153 catch (Throwable t) { 154 fail("Should not have thrown Throwable: " + t.getMessage()); 155 } 156 finally { 157 TransactionSynchronizationManager.unbindResource(sf); 158 } 159 160 sfControl.verify(); 161 sessionControl.verify(); 162 } 163 testInterceptorWithThreadBoundAndFlushEager()164 public void testInterceptorWithThreadBoundAndFlushEager() throws HibernateException { 165 MockControl sfControl = MockControl.createControl(SessionFactory.class); 166 SessionFactory sf = (SessionFactory) sfControl.getMock(); 167 MockControl sessionControl = MockControl.createControl(Session.class); 168 Session session = (Session) sessionControl.getMock(); 169 session.getSessionFactory(); 170 sessionControl.setReturnValue(sf, 1); 171 session.isOpen(); 172 sessionControl.setReturnValue(true, 1); 173 session.getFlushMode(); 174 sessionControl.setReturnValue(FlushMode.AUTO, 1); 175 session.flush(); 176 sessionControl.setVoidCallable(1); 177 sfControl.replay(); 178 sessionControl.replay(); 179 180 TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); 181 HibernateInterceptor interceptor = new HibernateInterceptor(); 182 interceptor.setFlushMode(HibernateInterceptor.FLUSH_EAGER); 183 interceptor.setSessionFactory(sf); 184 try { 185 interceptor.invoke(new TestInvocation(sf)); 186 } 187 catch (Throwable t) { 188 fail("Should not have thrown Throwable: " + t.getMessage()); 189 } 190 finally { 191 TransactionSynchronizationManager.unbindResource(sf); 192 } 193 194 sfControl.verify(); 195 sessionControl.verify(); 196 } 197 testInterceptorWithThreadBoundAndFlushEagerSwitch()198 public void testInterceptorWithThreadBoundAndFlushEagerSwitch() throws HibernateException { 199 MockControl sfControl = MockControl.createControl(SessionFactory.class); 200 SessionFactory sf = (SessionFactory) sfControl.getMock(); 201 MockControl sessionControl = MockControl.createControl(Session.class); 202 Session session = (Session) sessionControl.getMock(); 203 session.getSessionFactory(); 204 sessionControl.setReturnValue(sf, 1); 205 session.isOpen(); 206 sessionControl.setReturnValue(true, 1); 207 session.getFlushMode(); 208 sessionControl.setReturnValue(FlushMode.NEVER, 1); 209 session.setFlushMode(FlushMode.AUTO); 210 sessionControl.setVoidCallable(1); 211 session.flush(); 212 sessionControl.setVoidCallable(1); 213 session.setFlushMode(FlushMode.NEVER); 214 sessionControl.setVoidCallable(1); 215 sfControl.replay(); 216 sessionControl.replay(); 217 218 TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); 219 HibernateInterceptor interceptor = new HibernateInterceptor(); 220 interceptor.setFlushMode(HibernateInterceptor.FLUSH_EAGER); 221 interceptor.setSessionFactory(sf); 222 try { 223 interceptor.invoke(new TestInvocation(sf)); 224 } 225 catch (Throwable t) { 226 fail("Should not have thrown Throwable: " + t.getMessage()); 227 } 228 finally { 229 TransactionSynchronizationManager.unbindResource(sf); 230 } 231 232 sfControl.verify(); 233 sessionControl.verify(); 234 } 235 testInterceptorWithThreadBoundAndFlushCommit()236 public void testInterceptorWithThreadBoundAndFlushCommit() { 237 MockControl sfControl = MockControl.createControl(SessionFactory.class); 238 SessionFactory sf = (SessionFactory) sfControl.getMock(); 239 MockControl sessionControl = MockControl.createControl(Session.class); 240 Session session = (Session) sessionControl.getMock(); 241 session.getSessionFactory(); 242 sessionControl.setReturnValue(sf, 1); 243 session.isOpen(); 244 sessionControl.setReturnValue(true, 1); 245 session.getFlushMode(); 246 sessionControl.setReturnValue(FlushMode.AUTO, 1); 247 session.setFlushMode(FlushMode.COMMIT); 248 sessionControl.setVoidCallable(1); 249 session.setFlushMode(FlushMode.AUTO); 250 sessionControl.setVoidCallable(1); 251 sfControl.replay(); 252 sessionControl.replay(); 253 254 TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); 255 HibernateInterceptor interceptor = new HibernateInterceptor(); 256 interceptor.setSessionFactory(sf); 257 interceptor.setFlushMode(HibernateInterceptor.FLUSH_COMMIT); 258 try { 259 interceptor.invoke(new TestInvocation(sf)); 260 } 261 catch (Throwable t) { 262 fail("Should not have thrown Throwable: " + t.getMessage()); 263 } 264 finally { 265 TransactionSynchronizationManager.unbindResource(sf); 266 } 267 268 sfControl.verify(); 269 sessionControl.verify(); 270 } 271 testInterceptorWithThreadBoundAndFlushAlways()272 public void testInterceptorWithThreadBoundAndFlushAlways() { 273 MockControl sfControl = MockControl.createControl(SessionFactory.class); 274 SessionFactory sf = (SessionFactory) sfControl.getMock(); 275 MockControl sessionControl = MockControl.createControl(Session.class); 276 Session session = (Session) sessionControl.getMock(); 277 session.getSessionFactory(); 278 sessionControl.setReturnValue(sf, 1); 279 session.isOpen(); 280 sessionControl.setReturnValue(true, 1); 281 session.getFlushMode(); 282 sessionControl.setReturnValue(FlushMode.AUTO, 1); 283 session.setFlushMode(FlushMode.ALWAYS); 284 sessionControl.setVoidCallable(1); 285 session.setFlushMode(FlushMode.AUTO); 286 sessionControl.setVoidCallable(1); 287 sfControl.replay(); 288 sessionControl.replay(); 289 290 TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); 291 HibernateInterceptor interceptor = new HibernateInterceptor(); 292 interceptor.setSessionFactory(sf); 293 interceptor.setFlushMode(HibernateInterceptor.FLUSH_ALWAYS); 294 try { 295 interceptor.invoke(new TestInvocation(sf)); 296 } 297 catch (Throwable t) { 298 fail("Should not have thrown Throwable: " + t.getMessage()); 299 } 300 finally { 301 TransactionSynchronizationManager.unbindResource(sf); 302 } 303 304 sfControl.verify(); 305 sessionControl.verify(); 306 } 307 testInterceptorWithThreadBoundAndFilter()308 public void testInterceptorWithThreadBoundAndFilter() { 309 MockControl sfControl = MockControl.createControl(SessionFactory.class); 310 SessionFactory sf = (SessionFactory) sfControl.getMock(); 311 MockControl sessionControl = MockControl.createControl(Session.class); 312 Session session = (Session) sessionControl.getMock(); 313 session.getSessionFactory(); 314 sessionControl.setReturnValue(sf, 1); 315 session.isOpen(); 316 sessionControl.setReturnValue(true, 1); 317 session.enableFilter("myFilter"); 318 sessionControl.setReturnValue(null, 1); 319 session.disableFilter("myFilter"); 320 sessionControl.setVoidCallable(1); 321 sfControl.replay(); 322 sessionControl.replay(); 323 324 TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); 325 HibernateInterceptor interceptor = new HibernateInterceptor(); 326 interceptor.setSessionFactory(sf); 327 interceptor.setFilterName("myFilter"); 328 try { 329 interceptor.invoke(new TestInvocation(sf)); 330 } 331 catch (Throwable t) { 332 fail("Should not have thrown Throwable: " + t.getMessage()); 333 } 334 finally { 335 TransactionSynchronizationManager.unbindResource(sf); 336 } 337 338 sfControl.verify(); 339 sessionControl.verify(); 340 } 341 testInterceptorWithThreadBoundAndFilters()342 public void testInterceptorWithThreadBoundAndFilters() { 343 MockControl sfControl = MockControl.createControl(SessionFactory.class); 344 SessionFactory sf = (SessionFactory) sfControl.getMock(); 345 MockControl sessionControl = MockControl.createControl(Session.class); 346 Session session = (Session) sessionControl.getMock(); 347 session.getSessionFactory(); 348 sessionControl.setReturnValue(sf, 1); 349 session.isOpen(); 350 sessionControl.setReturnValue(true, 1); 351 session.enableFilter("myFilter"); 352 sessionControl.setReturnValue(null, 1); 353 session.enableFilter("yourFilter"); 354 sessionControl.setReturnValue(null, 1); 355 session.disableFilter("myFilter"); 356 sessionControl.setVoidCallable(1); 357 session.disableFilter("yourFilter"); 358 sessionControl.setVoidCallable(1); 359 sfControl.replay(); 360 sessionControl.replay(); 361 362 TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); 363 HibernateInterceptor interceptor = new HibernateInterceptor(); 364 interceptor.setSessionFactory(sf); 365 interceptor.setFilterNames(new String[] {"myFilter", "yourFilter"}); 366 try { 367 interceptor.invoke(new TestInvocation(sf)); 368 } 369 catch (Throwable t) { 370 fail("Should not have thrown Throwable: " + t.getMessage()); 371 } 372 finally { 373 TransactionSynchronizationManager.unbindResource(sf); 374 } 375 376 sfControl.verify(); 377 sessionControl.verify(); 378 } 379 testInterceptorWithFlushFailure()380 public void testInterceptorWithFlushFailure() throws Throwable { 381 MockControl sfControl = MockControl.createControl(SessionFactory.class); 382 SessionFactory sf = (SessionFactory) sfControl.getMock(); 383 MockControl sessionControl = MockControl.createControl(Session.class); 384 Session session = (Session) sessionControl.getMock(); 385 sf.openSession(); 386 sfControl.setReturnValue(session, 1); 387 session.getSessionFactory(); 388 sessionControl.setReturnValue(sf, 1); 389 SQLException sqlEx = new SQLException("argh", "27"); 390 session.flush(); 391 ConstraintViolationException jdbcEx = new ConstraintViolationException("", sqlEx, null); 392 sessionControl.setThrowable(jdbcEx, 1); 393 session.close(); 394 sessionControl.setReturnValue(null, 1); 395 sfControl.replay(); 396 sessionControl.replay(); 397 398 HibernateInterceptor interceptor = new HibernateInterceptor(); 399 interceptor.setSessionFactory(sf); 400 try { 401 interceptor.invoke(new TestInvocation(sf)); 402 fail("Should have thrown DataIntegrityViolationException"); 403 } 404 catch (DataIntegrityViolationException ex) { 405 // expected 406 assertEquals(jdbcEx, ex.getCause()); 407 } 408 409 sfControl.verify(); 410 sessionControl.verify(); 411 } 412 testInterceptorWithThreadBoundEmptyHolder()413 public void testInterceptorWithThreadBoundEmptyHolder() { 414 MockControl sfControl = MockControl.createControl(SessionFactory.class); 415 SessionFactory sf = (SessionFactory) sfControl.getMock(); 416 MockControl sessionControl = MockControl.createControl(Session.class); 417 Session session = (Session) sessionControl.getMock(); 418 sf.openSession(); 419 sfControl.setReturnValue(session, 1); 420 session.getSessionFactory(); 421 sessionControl.setReturnValue(sf, 1); 422 session.flush(); 423 sessionControl.setVoidCallable(1); 424 session.close(); 425 sessionControl.setReturnValue(null, 1); 426 sfControl.replay(); 427 sessionControl.replay(); 428 429 SessionHolder holder = new SessionHolder("key", session); 430 holder.removeSession("key"); 431 TransactionSynchronizationManager.bindResource(sf, holder); 432 HibernateInterceptor interceptor = new HibernateInterceptor(); 433 interceptor.setSessionFactory(sf); 434 try { 435 interceptor.invoke(new TestInvocation(sf)); 436 } 437 catch (Throwable t) { 438 fail("Should not have thrown Throwable: " + t.getMessage()); 439 } 440 441 sfControl.verify(); 442 sessionControl.verify(); 443 } 444 testInterceptorWithEntityInterceptor()445 public void testInterceptorWithEntityInterceptor() throws HibernateException { 446 MockControl interceptorControl = MockControl.createControl(org.hibernate.Interceptor.class); 447 org.hibernate.Interceptor entityInterceptor = (org.hibernate.Interceptor) interceptorControl.getMock(); 448 interceptorControl.replay(); 449 MockControl sfControl = MockControl.createControl(SessionFactory.class); 450 SessionFactory sf = (SessionFactory) sfControl.getMock(); 451 MockControl sessionControl = MockControl.createControl(Session.class); 452 Session session = (Session) sessionControl.getMock(); 453 sf.openSession(entityInterceptor); 454 sfControl.setReturnValue(session, 1); 455 session.getSessionFactory(); 456 sessionControl.setReturnValue(sf, 1); 457 session.flush(); 458 sessionControl.setVoidCallable(1); 459 session.close(); 460 sessionControl.setReturnValue(null, 1); 461 sfControl.replay(); 462 sessionControl.replay(); 463 464 HibernateInterceptor interceptor = new HibernateInterceptor(); 465 interceptor.setSessionFactory(sf); 466 interceptor.setEntityInterceptor(entityInterceptor); 467 try { 468 interceptor.invoke(new TestInvocation(sf)); 469 } 470 catch (Throwable t) { 471 fail("Should not have thrown Throwable: " + t.getMessage()); 472 } 473 474 interceptorControl.verify(); 475 sfControl.verify(); 476 sessionControl.verify(); 477 } 478 testInterceptorWithEntityInterceptorBeanName()479 public void testInterceptorWithEntityInterceptorBeanName() throws HibernateException { 480 MockControl interceptorControl = MockControl.createControl(org.hibernate.Interceptor.class); 481 org.hibernate.Interceptor entityInterceptor = (org.hibernate.Interceptor) interceptorControl.getMock(); 482 interceptorControl.replay(); 483 MockControl interceptor2Control = MockControl.createControl(org.hibernate.Interceptor.class); 484 org.hibernate.Interceptor entityInterceptor2 = (org.hibernate.Interceptor) interceptor2Control.getMock(); 485 interceptor2Control.replay(); 486 487 MockControl sfControl = MockControl.createControl(SessionFactory.class); 488 SessionFactory sf = (SessionFactory) sfControl.getMock(); 489 MockControl sessionControl = MockControl.createControl(Session.class); 490 Session session = (Session) sessionControl.getMock(); 491 sf.openSession(entityInterceptor); 492 sfControl.setReturnValue(session, 1); 493 sf.openSession(entityInterceptor2); 494 sfControl.setReturnValue(session, 1); 495 session.getSessionFactory(); 496 sessionControl.setReturnValue(sf, 2); 497 session.flush(); 498 sessionControl.setVoidCallable(2); 499 session.close(); 500 sessionControl.setReturnValue(null, 2); 501 sfControl.replay(); 502 sessionControl.replay(); 503 504 MockControl beanFactoryControl = MockControl.createControl(BeanFactory.class); 505 BeanFactory beanFactory = (BeanFactory) beanFactoryControl.getMock(); 506 beanFactory.getBean("entityInterceptor", org.hibernate.Interceptor.class); 507 beanFactoryControl.setReturnValue(entityInterceptor, 1); 508 beanFactory.getBean("entityInterceptor", org.hibernate.Interceptor.class); 509 beanFactoryControl.setReturnValue(entityInterceptor2, 1); 510 beanFactoryControl.replay(); 511 512 HibernateInterceptor interceptor = new HibernateInterceptor(); 513 interceptor.setSessionFactory(sf); 514 interceptor.setEntityInterceptorBeanName("entityInterceptor"); 515 interceptor.setBeanFactory(beanFactory); 516 for (int i = 0; i < 2; i++) { 517 try { 518 interceptor.invoke(new TestInvocation(sf)); 519 } 520 catch (Throwable t) { 521 fail("Should not have thrown Throwable: " + t.getMessage()); 522 } 523 } 524 525 interceptorControl.verify(); 526 interceptor2Control.verify(); 527 sfControl.verify(); 528 sessionControl.verify(); 529 } 530 tearDown()531 protected void tearDown() { 532 assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty()); 533 assertFalse(TransactionSynchronizationManager.isSynchronizationActive()); 534 } 535 536 537 private static class TestInvocation implements MethodInvocation { 538 539 private SessionFactory sessionFactory; 540 TestInvocation(SessionFactory sessionFactory)541 public TestInvocation(SessionFactory sessionFactory) { 542 this.sessionFactory = sessionFactory; 543 } 544 proceed()545 public Object proceed() throws Throwable { 546 if (!TransactionSynchronizationManager.hasResource(this.sessionFactory)) { 547 throw new IllegalStateException("Session not bound"); 548 } 549 return null; 550 } 551 getCurrentInterceptorIndex()552 public int getCurrentInterceptorIndex() { 553 return 0; 554 } 555 getNumberOfInterceptors()556 public int getNumberOfInterceptors() { 557 return 0; 558 } 559 getInterceptor(int i)560 public Interceptor getInterceptor(int i) { 561 return null; 562 } 563 getMethod()564 public Method getMethod() { 565 return null; 566 } 567 getStaticPart()568 public AccessibleObject getStaticPart() { 569 return null; 570 } 571 getArgument(int i)572 public Object getArgument(int i) { 573 return null; 574 } 575 getArguments()576 public Object[] getArguments() { 577 return null; 578 } 579 setArgument(int i, Object handler)580 public void setArgument(int i, Object handler) { 581 } 582 getArgumentCount()583 public int getArgumentCount() { 584 return 0; 585 } 586 getThis()587 public Object getThis() { 588 return null; 589 } 590 getProxy()591 public Object getProxy() { 592 return null; 593 } 594 cloneInstance()595 public Invocation cloneInstance() { 596 return null; 597 } 598 release()599 public void release() { 600 } 601 } 602 603 } 604