diff --git a/spring-autoconfigure/pom.xml b/spring-autoconfigure/pom.xml index 838ba74b9fd..2cc0fcccec5 100644 --- a/spring-autoconfigure/pom.xml +++ b/spring-autoconfigure/pom.xml @@ -118,5 +118,10 @@ spring-test test + + org.slf4j + slf4j-jdk14 + test + diff --git a/spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.java b/spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.java index f01a4d105fb..eb658a2d963 100644 --- a/spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.java +++ b/spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.java @@ -41,7 +41,7 @@ import org.springframework.util.StringUtils; @Configuration @ConditionalOnClass(HibernateEntityManager.class) @EnableTransactionManagement -public class HibernateJpaAutoConfiguration extends JpaAutoConfiguration { +public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration { private static final Map EMBEDDED_DATABASE_DIALECTS; static { diff --git a/spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/JpaAutoConfiguration.java b/spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/JpaBaseConfiguration.java similarity index 63% rename from spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/JpaAutoConfiguration.java rename to spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/JpaBaseConfiguration.java index c11f9b39946..2e5fcd33c45 100644 --- a/spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/JpaAutoConfiguration.java +++ b/spring-autoconfigure/src/main/java/org/springframework/autoconfigure/orm/jpa/JpaBaseConfiguration.java @@ -32,23 +32,32 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.bootstrap.context.condition.ConditionalOnBean; import org.springframework.bootstrap.context.condition.ConditionalOnClass; +import org.springframework.bootstrap.context.condition.ConditionalOnExpression; +import org.springframework.bootstrap.context.condition.ConditionalOnMissingBean; +import org.springframework.bootstrap.context.condition.ConditionalOnWebApplication; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter; +import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.util.Assert; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Base {@link EnableAutoConfiguration Auto-configuration} for JPA. * * @author Phillip Webb + * @author Dave Syer */ -@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, - EnableTransactionManagement.class, EntityManager.class }) +@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EnableTransactionManagement.class, + EntityManager.class }) @ConditionalOnBean(DataSource.class) -public abstract class JpaAutoConfiguration implements BeanFactoryAware { +public abstract class JpaBaseConfiguration implements BeanFactoryAware { private ConfigurableListableBeanFactory beanFactory; @@ -67,19 +76,33 @@ public abstract class JpaAutoConfiguration implements BeanFactoryAware { return entityManagerFactoryBean; } + @Configuration + @ConditionalOnWebApplication + @ConditionalOnMissingBean({ OpenEntityManagerInViewInterceptor.class, OpenEntityManagerInViewFilter.class }) + @ConditionalOnExpression("${spring.jpa.openInView:${spring.jpa.open_in_view:true}}") + protected static class JpaWebConfiguration extends WebMvcConfigurerAdapter { + + @Override + public void addInterceptors(InterceptorRegistry registry) { + super.addInterceptors(registry); + } + + @Bean + public OpenEntityManagerInViewInterceptor openEntityManagerInViewInterceptor() { + return new OpenEntityManagerInViewInterceptor(); + } + + } + /** - * Determines if the {@code dataSource} being used by Spring was created from - * {@link EmbeddedDatabaseConfiguration}. + * Determines if the {@code dataSource} being used by Spring was created from {@link EmbeddedDatabaseConfiguration}. * @return true if the data source was auto-configured. */ protected boolean isAutoConfiguredDataSource() { try { - BeanDefinition beanDefinition = this.beanFactory - .getBeanDefinition("dataSource"); - return EmbeddedDatabaseConfiguration.class.getName().equals( - beanDefinition.getFactoryBeanName()); - } - catch (NoSuchBeanDefinitionException ex) { + BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("dataSource"); + return EmbeddedDatabaseConfiguration.class.getName().equals(beanDefinition.getFactoryBeanName()); + } catch (NoSuchBeanDefinitionException ex) { return false; } } @@ -90,23 +113,19 @@ public abstract class JpaAutoConfiguration implements BeanFactoryAware { protected DataSource getDataSource() { try { return this.beanFactory.getBean("dataSource", DataSource.class); - } - catch (RuntimeException ex) { + } catch (RuntimeException ex) { return this.beanFactory.getBean(DataSource.class); } } protected String[] getPackagesToScan() { - List basePackages = AutoConfigurationUtils - .getBasePackages(this.beanFactory); - Assert.notEmpty(basePackages, - "Unable to find JPA packages to scan, please define " - + "a @ComponentScan annotation or disable JpaAutoConfiguration"); + List basePackages = AutoConfigurationUtils.getBasePackages(this.beanFactory); + Assert.notEmpty(basePackages, "Unable to find JPA packages to scan, please define " + + "a @ComponentScan annotation or disable JpaAutoConfiguration"); return basePackages.toArray(new String[basePackages.size()]); } - protected void configure( - LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) { + protected void configure(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) { } @Override diff --git a/spring-autoconfigure/src/test/java/org/springframework/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java b/spring-autoconfigure/src/test/java/org/springframework/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java index f3a0ac4b726..70f8d0e7cae 100644 --- a/spring-autoconfigure/src/test/java/org/springframework/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java +++ b/spring-autoconfigure/src/test/java/org/springframework/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java @@ -16,21 +16,29 @@ package org.springframework.autoconfigure.orm.jpa; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + import javax.sql.DataSource; +import org.junit.After; import org.junit.Test; import org.springframework.autoconfigure.ComponentScanDetectorConfiguration; import org.springframework.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.autoconfigure.jdbc.EmbeddedDatabaseConfiguration; -import org.springframework.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.autoconfigure.orm.jpa.test.City; +import org.springframework.bootstrap.TestUtils; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; import org.springframework.orm.jpa.JpaTransactionManager; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter; +import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; /** * Tests for {@link HibernateJpaAutoConfiguration}. @@ -39,11 +47,18 @@ import static org.junit.Assert.assertTrue; */ public class HibernateJpaAutoConfigurationTests { - private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + private ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(); + + @After + public void close() { + if (context != null) { + context.close(); + } + } @Test public void testEntityManagerCreated() throws Exception { - this.context.register(ComponentScanDetectorConfiguration.class, + ((AnnotationConfigApplicationContext) this.context).register(ComponentScanDetectorConfiguration.class, EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class); this.context.refresh(); @@ -53,17 +68,58 @@ public class HibernateJpaAutoConfigurationTests { @Test public void testDataSourceTransactionManagerNotCreated() throws Exception { - this.context.register(ComponentScanDetectorConfiguration.class, + ((AnnotationConfigApplicationContext) this.context).register(ComponentScanDetectorConfiguration.class, EmbeddedDatabaseConfiguration.class, HibernateJpaAutoConfiguration.class, - DataSourceTransactionManagerAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class); + DataSourceTransactionManagerAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, + TestConfiguration.class); this.context.refresh(); assertNotNull(this.context.getBean(DataSource.class)); assertTrue(this.context.getBean("transactionManager") instanceof JpaTransactionManager); } + @Test + public void testOpenEntityManagerInViewInterceptorCreated() throws Exception { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.register(ComponentScanDetectorConfiguration.class, EmbeddedDatabaseConfiguration.class, + HibernateJpaAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, + TestConfiguration.class); + this.context = context; + this.context.refresh(); + assertNotNull(this.context.getBean(OpenEntityManagerInViewInterceptor.class)); + } + + @Test + public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenFilterPresent() throws Exception { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.register(TestFilterConfiguration.class, ComponentScanDetectorConfiguration.class, EmbeddedDatabaseConfiguration.class, + HibernateJpaAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); + this.context = context; + this.context.refresh(); + assertEquals(0, this.context.getBeanNamesForType(OpenEntityManagerInViewInterceptor.class).length); + } + + @Test + public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenExplicitlyOff() throws Exception { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + TestUtils.addEnviroment(context, "spring.jpa.open_in_view:false"); + context.register(TestConfiguration.class, ComponentScanDetectorConfiguration.class, EmbeddedDatabaseConfiguration.class, + HibernateJpaAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); + this.context = context; + this.context.refresh(); + assertEquals(0, this.context.getBeanNamesForType(OpenEntityManagerInViewInterceptor.class).length); + } + @ComponentScan(basePackageClasses = { City.class }) protected static class TestConfiguration { } + + @ComponentScan(basePackageClasses = { City.class }) + @Configuration + protected static class TestFilterConfiguration { + @Bean + public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() { + return new OpenEntityManagerInViewFilter(); + } + } } diff --git a/spring-bootstrap/pom.xml b/spring-bootstrap/pom.xml index 29e3b1b099d..7492a23fdc5 100644 --- a/spring-bootstrap/pom.xml +++ b/spring-bootstrap/pom.xml @@ -99,6 +99,11 @@ jcl-over-slf4j test + + org.slf4j + slf4j-jdk14 + test +