|
|
|
@ -24,23 +24,17 @@ import javax.persistence.EntityManagerFactory;
|
|
|
|
|
import javax.sql.DataSource;
|
|
|
|
|
|
|
|
|
|
import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform;
|
|
|
|
|
import org.junit.After;
|
|
|
|
|
import org.junit.Rule;
|
|
|
|
|
import org.junit.Test;
|
|
|
|
|
import org.junit.rules.ExpectedException;
|
|
|
|
|
|
|
|
|
|
import org.springframework.beans.factory.BeanCreationException;
|
|
|
|
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|
|
|
|
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
|
|
|
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
|
|
|
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
|
|
|
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
|
|
|
|
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
|
|
|
|
import org.springframework.boot.autoconfigure.orm.jpa.test.City;
|
|
|
|
|
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
|
|
|
|
|
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
|
|
|
|
import org.springframework.boot.test.util.TestPropertyValues;
|
|
|
|
|
import org.springframework.context.ApplicationContext;
|
|
|
|
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
|
|
|
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
|
|
|
|
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
|
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
|
|
import org.springframework.orm.jpa.JpaTransactionManager;
|
|
|
|
@ -51,8 +45,6 @@ import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
|
|
|
|
|
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
|
|
|
|
|
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
|
|
|
|
|
import org.springframework.transaction.PlatformTransactionManager;
|
|
|
|
|
import org.springframework.util.ObjectUtils;
|
|
|
|
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
|
|
|
|
|
@ -65,172 +57,154 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
|
*/
|
|
|
|
|
public abstract class AbstractJpaAutoConfigurationTests {
|
|
|
|
|
|
|
|
|
|
@Rule
|
|
|
|
|
public ExpectedException expected = ExpectedException.none();
|
|
|
|
|
private final Class<?> autoConfiguredClass;
|
|
|
|
|
|
|
|
|
|
protected AnnotationConfigApplicationContext context;
|
|
|
|
|
private final ApplicationContextRunner contextRunner;
|
|
|
|
|
|
|
|
|
|
@After
|
|
|
|
|
public void close() {
|
|
|
|
|
if (this.context != null) {
|
|
|
|
|
this.context.close();
|
|
|
|
|
}
|
|
|
|
|
protected AbstractJpaAutoConfigurationTests(Class<?> autoConfiguredClass) {
|
|
|
|
|
this.autoConfiguredClass = autoConfiguredClass;
|
|
|
|
|
this.contextRunner = new ApplicationContextRunner()
|
|
|
|
|
.withPropertyValues("spring.datasource.generate-unique-name=true")
|
|
|
|
|
.withUserConfiguration(TestConfiguration.class)
|
|
|
|
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
|
|
|
|
|
TransactionAutoConfiguration.class, autoConfiguredClass));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected abstract Class<?> getAutoConfigureClass();
|
|
|
|
|
protected ApplicationContextRunner contextRunner() {
|
|
|
|
|
return this.contextRunner;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testNoDataSource() throws Exception {
|
|
|
|
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
|
|
|
|
context.register(PropertyPlaceholderAutoConfiguration.class,
|
|
|
|
|
getAutoConfigureClass());
|
|
|
|
|
this.expected.expect(BeanCreationException.class);
|
|
|
|
|
this.expected.expectMessage("No qualifying bean");
|
|
|
|
|
this.expected.expectMessage("DataSource");
|
|
|
|
|
context.refresh();
|
|
|
|
|
context.close();
|
|
|
|
|
public void dataSourceIsNotAvailable() {
|
|
|
|
|
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(
|
|
|
|
|
this.autoConfiguredClass)).run((context) -> {
|
|
|
|
|
assertThat(context).hasFailed();
|
|
|
|
|
assertThat(context.getStartupFailure())
|
|
|
|
|
.isInstanceOf(BeanCreationException.class);
|
|
|
|
|
assertThat(context.getStartupFailure())
|
|
|
|
|
.hasMessageContaining("No qualifying bean");
|
|
|
|
|
assertThat(context.getStartupFailure()).hasMessageContaining("DataSource");
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testEntityManagerCreated() throws Exception {
|
|
|
|
|
load();
|
|
|
|
|
assertThat(this.context.getBean(DataSource.class)).isNotNull();
|
|
|
|
|
assertThat(this.context.getBean(JpaTransactionManager.class)).isNotNull();
|
|
|
|
|
public void dataSourceIsCreatedWithDefaultConfig() {
|
|
|
|
|
this.contextRunner.run((context) -> {
|
|
|
|
|
assertThat(context).hasSingleBean(DataSource.class);
|
|
|
|
|
assertThat(context).hasSingleBean(JpaTransactionManager.class);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testDataSourceTransactionManagerNotCreated() throws Exception {
|
|
|
|
|
load(new Class<?>[0],
|
|
|
|
|
new Class<?>[] { DataSourceTransactionManagerAutoConfiguration.class });
|
|
|
|
|
assertThat(this.context.getBean(DataSource.class)).isNotNull();
|
|
|
|
|
assertThat(this.context.getBean("transactionManager"))
|
|
|
|
|
.isInstanceOf(JpaTransactionManager.class);
|
|
|
|
|
public void jtaTransactionManagerTakesPrecedence() {
|
|
|
|
|
this.contextRunner.withConfiguration(AutoConfigurations.of(
|
|
|
|
|
DataSourceTransactionManagerAutoConfiguration.class)).run((context) -> {
|
|
|
|
|
assertThat(context).hasSingleBean(DataSource.class);
|
|
|
|
|
assertThat(context).hasSingleBean(JpaTransactionManager.class);
|
|
|
|
|
assertThat(context).getBean("transactionManager")
|
|
|
|
|
.isInstanceOf(JpaTransactionManager.class);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testOpenEntityManagerInViewInterceptorCreated() throws Exception {
|
|
|
|
|
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
|
|
|
|
context.register(TestConfiguration.class, EmbeddedDataSourceConfiguration.class,
|
|
|
|
|
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
|
|
|
|
|
context.refresh();
|
|
|
|
|
assertThat(context.getBean(OpenEntityManagerInViewInterceptor.class)).isNotNull();
|
|
|
|
|
context.close();
|
|
|
|
|
public void openEntityManagerInViewInterceptorIsCreated() {
|
|
|
|
|
new WebApplicationContextRunner()
|
|
|
|
|
.withPropertyValues("spring.datasource.generate-unique-name=true")
|
|
|
|
|
.withUserConfiguration(TestConfiguration.class)
|
|
|
|
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
|
|
|
|
|
TransactionAutoConfiguration.class, this.autoConfiguredClass))
|
|
|
|
|
.run((context) -> assertThat(context)
|
|
|
|
|
.hasSingleBean(OpenEntityManagerInViewInterceptor.class));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenFilterPresent()
|
|
|
|
|
throws Exception {
|
|
|
|
|
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
|
|
|
|
context.register(TestFilterConfiguration.class,
|
|
|
|
|
EmbeddedDataSourceConfiguration.class,
|
|
|
|
|
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
|
|
|
|
|
context.refresh();
|
|
|
|
|
assertThat(getInterceptorBeans(context).length).isEqualTo(0);
|
|
|
|
|
context.close();
|
|
|
|
|
public void openEntityManagerInViewInterceptorIsNotRegisteredWhenFilterPresent() {
|
|
|
|
|
new WebApplicationContextRunner()
|
|
|
|
|
.withPropertyValues("spring.datasource.generate-unique-name=true")
|
|
|
|
|
.withUserConfiguration(TestFilterConfiguration.class)
|
|
|
|
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
|
|
|
|
|
TransactionAutoConfiguration.class, this.autoConfiguredClass))
|
|
|
|
|
.run((context) -> assertThat(context)
|
|
|
|
|
.doesNotHaveBean(OpenEntityManagerInViewInterceptor.class));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenExplicitlyOff()
|
|
|
|
|
throws Exception {
|
|
|
|
|
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
|
|
|
|
TestPropertyValues.of("spring.jpa.open_in_view:false").applyTo(context);
|
|
|
|
|
context.register(TestConfiguration.class, EmbeddedDataSourceConfiguration.class,
|
|
|
|
|
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
|
|
|
|
|
ConfigurationPropertySources.attach(context.getEnvironment());
|
|
|
|
|
context.refresh();
|
|
|
|
|
assertThat(getInterceptorBeans(context).length).isEqualTo(0);
|
|
|
|
|
context.close();
|
|
|
|
|
public void openEntityManagerInViewInterceptorISNotRegisteredWhenExplicitlyOff() {
|
|
|
|
|
new WebApplicationContextRunner()
|
|
|
|
|
.withPropertyValues(
|
|
|
|
|
"spring.datasource.generate-unique-name=true",
|
|
|
|
|
"spring.jpa.open-in-view=false")
|
|
|
|
|
.withUserConfiguration(TestConfiguration.class)
|
|
|
|
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
|
|
|
|
|
TransactionAutoConfiguration.class, this.autoConfiguredClass))
|
|
|
|
|
.run((context) -> assertThat(context)
|
|
|
|
|
.doesNotHaveBean(OpenEntityManagerInViewInterceptor.class));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void customJpaProperties() throws Exception {
|
|
|
|
|
load("spring.jpa.properties.a:b", "spring.jpa.properties.a.b:c",
|
|
|
|
|
"spring.jpa.properties.c:d");
|
|
|
|
|
LocalContainerEntityManagerFactoryBean bean = this.context
|
|
|
|
|
.getBean(LocalContainerEntityManagerFactoryBean.class);
|
|
|
|
|
Map<String, Object> map = bean.getJpaPropertyMap();
|
|
|
|
|
assertThat(map.get("a")).isEqualTo("b");
|
|
|
|
|
assertThat(map.get("c")).isEqualTo("d");
|
|
|
|
|
assertThat(map.get("a.b")).isEqualTo("c");
|
|
|
|
|
public void customJpaProperties() {
|
|
|
|
|
this.contextRunner.withPropertyValues("spring.jpa.properties.a:b",
|
|
|
|
|
"spring.jpa.properties.a.b:c",
|
|
|
|
|
"spring.jpa.properties.c:d").run((context) -> {
|
|
|
|
|
LocalContainerEntityManagerFactoryBean bean = context
|
|
|
|
|
.getBean(LocalContainerEntityManagerFactoryBean.class);
|
|
|
|
|
Map<String, Object> map = bean.getJpaPropertyMap();
|
|
|
|
|
assertThat(map.get("a")).isEqualTo("b");
|
|
|
|
|
assertThat(map.get("c")).isEqualTo("d");
|
|
|
|
|
assertThat(map.get("a.b")).isEqualTo("c");
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void usesManuallyDefinedLocalContainerEntityManagerFactoryBeanIfAvailable() {
|
|
|
|
|
load(TestConfigurationWithLocalContainerEntityManagerFactoryBean.class);
|
|
|
|
|
LocalContainerEntityManagerFactoryBean factoryBean = this.context
|
|
|
|
|
.getBean(LocalContainerEntityManagerFactoryBean.class);
|
|
|
|
|
Map<String, Object> map = factoryBean.getJpaPropertyMap();
|
|
|
|
|
assertThat(map.get("configured")).isEqualTo("manually");
|
|
|
|
|
this.contextRunner.withUserConfiguration(
|
|
|
|
|
TestConfigurationWithLocalContainerEntityManagerFactoryBean.class
|
|
|
|
|
).run((context) -> {
|
|
|
|
|
LocalContainerEntityManagerFactoryBean factoryBean = context
|
|
|
|
|
.getBean(LocalContainerEntityManagerFactoryBean.class);
|
|
|
|
|
Map<String, Object> map = factoryBean.getJpaPropertyMap();
|
|
|
|
|
assertThat(map.get("configured")).isEqualTo("manually");
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void usesManuallyDefinedEntityManagerFactoryIfAvailable() {
|
|
|
|
|
load(TestConfigurationWithLocalContainerEntityManagerFactoryBean.class);
|
|
|
|
|
EntityManagerFactory factoryBean = this.context
|
|
|
|
|
.getBean(EntityManagerFactory.class);
|
|
|
|
|
Map<String, Object> map = factoryBean.getProperties();
|
|
|
|
|
assertThat(map.get("configured")).isEqualTo("manually");
|
|
|
|
|
this.contextRunner.withUserConfiguration(
|
|
|
|
|
TestConfigurationWithLocalContainerEntityManagerFactoryBean.class
|
|
|
|
|
).run((context) -> {
|
|
|
|
|
EntityManagerFactory factoryBean = context
|
|
|
|
|
.getBean(EntityManagerFactory.class);
|
|
|
|
|
Map<String, Object> map = factoryBean.getProperties();
|
|
|
|
|
assertThat(map.get("configured")).isEqualTo("manually");
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void usesManuallyDefinedTransactionManagerBeanIfAvailable() {
|
|
|
|
|
load(TestConfigurationWithTransactionManager.class);
|
|
|
|
|
PlatformTransactionManager txManager = this.context
|
|
|
|
|
.getBean(PlatformTransactionManager.class);
|
|
|
|
|
assertThat(txManager).isInstanceOf(CustomJpaTransactionManager.class);
|
|
|
|
|
this.contextRunner.withUserConfiguration(
|
|
|
|
|
TestConfigurationWithTransactionManager.class
|
|
|
|
|
).run((context) -> {
|
|
|
|
|
PlatformTransactionManager txManager = context
|
|
|
|
|
.getBean(PlatformTransactionManager.class);
|
|
|
|
|
assertThat(txManager).isInstanceOf(CustomJpaTransactionManager.class);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void customPersistenceUnitManager() throws Exception {
|
|
|
|
|
load(TestConfigurationWithCustomPersistenceUnitManager.class);
|
|
|
|
|
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = this.context
|
|
|
|
|
.getBean(LocalContainerEntityManagerFactoryBean.class);
|
|
|
|
|
Field field = LocalContainerEntityManagerFactoryBean.class
|
|
|
|
|
.getDeclaredField("persistenceUnitManager");
|
|
|
|
|
field.setAccessible(true);
|
|
|
|
|
assertThat(field.get(entityManagerFactoryBean))
|
|
|
|
|
.isEqualTo(this.context.getBean(PersistenceUnitManager.class));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void load(String... environment) {
|
|
|
|
|
load(new Class<?>[0], new Class<?>[0], environment);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void load(Class<?> config, String... environment) {
|
|
|
|
|
Class<?>[] configs = config != null ? new Class<?>[] { config } : null;
|
|
|
|
|
load(configs, new Class<?>[0], environment);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void load(Class<?>[] configs, Class<?>[] autoConfigs,
|
|
|
|
|
String... environment) {
|
|
|
|
|
load(configs, autoConfigs, null, environment);
|
|
|
|
|
public void customPersistenceUnitManager() {
|
|
|
|
|
this.contextRunner.withUserConfiguration(
|
|
|
|
|
TestConfigurationWithCustomPersistenceUnitManager.class
|
|
|
|
|
).run((context) -> {
|
|
|
|
|
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = context
|
|
|
|
|
.getBean(LocalContainerEntityManagerFactoryBean.class);
|
|
|
|
|
Field field = LocalContainerEntityManagerFactoryBean.class
|
|
|
|
|
.getDeclaredField("persistenceUnitManager");
|
|
|
|
|
field.setAccessible(true);
|
|
|
|
|
assertThat(field.get(entityManagerFactoryBean))
|
|
|
|
|
.isEqualTo(context.getBean(PersistenceUnitManager.class));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void load(Class<?>[] configs, Class<?>[] autoConfigs,
|
|
|
|
|
ClassLoader classLoader, String... environment) {
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
|
|
|
|
if (classLoader != null) {
|
|
|
|
|
ctx.setClassLoader(classLoader);
|
|
|
|
|
}
|
|
|
|
|
TestPropertyValues.of(environment)
|
|
|
|
|
.and("spring.datasource.generate-unique-name=true").applyTo(ctx);
|
|
|
|
|
ctx.register(TestConfiguration.class);
|
|
|
|
|
if (!ObjectUtils.isEmpty(configs)) {
|
|
|
|
|
ctx.register(configs);
|
|
|
|
|
}
|
|
|
|
|
ctx.register(DataSourceAutoConfiguration.class,
|
|
|
|
|
TransactionAutoConfiguration.class,
|
|
|
|
|
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
|
|
|
|
|
if (!ObjectUtils.isEmpty(autoConfigs)) {
|
|
|
|
|
ctx.register(autoConfigs);
|
|
|
|
|
}
|
|
|
|
|
ctx.refresh();
|
|
|
|
|
this.context = ctx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String[] getInterceptorBeans(ApplicationContext context) {
|
|
|
|
|
return context.getBeanNamesForType(OpenEntityManagerInViewInterceptor.class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Configuration
|
|
|
|
|
@TestAutoConfigurationPackage(City.class)
|
|
|
|
|