2

I'm writing some junit tests for my Spring 3.2.8 + Hibernate 4.3.4 application. My test class is annotated with:

@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
@Transactional
public class UserServiceImplTest {
   ...
   ...
}

However, I get the following error thrown by an aspect that is trying to use the entity manager:

org.springframework.dao.InvalidDataAccessApiUsageException: EntityManagerFactory is closed; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed

If I look at the logs, I see the following error message at the start of my second test:

2014-04-02 16:36:48,891 [main] WARN  org.hibernate.jpa.internal.EntityManagerFactoryRegistry - HHH000436: Entity manager factory name (default) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'

I realize that it is just a warning, but I am wondering if this is part of the issue. I do not understand why it is complaining that the factory is already registered when the @DirtiesContext is supposed to ensure that the context is cleaned out before starting the second test.

I do see the context being cleaned up at the end of my first test:

2014-04-02 16:36:10,733 [main] INFO  springframework.test.context.transaction.TransactionalTestExecutionListener - Rolled back transaction after test execution for test context [TestContext@1ff221ad testClass = UserServiceImplTest, testInstance = com.ia.service.UserServiceImplTest@5180f53d, testMethod = testUpdateRoles@UserServiceImplTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@6964a198 testClass = UserServiceImplTest, locations = '{classpath:META-INF/spring/applicationContext*.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{test}', resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]]
2014-04-02 16:36:10,735 [main] INFO  springframework.web.context.support.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@53c3dcdc: startup date [Wed Apr 02 16:35:00 EDT 2014]; root of context hierarchy
2014-04-02 16:36:10,736 [main] INFO  springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2ff0a910: defining beans [dataSource,entityManagerFactory,org.springframework.transaction.config.internalTransactionAspect,hibernateJpaVendorAdapter,transactionManager,org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor#0,org.springframework.data.jpa.repository.support.EntityManagerBeanDefinitionRegistrarPostProcessor#0,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor#0,rateRepository,userRepositoryImpl,userRepository,patchRepository,org.springframework.security.filterChains,org.springframework.security.filterChainProxy,org.springframework.security.web.DefaultSecurityFilterChain#0,org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler#0,org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource#0,org.springframework.security.access.vote.AffirmativeBased#0,org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor#0,org.springframework.security.methodSecurityMetadataSourceAdvisor,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.security.web.PortMapperImpl#0,org.springframework.security.web.PortResolverImpl#0,org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0,org.springframework.security.authentication.ProviderManager#0,org.springframework.security.web.context.NullSecurityContextRepository#0,org.springframework.security.web.savedrequest.NullRequestCache#0,org.springframework.security.access.vote.AffirmativeBased#1,org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0,org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator#0,org.springframework.security.authentication.AnonymousAuthenticationProvider#0,org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint#0,org.springframework.security.userDetailsServiceFactory,org.springframework.security.web.DefaultSecurityFilterChain#1,org.springframework.security.authentication.dao.DaoAuthenticationProvider#0,org.springframework.security.authentication.DefaultAuthenticationEventPublisher#0,org.springframework.security.authenticationManager,basicAuthenticationFilter,authenticationEntryPoint,defaultWebSecurityExpressionHandler,org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0,org.springframework.context.config.internalBeanConfigurerAspect,contactDataOnDemand,userDataOnDemand,testBase.BeanRegistry,securityService,patchServiceImpl,rateServiceImpl,userServiceImpl,appConfig,viewConfig,webContextFilter,patchEngineContextListener,patchEngineImpl.PatchEngineInitializer,patchEngineImpl,initializeUsersRolesAndPermissionsPatch,tilesContainerFactory,viewMetaPreparer,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,applicationProperties,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.data.auditing.AuditingHandler#0,org.springframework.data.jpa.domain.support.AuditingEntityListener,org.springframework.data.jpa.domain.support.AuditingBeanFactoryPostProcessor,org.springframework.data.auditing.AuditingHandler#1,auditorProvider,objectMapper,org.springframework.orm.jpa.SharedEntityManagerCreator#0]; root of factory hierarchy
2014-04-02 16:36:10,754 [main] INFO  org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default'

so I am not sure why it is complaining that the EntityManagerFactory is already registered. Furthermore, I am not sure why the EMF is closed when I am trying to access it.

Do I need to do something special to ensure that it is still accessible in each test? I did find this post on SO that relates to the issue, but doesn't help me nail down why this is happening.

Community
  • 1
  • 1
Eric B.
  • 23,425
  • 50
  • 169
  • 316

2 Answers2

2

It turns out after much debugging that the problem is in the aspect that is using the EntityManagerFactory. Given that the aspect is instantiated outside the Spring context, when the context is refreshed, the aspect's references are not updated. Consequently, the aspect is holding a reference to an EMF that is indeed closed - the original EMF from the first unit test. Now I just have to figure out how to get Spring to update/refresh the references when the context is updated.

Eric B.
  • 23,425
  • 50
  • 169
  • 316
  • @Gab - I would, but it takes 2 days before I can accept my own answer. :) – Eric B. Apr 03 '14 at 14:39
  • Were you able to figure out a way to refresh aspect references? – Ankit Batra Oct 04 '16 at 04:46
  • @AnkitBatra This was a couple of years ago, so I don't remember precisely, but I do recall that I had a lot of difficulty with the Aspects retaining contextual information when I didn't want them to. I worked hard to get around that issue, but there is a lot of static data that is initialized in the aspects (due to the way AJ works) that I could not "undo". I believe my only way to circumvent the issue was to launch multiple forks, where each test ran in an independent fork. – Eric B. Oct 05 '16 at 16:02
  • @Eric Thanks for getting back. – Ankit Batra Oct 05 '16 at 16:21
1

Seems that something try to get a persistence context before the spring context was set up or after it was disposed.

Don't you have some junit @before or @after annotated method which accesses the persistence ?

Gab
  • 7,869
  • 4
  • 37
  • 68
  • No - nothing in the `@before` or `@after` methods. But after a whole bunch of debugging, I finally realized that it was a problem with my aspect; it is maintaining the EntityManagerFactory bean reference from the first context, and not updating the reference after the context refreshes. – Eric B. Apr 03 '14 at 01:47