Browse Source
Rework several aspects of database auto-configuration: - Use RelaxedPropertyResolver to obtain property values - Extract EmbeddedDatabaseConnection from EmbeddedDatabaseConfiguration - Rename several configuration classes for consistency Issue: #53028397pull/50/head
18 changed files with 504 additions and 377 deletions
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
/* |
||||
* Copyright 2012-2013 the original author or authors. |
||||
* |
||||
* 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.springframework.boot.autoconfigure.jdbc; |
||||
|
||||
import javax.annotation.PreDestroy; |
||||
import javax.sql.DataSource; |
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; |
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; |
||||
|
||||
/** |
||||
* Configuration for embedded data sources. |
||||
* |
||||
* @author Phillip Webb |
||||
* @see DataSourceAutoConfiguration |
||||
*/ |
||||
@Configuration |
||||
public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware { |
||||
|
||||
private EmbeddedDatabase database; |
||||
|
||||
private ClassLoader classLoader; |
||||
|
||||
@Override |
||||
public void setBeanClassLoader(ClassLoader classLoader) { |
||||
this.classLoader = classLoader; |
||||
} |
||||
|
||||
@Bean |
||||
public DataSource dataSource() { |
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder() |
||||
.setType(EmbeddedDatabaseConnection.get(this.classLoader).getType()); |
||||
this.database = builder.build(); |
||||
return this.database; |
||||
} |
||||
|
||||
@PreDestroy |
||||
public void close() { |
||||
if (this.database != null) { |
||||
this.database.shutdown(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,96 +0,0 @@
@@ -1,96 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2013 the original author or authors. |
||||
* |
||||
* 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.springframework.boot.autoconfigure.jdbc; |
||||
|
||||
import java.util.LinkedHashMap; |
||||
import java.util.Map; |
||||
|
||||
import javax.annotation.PreDestroy; |
||||
import javax.sql.DataSource; |
||||
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; |
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; |
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; |
||||
import org.springframework.util.ClassUtils; |
||||
|
||||
/** |
||||
* {@link EnableAutoConfiguration Auto-configuration} for embedded databases. |
||||
* |
||||
* @author Phillip Webb |
||||
*/ |
||||
@Configuration |
||||
public class EmbeddedDatabaseConfiguration { |
||||
|
||||
private static final Map<EmbeddedDatabaseType, String> EMBEDDED_DATABASE_DRIVER_CLASSES; |
||||
static { |
||||
Map<EmbeddedDatabaseType, String> drivers = new LinkedHashMap<EmbeddedDatabaseType, String>(); |
||||
drivers.put(EmbeddedDatabaseType.H2, "org.h2.Driver"); |
||||
drivers.put(EmbeddedDatabaseType.DERBY, "org.apache.derby.jdbc.EmbeddedDriver"); |
||||
drivers.put(EmbeddedDatabaseType.HSQL, "org.hsqldb.jdbcDriver"); |
||||
EMBEDDED_DATABASE_DRIVER_CLASSES = drivers; |
||||
} |
||||
|
||||
private static final Map<EmbeddedDatabaseType, String> EMBEDDED_DATABASE_URLS; |
||||
static { |
||||
Map<EmbeddedDatabaseType, String> urls = new LinkedHashMap<EmbeddedDatabaseType, String>(); |
||||
urls.put(EmbeddedDatabaseType.H2, "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1"); |
||||
urls.put(EmbeddedDatabaseType.DERBY, "jdbc:derby:memory:testdb;create=true"); |
||||
urls.put(EmbeddedDatabaseType.HSQL, "jdbc:hsqldb:mem:testdb"); |
||||
EMBEDDED_DATABASE_URLS = urls; |
||||
} |
||||
|
||||
private EmbeddedDatabase database; |
||||
|
||||
@Bean |
||||
public DataSource dataSource() { |
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder() |
||||
.setType(getEmbeddedDatabaseType()); |
||||
this.database = builder.build(); |
||||
return this.database; |
||||
} |
||||
|
||||
@PreDestroy |
||||
public void close() { |
||||
if (this.database != null) { |
||||
this.database.shutdown(); |
||||
} |
||||
} |
||||
|
||||
public static String getEmbeddedDatabaseDriverClass( |
||||
EmbeddedDatabaseType embeddedDatabaseType) { |
||||
return EMBEDDED_DATABASE_DRIVER_CLASSES.get(embeddedDatabaseType); |
||||
} |
||||
|
||||
public static String getEmbeddedDatabaseUrl(EmbeddedDatabaseType embeddedDatabaseType) { |
||||
return EMBEDDED_DATABASE_URLS.get(embeddedDatabaseType); |
||||
} |
||||
|
||||
public static EmbeddedDatabaseType getEmbeddedDatabaseType() { |
||||
for (Map.Entry<EmbeddedDatabaseType, String> entry : EMBEDDED_DATABASE_DRIVER_CLASSES |
||||
.entrySet()) { |
||||
if (ClassUtils.isPresent(entry.getValue(), |
||||
EmbeddedDatabaseConfiguration.class.getClassLoader())) { |
||||
return entry.getKey(); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,109 @@
@@ -0,0 +1,109 @@
|
||||
/* |
||||
* Copyright 2012-2013 the original author or authors. |
||||
* |
||||
* 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.springframework.boot.autoconfigure.jdbc; |
||||
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; |
||||
import org.springframework.util.ClassUtils; |
||||
|
||||
/** |
||||
* Connection details for {@link EmbeddedDatabaseType embedded databases}. |
||||
* |
||||
* @author Phillip Webb |
||||
* @author Dave Syer |
||||
* @see #get(ClassLoader) |
||||
*/ |
||||
public enum EmbeddedDatabaseConnection { |
||||
|
||||
/** |
||||
* No Connection. |
||||
*/ |
||||
NONE(null, null, null), |
||||
|
||||
/** |
||||
* H2 Database Connection. |
||||
*/ |
||||
H2(EmbeddedDatabaseType.H2, "org.h2.Driver", "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1"), |
||||
|
||||
/** |
||||
* Derby Database Connection. |
||||
*/ |
||||
DERBY(EmbeddedDatabaseType.DERBY, "org.apache.derby.jdbc.EmbeddedDriver", |
||||
"jdbc:derby:memory:testdb;create=true"), |
||||
|
||||
/** |
||||
* HSQL Database Connection. |
||||
*/ |
||||
HSQL(EmbeddedDatabaseType.HSQL, "org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:testdb"); |
||||
|
||||
private final EmbeddedDatabaseType type; |
||||
|
||||
private final String driverClass; |
||||
|
||||
private final String url; |
||||
|
||||
private EmbeddedDatabaseConnection(EmbeddedDatabaseType type, String driverClass, |
||||
String url) { |
||||
this.type = type; |
||||
this.driverClass = driverClass; |
||||
this.url = url; |
||||
} |
||||
|
||||
/** |
||||
* Returns the driver class name. |
||||
*/ |
||||
public String getDriverClassName() { |
||||
return this.driverClass; |
||||
} |
||||
|
||||
/** |
||||
* Returns the {@link EmbeddedDatabaseType} for the connection. |
||||
*/ |
||||
public EmbeddedDatabaseType getType() { |
||||
return this.type; |
||||
} |
||||
|
||||
/** |
||||
* Returns the URL for the connection. |
||||
*/ |
||||
public String getUrl() { |
||||
return this.url; |
||||
} |
||||
|
||||
/** |
||||
* Override for testing. |
||||
*/ |
||||
static EmbeddedDatabaseConnection override; |
||||
|
||||
/** |
||||
* Returns the most suitable {@link EmbeddedDatabaseConnection} for the given class
|
||||
* loader. |
||||
* @param classLoader the class loader used to check for classes |
||||
* @return an {@link EmbeddedDatabaseConnection} or {@link #NONE}. |
||||
*/ |
||||
public static EmbeddedDatabaseConnection get(ClassLoader classLoader) { |
||||
if (override != null) { |
||||
return override; |
||||
} |
||||
for (EmbeddedDatabaseConnection candidate : EmbeddedDatabaseConnection.values()) { |
||||
if (candidate != NONE |
||||
&& ClassUtils.isPresent(candidate.getDriverClassName(), classLoader)) { |
||||
return candidate; |
||||
} |
||||
} |
||||
return NONE; |
||||
} |
||||
} |
||||
@ -0,0 +1,162 @@
@@ -0,0 +1,162 @@
|
||||
/* |
||||
* Copyright 2012-2013 the original author or authors. |
||||
* |
||||
* 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.springframework.boot.autoconfigure.orm.jpa; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import javax.sql.DataSource; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Test; |
||||
import org.springframework.boot.TestUtils; |
||||
import org.springframework.boot.autoconfigure.ComponentScanDetectorConfiguration; |
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; |
||||
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.context.ApplicationContext; |
||||
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 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; |
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter; |
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; |
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; |
||||
|
||||
import static org.hamcrest.Matchers.equalTo; |
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertNotNull; |
||||
import static org.junit.Assert.assertThat; |
||||
import static org.junit.Assert.assertTrue; |
||||
|
||||
/** |
||||
* Base for JPA tests and tests for {@link JpaBaseConfiguration}. |
||||
* |
||||
* @author Phillip Webb |
||||
* @author Dave Syer |
||||
*/ |
||||
public abstract class AbstractJpaAutoConfigurationTests { |
||||
|
||||
protected AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); |
||||
|
||||
@After |
||||
public void close() { |
||||
this.context.close(); |
||||
} |
||||
|
||||
protected abstract Class<?> getAutoConfigureClass(); |
||||
|
||||
@Test |
||||
public void testEntityManagerCreated() throws Exception { |
||||
setupTestConfiguration(); |
||||
this.context.refresh(); |
||||
assertNotNull(this.context.getBean(DataSource.class)); |
||||
assertNotNull(this.context.getBean(JpaTransactionManager.class)); |
||||
} |
||||
|
||||
@Test |
||||
public void testDataSourceTransactionManagerNotCreated() throws Exception { |
||||
setupTestConfiguration(); |
||||
this.context.register(DataSourceTransactionManagerAutoConfiguration.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(TestConfiguration.class, |
||||
ComponentScanDetectorConfiguration.class, |
||||
EmbeddedDataSourceConfiguration.class, |
||||
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass()); |
||||
context.refresh(); |
||||
assertNotNull(context.getBean(OpenEntityManagerInViewInterceptor.class)); |
||||
context.close(); |
||||
} |
||||
|
||||
@Test |
||||
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenFilterPresent() |
||||
throws Exception { |
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); |
||||
context.register(TestFilterConfiguration.class, |
||||
ComponentScanDetectorConfiguration.class, |
||||
EmbeddedDataSourceConfiguration.class, |
||||
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass()); |
||||
context.refresh(); |
||||
assertEquals(0, getInterceptorBeans(context).length); |
||||
context.close(); |
||||
} |
||||
|
||||
@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, |
||||
EmbeddedDataSourceConfiguration.class, |
||||
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass()); |
||||
context.refresh(); |
||||
assertEquals(0, getInterceptorBeans(context).length); |
||||
context.close(); |
||||
} |
||||
|
||||
@Test |
||||
public void customJpaProperties() throws Exception { |
||||
TestUtils.addEnviroment(this.context, "spring.jpa.properties.a:b", |
||||
"spring.jpa.properties.c:d"); |
||||
setupTestConfiguration(); |
||||
this.context.refresh(); |
||||
LocalContainerEntityManagerFactoryBean bean = this.context |
||||
.getBean(LocalContainerEntityManagerFactoryBean.class); |
||||
Map<String, Object> map = bean.getJpaPropertyMap(); |
||||
assertThat(map.get("a"), equalTo((Object) "b")); |
||||
assertThat(map.get("c"), equalTo((Object) "d")); |
||||
} |
||||
|
||||
protected void setupTestConfiguration() { |
||||
this.context.register(TestConfiguration.class, |
||||
ComponentScanDetectorConfiguration.class, |
||||
EmbeddedDataSourceConfiguration.class, |
||||
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass()); |
||||
} |
||||
|
||||
private String[] getInterceptorBeans(ApplicationContext context) { |
||||
return context.getBeanNamesForType(OpenEntityManagerInViewInterceptor.class); |
||||
} |
||||
|
||||
@Configuration |
||||
@ComponentScan(basePackageClasses = { City.class }) |
||||
protected static class TestConfiguration { |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
@ComponentScan(basePackageClasses = { City.class }) |
||||
protected static class TestFilterConfiguration { |
||||
|
||||
@Bean |
||||
public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() { |
||||
return new OpenEntityManagerInViewFilter(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue