/** Simulate a transaction infrastructure failure. Shouldn't invoke target method. */
  public void testCannotCreateTransaction() throws Exception {
    TransactionAttribute txatt = new DefaultTransactionAttribute();

    Method m = getNameMethod;
    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(m, txatt);

    MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
    PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
    // Expect a transaction
    ptm.getTransaction(txatt);
    CannotCreateTransactionException ex = new CannotCreateTransactionException("foobar", null);
    ptmControl.setThrowable(ex);
    ptmControl.replay();

    TestBean tb =
        new TestBean() {
          public String getName() {
            throw new UnsupportedOperationException(
                "Shouldn't have invoked target method when couldn't create transaction for transactional method");
          }
        };
    ITestBean itb = (ITestBean) advised(tb, ptm, tas);

    try {
      itb.getName();
      fail("Shouldn't have invoked method");
    } catch (CannotCreateTransactionException thrown) {
      assertTrue(thrown == ex);
    }
    ptmControl.verify();
  }
  /** Test that TransactionStatus.setRollbackOnly works. */
  public void testProgrammaticRollback() throws Exception {
    TransactionAttribute txatt = new DefaultTransactionAttribute();

    Method m = getNameMethod;
    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(m, txatt);

    TransactionStatus status = transactionStatusForNewTransaction();
    MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
    PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();

    ptm.getTransaction(txatt);
    ptmControl.setReturnValue(status, 1);
    ptm.commit(status);
    ptmControl.setVoidCallable(1);
    ptmControl.replay();

    final String name = "jenny";
    TestBean tb =
        new TestBean() {
          public String getName() {
            TransactionStatus txStatus = TransactionInterceptor.currentTransactionStatus();
            txStatus.setRollbackOnly();
            return name;
          }
        };

    ITestBean itb = (ITestBean) advised(tb, ptm, tas);

    // verification!?
    assertTrue(name.equals(itb.getName()));

    ptmControl.verify();
  }
  /** Check that a transaction is created and committed. */
  public void testTransactionShouldSucceed() throws Exception {
    TransactionAttribute txatt = new DefaultTransactionAttribute();

    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(getNameMethod, txatt);

    TransactionStatus status = transactionStatusForNewTransaction();
    MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
    PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
    // expect a transaction
    ptm.getTransaction(txatt);
    ptmControl.setReturnValue(status, 1);
    ptm.commit(status);
    ptmControl.setVoidCallable(1);
    ptmControl.replay();

    TestBean tb = new TestBean();
    ITestBean itb = (ITestBean) advised(tb, ptm, tas);

    checkTransactionStatus(false);
    itb.getName();
    checkTransactionStatus(false);

    ptmControl.verify();
  }
  /**
   * Simulate failure of the underlying transaction infrastructure to commit. Check that the target
   * method was invoked, but that the transaction infrastructure exception was thrown to the client
   */
  public void testCannotCommitTransaction() throws Exception {
    TransactionAttribute txatt = new DefaultTransactionAttribute();

    Method m = setNameMethod;
    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(m, txatt);
    Method m2 = getNameMethod;
    // No attributes for m2

    MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
    PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();

    TransactionStatus status = transactionStatusForNewTransaction();
    ptm.getTransaction(txatt);
    ptmControl.setReturnValue(status);
    UnexpectedRollbackException ex = new UnexpectedRollbackException("foobar", null);
    ptm.commit(status);
    ptmControl.setThrowable(ex);
    ptmControl.replay();

    TestBean tb = new TestBean();
    ITestBean itb = (ITestBean) advised(tb, ptm, tas);

    String name = "new name";
    try {
      itb.setName(name);
      fail("Shouldn't have succeeded");
    } catch (UnexpectedRollbackException thrown) {
      assertTrue(thrown == ex);
    }

    // Should have invoked target and changed name
    assertTrue(itb.getName() == name);
    ptmControl.verify();
  }
 public void testAdrian() {
   ITestBean adrian = (ITestBean) applicationContext.getBean("adrian");
   assertEquals(0, LazyTestBean.instantiations);
   assertNotNull(adrian);
   adrian.getAge();
   assertEquals(68, adrian.getAge());
   assertEquals(1, LazyTestBean.instantiations);
 }
  /**
   * Check that the given exception thrown by the target can produce the desired behavior with the
   * appropriate transaction attribute.
   *
   * @param ex exception to be thrown by the target
   * @param shouldRollback whether this should cause a transaction rollback
   */
  protected void doTestRollbackOnException(
      final Exception ex, final boolean shouldRollback, boolean rollbackException)
      throws Exception {

    TransactionAttribute txatt =
        new DefaultTransactionAttribute() {
          public boolean rollbackOn(Throwable t) {
            assertTrue(t == ex);
            return shouldRollback;
          }
        };

    Method m = exceptionalMethod;
    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(m, txatt);

    MockControl statusControl = MockControl.createControl(TransactionStatus.class);
    TransactionStatus status = (TransactionStatus) statusControl.getMock();
    MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
    PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
    // Gets additional call(s) from TransactionControl

    ptm.getTransaction(txatt);
    ptmControl.setReturnValue(status, 1);

    if (shouldRollback) {
      ptm.rollback(status);
    } else {
      ptm.commit(status);
    }
    TransactionSystemException tex = new TransactionSystemException("system exception");
    if (rollbackException) {
      ptmControl.setThrowable(tex, 1);
    } else {
      ptmControl.setVoidCallable(1);
    }
    ptmControl.replay();

    TestBean tb = new TestBean();
    ITestBean itb = (ITestBean) advised(tb, ptm, tas);

    try {
      itb.exceptional(ex);
      fail("Should have thrown exception");
    } catch (Throwable t) {
      if (rollbackException) {
        assertEquals("Caught wrong exception", tex, t);
      } else {
        assertEquals("Caught wrong exception", ex, t);
      }
    }

    ptmControl.verify();
  }
  @Test
  public void testBeanNameAutoProxyCreator() {
    StaticApplicationContext sac = new StaticApplicationContext();
    sac.registerSingleton("testInterceptor", TestInterceptor.class);

    RootBeanDefinition proxyCreator = new RootBeanDefinition(BeanNameAutoProxyCreator.class);
    proxyCreator.getPropertyValues().add("interceptorNames", "testInterceptor");
    proxyCreator
        .getPropertyValues()
        .add("beanNames", "singletonToBeProxied,innerBean,singletonFactoryToBeProxied");
    sac.getDefaultListableBeanFactory()
        .registerBeanDefinition("beanNameAutoProxyCreator", proxyCreator);

    RootBeanDefinition bd =
        new RootBeanDefinition(TestBean.class, RootBeanDefinition.AUTOWIRE_BY_TYPE);
    RootBeanDefinition innerBean = new RootBeanDefinition(TestBean.class);
    bd.getPropertyValues().add("spouse", new BeanDefinitionHolder(innerBean, "innerBean"));
    sac.getDefaultListableBeanFactory().registerBeanDefinition("singletonToBeProxied", bd);

    sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
    sac.registerSingleton("autowiredIndexedTestBean", IndexedTestBean.class);

    sac.refresh();

    MessageSource messageSource = (MessageSource) sac.getBean("messageSource");
    ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
    assertFalse(Proxy.isProxyClass(messageSource.getClass()));
    assertTrue(Proxy.isProxyClass(singletonToBeProxied.getClass()));
    assertTrue(Proxy.isProxyClass(singletonToBeProxied.getSpouse().getClass()));

    // test whether autowiring succeeded with auto proxy creation
    assertEquals(
        sac.getBean("autowiredIndexedTestBean"), singletonToBeProxied.getNestedIndexedBean());

    TestInterceptor ti = (TestInterceptor) sac.getBean("testInterceptor");
    // already 2: getSpouse + getNestedIndexedBean calls above
    assertEquals(2, ti.nrOfInvocations);
    singletonToBeProxied.getName();
    singletonToBeProxied.getSpouse().getName();
    assertEquals(5, ti.nrOfInvocations);

    ITestBean tb = (ITestBean) sac.getBean("singletonFactoryToBeProxied");
    assertTrue(AopUtils.isJdkDynamicProxy(tb));
    assertEquals(5, ti.nrOfInvocations);
    tb.getAge();
    assertEquals(6, ti.nrOfInvocations);

    ITestBean tb2 = (ITestBean) sac.getBean("singletonFactoryToBeProxied");
    assertSame(tb, tb2);
    assertEquals(6, ti.nrOfInvocations);
    tb2.getAge();
    assertEquals(7, ti.nrOfInvocations);
  }
  public void testEnclosingTransactionWithNonTransactionMethodOnAdvisedInside() throws Throwable {
    TransactionAttribute txatt = new DefaultTransactionAttribute();

    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(exceptionalMethod, txatt);

    TransactionStatus status = transactionStatusForNewTransaction();
    MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
    PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
    // Expect a transaction
    ptm.getTransaction(txatt);
    ptmControl.setReturnValue(status, 1);
    ptm.commit(status);
    ptmControl.setVoidCallable(1);
    ptmControl.replay();

    final String spouseName = "innerName";

    TestBean outer =
        new TestBean() {
          public void exceptional(Throwable t) throws Throwable {
            TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
            assertTrue(ti.hasTransaction());
            assertEquals(spouseName, getSpouse().getName());
          }
        };
    TestBean inner =
        new TestBean() {
          public String getName() {
            // Assert that we're in the inner proxy
            TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
            assertFalse(ti.hasTransaction());
            return spouseName;
          }
        };

    ITestBean outerProxy = (ITestBean) advised(outer, ptm, tas);
    ITestBean innerProxy = (ITestBean) advised(inner, ptm, tas);
    outer.setSpouse(innerProxy);

    checkTransactionStatus(false);

    // Will invoke inner.getName, which is non-transactional
    outerProxy.exceptional(null);

    checkTransactionStatus(false);

    ptmControl.verify();
  }
 @Test
 public void testOneObjectArgBindingProxyWithThis() {
   mockCollaborator.oneObjectArg(this.testBeanProxy);
   replay(mockCollaborator);
   testBeanProxy.getAge();
   verify(mockCollaborator);
 }
 @Test
 public void testNeedsJoinPoint() {
   mockCollaborator.needsJoinPoint("getAge");
   replay(mockCollaborator);
   testBeanProxy.getAge();
   verify(mockCollaborator);
 }
 @Test
 public void testOneIntAndOneObjectArgs() {
   mockCollaborator.oneIntAndOneObject(5, this.testBeanProxy);
   replay(mockCollaborator);
   testBeanProxy.setAge(5);
   verify(mockCollaborator);
 }
 @Test
 public void testOneObjectArgBindingTarget() {
   mockCollaborator.oneObjectArg(this.testBeanTarget);
   replay(mockCollaborator);
   testBeanProxy.getDoctor();
   verify(mockCollaborator);
 }
 @Test
 public void testOneIntArg() {
   mockCollaborator.oneIntArg(5);
   replay(mockCollaborator);
   testBeanProxy.setAge(5);
   verify(mockCollaborator);
 }
  /**
   * Check that a transaction is created and committed using
   * CallbackPreferringPlatformTransactionManager.
   */
  public void testTransactionShouldSucceedWithCallbackPreference() throws Exception {
    TransactionAttribute txatt = new DefaultTransactionAttribute();

    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(getNameMethod, txatt);

    MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();

    TestBean tb = new TestBean();
    ITestBean itb = (ITestBean) advised(tb, ptm, tas);

    checkTransactionStatus(false);
    itb.getName();
    checkTransactionStatus(false);

    assertSame(txatt, ptm.getDefinition());
    assertFalse(ptm.getStatus().isRollbackOnly());
  }
  public void testNoTransaction() throws Exception {
    MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
    PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();

    // expect no calls
    ptmControl.replay();

    TestBean tb = new TestBean();
    TransactionAttributeSource tas = new MapTransactionAttributeSource();

    // All the methods in this class use the advised() template method
    // to obtain a transaction object, configured with the given PlatformTransactionManager
    // and transaction attribute source
    ITestBean itb = (ITestBean) advised(tb, ptm, tas);

    checkTransactionStatus(false);
    itb.getName();
    checkTransactionStatus(false);

    ptmControl.verify();
  }
  @Test
  public void testCustomAutoProxyCreator() {
    StaticApplicationContext sac = new StaticApplicationContext();
    sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class);
    sac.registerSingleton("singletonNoInterceptor", TestBean.class);
    sac.registerSingleton("singletonToBeProxied", TestBean.class);
    sac.registerPrototype("prototypeToBeProxied", TestBean.class);
    sac.refresh();

    MessageSource messageSource = (MessageSource) sac.getBean("messageSource");
    ITestBean singletonNoInterceptor = (ITestBean) sac.getBean("singletonNoInterceptor");
    ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
    ITestBean prototypeToBeProxied = (ITestBean) sac.getBean("prototypeToBeProxied");
    assertFalse(AopUtils.isCglibProxy(messageSource));
    assertTrue(AopUtils.isCglibProxy(singletonNoInterceptor));
    assertTrue(AopUtils.isCglibProxy(singletonToBeProxied));
    assertTrue(AopUtils.isCglibProxy(prototypeToBeProxied));

    TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
    assertEquals(0, tapc.testInterceptor.nrOfInvocations);
    singletonNoInterceptor.getName();
    assertEquals(0, tapc.testInterceptor.nrOfInvocations);
    singletonToBeProxied.getAge();
    assertEquals(1, tapc.testInterceptor.nrOfInvocations);
    prototypeToBeProxied.getSpouse();
    assertEquals(2, tapc.testInterceptor.nrOfInvocations);
  }
  @Test
  public void testGetFromScopeThroughDynamicProxy() throws Exception {
    String name = "requestScopedProxy";
    ITestBean bean = (ITestBean) this.beanFactory.getBean(name);
    assertTrue(AopUtils.isJdkDynamicProxy(bean));

    MockHttpServletRequest request = new MockHttpServletRequest();
    RequestAttributes requestAttributes = new ServletRequestAttributes(request);
    RequestContextHolder.setRequestAttributes(requestAttributes);

    try {
      assertNull(request.getAttribute("scopedTarget." + name));
      assertEquals("scoped", bean.getName());
      assertNotNull(request.getAttribute("scopedTarget." + name));
      TestBean target = (TestBean) request.getAttribute("scopedTarget." + name);
      assertEquals(TestBean.class, target.getClass());
      assertEquals("scoped", target.getName());
      assertSame(bean, this.beanFactory.getBean(name));
      assertEquals(bean.toString(), target.toString());
    } finally {
      RequestContextHolder.setRequestAttributes(null);
    }
  }
  public void testTransactionExceptionPropagatedWithCallbackPreference() throws Throwable {
    TransactionAttribute txatt = new DefaultTransactionAttribute();

    MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
    tas.register(exceptionalMethod, txatt);

    MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();

    TestBean tb = new TestBean();
    ITestBean itb = (ITestBean) advised(tb, ptm, tas);

    checkTransactionStatus(false);
    try {
      itb.exceptional(new OptimisticLockingFailureException(""));
      fail("Should have thrown OptimisticLockingFailureException");
    } catch (OptimisticLockingFailureException ex) {
      // expected
    }
    checkTransactionStatus(false);

    assertSame(txatt, ptm.getDefinition());
    assertFalse(ptm.getStatus().isRollbackOnly());
  }
  @Test
  public void testBeanNameAutoProxyCreatorWithFactoryBeanProxy() {
    StaticApplicationContext sac = new StaticApplicationContext();
    sac.registerSingleton("testInterceptor", TestInterceptor.class);

    RootBeanDefinition proxyCreator = new RootBeanDefinition(BeanNameAutoProxyCreator.class);
    proxyCreator.getPropertyValues().add("interceptorNames", "testInterceptor");
    proxyCreator
        .getPropertyValues()
        .add("beanNames", "singletonToBeProxied,&singletonFactoryToBeProxied");
    sac.getDefaultListableBeanFactory()
        .registerBeanDefinition("beanNameAutoProxyCreator", proxyCreator);

    RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
    sac.getDefaultListableBeanFactory().registerBeanDefinition("singletonToBeProxied", bd);

    sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);

    sac.refresh();

    ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
    assertTrue(Proxy.isProxyClass(singletonToBeProxied.getClass()));

    TestInterceptor ti = (TestInterceptor) sac.getBean("testInterceptor");
    int initialNr = ti.nrOfInvocations;
    singletonToBeProxied.getName();
    assertEquals(initialNr + 1, ti.nrOfInvocations);

    FactoryBean<?> factory = (FactoryBean<?>) sac.getBean("&singletonFactoryToBeProxied");
    assertTrue(Proxy.isProxyClass(factory.getClass()));
    TestBean tb = (TestBean) sac.getBean("singletonFactoryToBeProxied");
    assertFalse(AopUtils.isAopProxy(tb));
    assertEquals(initialNr + 3, ti.nrOfInvocations);
    tb.getAge();
    assertEquals(initialNr + 3, ti.nrOfInvocations);
  }