Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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 ?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top