| // Copyright 2011 The Apache Software Foundation |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package org.apache.tapestry5.internal.jpa; |
| |
| import java.sql.SQLException; |
| import java.util.Map; |
| |
| import javax.persistence.EntityManager; |
| import javax.persistence.EntityTransaction; |
| import javax.persistence.PersistenceContext; |
| |
| import org.apache.tapestry5.ioc.IOCUtilities; |
| import org.apache.tapestry5.ioc.Registry; |
| import org.apache.tapestry5.ioc.internal.util.CollectionFactory; |
| import org.apache.tapestry5.ioc.services.AspectDecorator; |
| import org.apache.tapestry5.ioc.services.AspectInterceptorBuilder; |
| import org.apache.tapestry5.ioc.test.IOCTestCase; |
| import org.apache.tapestry5.ioc.test.TestBase; |
| import org.apache.tapestry5.jpa.EntityManagerManager; |
| import org.apache.tapestry5.jpa.EntityTransactionManager; |
| import org.apache.tapestry5.jpa.JpaTransactionAdvisor; |
| import org.apache.tapestry5.jpa.annotations.CommitAfter; |
| import org.slf4j.LoggerFactory; |
| import org.testng.Assert; |
| import org.testng.annotations.AfterClass; |
| import org.testng.annotations.BeforeClass; |
| import org.testng.annotations.Test; |
| |
| public class JpaTransactionAdvisorImplTest extends IOCTestCase |
| { |
| private static final String UNIT_NAME = "FooUnit"; |
| |
| private Registry registry; |
| |
| private AspectDecorator aspectDecorator; |
| |
| @BeforeClass |
| public void setup() |
| { |
| registry = IOCUtilities.buildDefaultRegistry(); |
| |
| aspectDecorator = registry.getService(AspectDecorator.class); |
| } |
| |
| @AfterClass |
| public void shutdown() |
| { |
| registry.shutdown(); |
| |
| aspectDecorator = null; |
| registry = null; |
| } |
| |
| @Test |
| public void undecorated() |
| { |
| final VoidService delegate = newMock(VoidService.class); |
| final EntityTransactionManager transactionManager = newMock(EntityTransactionManager.class); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final AspectInterceptorBuilder<VoidService> builder = aspectDecorator.createBuilder( |
| VoidService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final VoidService interceptor = builder.build(); |
| |
| delegate.undecorated(); |
| |
| replay(); |
| interceptor.undecorated(); |
| verify(); |
| } |
| |
| @Test |
| public void persistence_unit_name_missing() |
| { |
| Map<String, EntityManager> managers = CollectionFactory.newMap(); |
| managers.put("A", newMock(EntityManager.class)); |
| managers.put("B", newMock(EntityManager.class)); |
| |
| final VoidService delegate = newMock(VoidService.class); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(managers); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final AspectInterceptorBuilder<VoidService> builder = aspectDecorator.createBuilder( |
| VoidService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final VoidService interceptor = builder.build(); |
| |
| expect(manager.getEntityManagers()).andReturn(managers); |
| |
| replay(); |
| |
| try |
| { |
| interceptor.persistenceUnitNameMissing(); |
| TestBase.unreachable(); |
| } catch (Exception e) |
| { |
| Assert.assertEquals(e.getMessage(), "Unable to locate a single EntityManager. " + |
| "You must provide the persistence unit name as defined in the persistence.xml using the @PersistenceContext annotation."); |
| } |
| verify(); |
| } |
| |
| @Test |
| public void persistence_unit_name_missing_single_unit_configured() |
| { |
| EntityManager em = newMock(EntityManager.class); |
| Map<String, EntityManager> managers = CollectionFactory.newMap(); |
| managers.put("A", em); |
| |
| final VoidService delegate = newMock(VoidService.class); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(managers); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| |
| final EntityTransaction transaction = newMock(EntityTransaction.class); |
| |
| |
| final AspectInterceptorBuilder<VoidService> builder = aspectDecorator.createBuilder( |
| VoidService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final VoidService interceptor = builder.build(); |
| |
| expect(manager.getEntityManagers()).andReturn(managers); |
| train_getTransaction(em, transaction, true); |
| delegate.persistenceUnitNameMissing(); |
| train_commitActiveTransaction(transaction); |
| |
| replay(); |
| interceptor.persistenceUnitNameMissing(); |
| verify(); |
| } |
| |
| @Test |
| public void persistence_unit_missing() |
| { |
| Map<String, EntityManager> managers = CollectionFactory.newMap(); |
| managers.put("A", newMock(EntityManager.class)); |
| managers.put("B", newMock(EntityManager.class)); |
| |
| final VoidService delegate = newMock(VoidService.class); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(managers); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| |
| |
| final AspectInterceptorBuilder<VoidService> builder = aspectDecorator.createBuilder( |
| VoidService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final VoidService interceptor = builder.build(); |
| |
| expect(manager.getEntityManagers()).andReturn(managers); |
| |
| replay(); |
| |
| try |
| { |
| interceptor.persistenceUnitMissing(); |
| TestBase.unreachable(); |
| } catch (Exception e) |
| { |
| assertMessageContains(e, "Unable to locate a single EntityManager"); |
| } |
| |
| verify(); |
| } |
| |
| @Test |
| public void persistence_unit_missing_single_unit_configured() |
| { |
| EntityManager em = newMock(EntityManager.class); |
| Map<String, EntityManager> managers = CollectionFactory.newMap(); |
| managers.put("A", em); |
| final VoidService delegate = newMock(VoidService.class); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(managers); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final EntityTransaction transaction = newMock(EntityTransaction.class); |
| |
| final AspectInterceptorBuilder<VoidService> builder = aspectDecorator.createBuilder( |
| VoidService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final VoidService interceptor = builder.build(); |
| |
| expect(manager.getEntityManagers()).andReturn(managers); |
| train_getTransaction(em, transaction, true); |
| delegate.persistenceUnitMissing(); |
| train_commitActiveTransaction(transaction); |
| |
| replay(); |
| interceptor.persistenceUnitMissing(); |
| verify(); |
| } |
| |
| @Test |
| public void transaction_inactive() |
| { |
| final VoidService delegate = newMock(VoidService.class); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(CollectionFactory.newMap()); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final EntityManager entityManager = newMock(EntityManager.class); |
| final EntityTransaction transaction = newMock(EntityTransaction.class); |
| |
| final AspectInterceptorBuilder<VoidService> builder = aspectDecorator.createBuilder( |
| VoidService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final VoidService interceptor = builder.build(); |
| |
| train_getAndBeginTransaction(manager, entityManager, transaction); |
| |
| delegate.voidMethod(); |
| |
| train_commitActiveTransaction(transaction); |
| |
| replay(); |
| interceptor.voidMethod(); |
| verify(); |
| } |
| |
| @Test |
| public void void_method() |
| { |
| final VoidService delegate = newMock(VoidService.class); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(CollectionFactory.newMap()); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final EntityManager entityManager = newMock(EntityManager.class); |
| final EntityTransaction transaction = newMock(EntityTransaction.class); |
| |
| final AspectInterceptorBuilder<VoidService> builder = aspectDecorator.createBuilder( |
| VoidService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final VoidService interceptor = builder.build(); |
| |
| train_getActiveTransaction(manager, entityManager, transaction); |
| |
| delegate.voidMethod(); |
| |
| train_commitActiveTransaction(transaction); |
| |
| replay(); |
| interceptor.voidMethod(); |
| verify(); |
| } |
| |
| @Test |
| public void void_method_with_param() |
| { |
| final VoidService delegate = newMock(VoidService.class); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(CollectionFactory.newMap()); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final EntityManager entityManager = newMock(EntityManager.class); |
| final EntityTransaction transaction = newMock(EntityTransaction.class); |
| |
| final AspectInterceptorBuilder<VoidService> builder = aspectDecorator.createBuilder( |
| VoidService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final VoidService interceptor = builder.build(); |
| |
| train_getActiveTransaction(manager, entityManager, transaction); |
| delegate.voidMethodWithParam(777); |
| train_commitActiveTransaction(transaction); |
| |
| replay(); |
| interceptor.voidMethodWithParam(777); |
| verify(); |
| } |
| |
| @Test |
| public void runtime_exception_will_abort_transaction() throws Exception |
| { |
| final Performer delegate = newMock(Performer.class); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(CollectionFactory.newMap()); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final EntityManager entityManager = newMock(EntityManager.class); |
| final EntityTransaction transaction = newMock(EntityTransaction.class); |
| final RuntimeException re = new RuntimeException("Unexpected."); |
| |
| final AspectInterceptorBuilder<Performer> builder = aspectDecorator.createBuilder( |
| Performer.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final Performer interceptor = builder.build(); |
| |
| train_getActiveTransaction(manager, entityManager, transaction); |
| delegate.perform(); |
| TestBase.setThrowable(re); |
| train_rollBackActiveTransaction(transaction); |
| |
| replay(); |
| try |
| { |
| interceptor.perform(); |
| TestBase.unreachable(); |
| } catch (final RuntimeException ex) |
| { |
| Assert.assertSame(ex, re); |
| } |
| |
| verify(); |
| } |
| |
| @Test |
| public void checked_exception_will_commit_transaction() throws Exception |
| { |
| final Performer delegate = newMock(Performer.class); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(CollectionFactory.newMap()); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final EntityManager entityManager = newMock(EntityManager.class); |
| final EntityTransaction transaction = newMock(EntityTransaction.class); |
| final SQLException se = new SQLException("Checked."); |
| |
| final AspectInterceptorBuilder<Performer> builder = aspectDecorator.createBuilder( |
| Performer.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final Performer interceptor = builder.build(); |
| |
| train_getActiveTransaction(manager, entityManager, transaction); |
| |
| delegate.perform(); |
| setThrowable(se); |
| |
| train_commitActiveTransaction(transaction); |
| |
| replay(); |
| |
| |
| try |
| { |
| interceptor.perform(); |
| |
| unreachable(); |
| } catch (final SQLException ex) |
| { |
| Assert.assertSame(ex, se); |
| } |
| |
| verify(); |
| } |
| |
| @Test |
| public void return_type_method() |
| { |
| final ReturnTypeService delegate = newTestService(); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(CollectionFactory.newMap()); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final EntityManager entityManager = newMock(EntityManager.class); |
| final EntityTransaction transaction = newMock(EntityTransaction.class); |
| |
| final AspectInterceptorBuilder<ReturnTypeService> builder = aspectDecorator.createBuilder( |
| ReturnTypeService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final ReturnTypeService interceptor = builder.build(); |
| |
| train_getActiveTransaction(manager, entityManager, transaction); |
| delegate.returnTypeMethod(); |
| train_commitActiveTransaction(transaction); |
| |
| replay(); |
| Assert.assertEquals(interceptor.returnTypeMethod(), "Foo"); |
| verify(); |
| } |
| |
| @Test |
| public void return_type_method_with_param() |
| { |
| final ReturnTypeService delegate = newTestService(); |
| final EntityManagerManager manager = newMock(EntityManagerManager.class); |
| expect(manager.getEntityManagers()).andReturn(CollectionFactory.newMap()); |
| |
| replay(); |
| final EntityTransactionManager transactionManager = new EntityTransactionManagerImpl( |
| LoggerFactory.getLogger(EntityTransactionManagerImpl.class),manager); |
| verify(); |
| final JpaAdvisorProvider provider = new JpaAdvisorProviderImpl(transactionManager); |
| final JpaTransactionAdvisor advisor = newJpaTransactionAdvisor(provider); |
| final EntityManager entityManager = newMock(EntityManager.class); |
| final EntityTransaction transaction = newMock(EntityTransaction.class); |
| |
| final AspectInterceptorBuilder<ReturnTypeService> builder = aspectDecorator.createBuilder( |
| ReturnTypeService.class, delegate, "foo.Bar"); |
| |
| advisor.addTransactionCommitAdvice(builder); |
| |
| final ReturnTypeService interceptor = builder.build(); |
| |
| train_getActiveTransaction(manager, entityManager, transaction); |
| delegate.returnTypeMethodWithParam(5, 3); |
| train_commitActiveTransaction(transaction); |
| |
| replay(); |
| Assert.assertEquals(interceptor.returnTypeMethodWithParam(5, 3), 8); |
| verify(); |
| } |
| |
| private void train_getAndBeginTransaction(final EntityManagerManager manager, |
| final EntityManager entityManager, final EntityTransaction transaction) |
| { |
| train_getTransaction(manager, entityManager, transaction, false); |
| transaction.begin(); |
| } |
| |
| private void train_getActiveTransaction(final EntityManagerManager manager, |
| final EntityManager entityManager, final EntityTransaction transaction) |
| { |
| train_getTransaction(manager, entityManager, transaction, true); |
| } |
| |
| private void train_getTransaction(final EntityManagerManager manager, |
| final EntityManager entityManager, final EntityTransaction transaction, |
| final boolean isActive) |
| { |
| expect(manager.getEntityManager(UNIT_NAME)).andReturn(entityManager); |
| train_getTransaction(entityManager, transaction, isActive); |
| } |
| |
| private void train_getTransaction( |
| final EntityManager entityManager, final EntityTransaction transaction, |
| final boolean isActive) |
| { |
| expect(entityManager.getTransaction()).andReturn(transaction); |
| expect(transaction.isActive()).andReturn(isActive); |
| } |
| |
| private void train_commitActiveTransaction(final EntityTransaction transaction) |
| { |
| expect(transaction.isActive()).andReturn(true); |
| transaction.commit(); |
| } |
| |
| private void train_rollBackActiveTransaction(final EntityTransaction transaction) |
| { |
| expect(transaction.isActive()).andReturn(true); |
| transaction.rollback(); |
| } |
| |
| private JpaTransactionAdvisor newJpaTransactionAdvisor(final JpaAdvisorProvider provider) |
| { |
| return new JpaTransactionAdvisorImpl(provider); |
| } |
| |
| private ReturnTypeService newTestService() |
| { |
| return new ReturnTypeService() |
| { |
| |
| @Override |
| public String returnTypeMethod() |
| { |
| return "Foo"; |
| } |
| |
| @Override |
| public int returnTypeMethodWithParam(final int first, final int second) |
| { |
| return first + second; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return "Baz"; |
| } |
| }; |
| } |
| |
| public interface ReturnTypeService |
| { |
| @CommitAfter |
| @PersistenceContext(unitName = UNIT_NAME) |
| String returnTypeMethod(); |
| |
| @CommitAfter |
| @PersistenceContext(unitName = UNIT_NAME) |
| int returnTypeMethodWithParam(int first, int second); |
| |
| @Override |
| String toString(); |
| } |
| |
| public interface VoidService |
| { |
| void undecorated(); |
| |
| @CommitAfter |
| @PersistenceContext |
| void persistenceUnitNameMissing(); |
| |
| @CommitAfter |
| void persistenceUnitMissing(); |
| |
| @CommitAfter |
| @PersistenceContext(unitName = UNIT_NAME) |
| void voidMethod(); |
| |
| @CommitAfter |
| @PersistenceContext(unitName = UNIT_NAME) |
| void voidMethodWithParam(long id); |
| } |
| |
| public interface Performer |
| { |
| @CommitAfter |
| @PersistenceContext(unitName = UNIT_NAME) |
| void perform() throws SQLException; |
| } |
| } |