From ab121dc91b11ef4e947646f3dca99355b9f866fc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Sat, 18 May 2013 16:18:34 +0100 Subject: [PATCH] [bs-127] Add DataSourceTransactionManager if no others are in use * If the auto config class has a high Order it can check for an existing transaction manager * Unit tests added, and checked also witrh petclinic [Fixes #50064347] --- .../spring-bootstrap-actuator-sample/pom.xml | 10 --- .../sample/service/ProductionDatabase.java | 55 ---------------- ...ceTransactionManagerAutoConfiguration.java | 54 +++++++++++++++ .../main/resources/META-INF/spring.factories | 1 + ...nsactionManagerAutoConfigurationTests.java | 54 +++++++++++++++ .../HibernateJpaAutoConfigurationTests.java | 65 +++++++++++++++++++ .../autoconfigure/orm/jpa/test/City.java | 60 +++++++++++++++++ 7 files changed, 234 insertions(+), 65 deletions(-) delete mode 100644 spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/main/java/org/springframework/bootstrap/sample/service/ProductionDatabase.java create mode 100644 spring-bootstrap/src/main/java/org/springframework/bootstrap/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java create mode 100644 spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfigurationTests.java create mode 100644 spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java create mode 100644 spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/orm/jpa/test/City.java diff --git a/spring-bootstrap-samples/spring-bootstrap-actuator-sample/pom.xml b/spring-bootstrap-samples/spring-bootstrap-actuator-sample/pom.xml index c6268dcecb..c761d570b1 100644 --- a/spring-bootstrap-samples/spring-bootstrap-actuator-sample/pom.xml +++ b/spring-bootstrap-samples/spring-bootstrap-actuator-sample/pom.xml @@ -95,16 +95,6 @@ org.springframework.security spring-security-javaconfig - - org.apache.tomcat - tomcat-jdbc - - - mysql - mysql-connector-java - 5.1.23 - runtime - diff --git a/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/main/java/org/springframework/bootstrap/sample/service/ProductionDatabase.java b/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/main/java/org/springframework/bootstrap/sample/service/ProductionDatabase.java deleted file mode 100644 index 070c315cc5..0000000000 --- a/spring-bootstrap-samples/spring-bootstrap-actuator-sample/src/main/java/org/springframework/bootstrap/sample/service/ProductionDatabase.java +++ /dev/null @@ -1,55 +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.bootstrap.sample.service; - -import javax.sql.DataSource; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; - -/** - * @author Dave Syer - * - */ -@Configuration -@Profile("prod") -public class ProductionDatabase { - - @Value("${spring.database.driverClassName:com.mysql.jdbc.Driver}") - private String driverClassName; - - @Value("${spring.database.url:jdbc:mysql://localhost:3306/test}") - private String url; - - @Value("${spring.database.username:root}") - private String username; - - @Value("${spring.database.password:}") - private String password; - - @Bean - public DataSource dataSource() { - org.apache.tomcat.jdbc.pool.DataSource pool = new org.apache.tomcat.jdbc.pool.DataSource(); - pool.setDriverClassName(this.driverClassName); - pool.setUrl(this.url); - pool.setUsername(this.username); - pool.setPassword(this.password); - return pool; - } - -} diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java new file mode 100644 index 0000000000..271daff259 --- /dev/null +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java @@ -0,0 +1,54 @@ +/* + * 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.bootstrap.autoconfigure.jdbc; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.bootstrap.context.annotation.ConditionalOnBean; +import org.springframework.bootstrap.context.annotation.ConditionalOnClass; +import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * @author Dave Syer + * + */ +@Configuration +@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class }) +public class DataSourceTransactionManagerAutoConfiguration implements Ordered { + + @Override + public int getOrder() { + return Integer.MAX_VALUE; + } + + @Autowired(required = false) + private DataSource dataSource; + + @Bean + @ConditionalOnMissingBean(name = "transactionManager") + @ConditionalOnBean(DataSource.class) + public PlatformTransactionManager transactionManager() { + return new DataSourceTransactionManager(this.dataSource); + } + +} diff --git a/spring-bootstrap/src/main/resources/META-INF/spring.factories b/spring-bootstrap/src/main/resources/META-INF/spring.factories index ffa58f4d1d..d2e8106887 100644 --- a/spring-bootstrap/src/main/resources/META-INF/spring.factories +++ b/spring-bootstrap/src/main/resources/META-INF/spring.factories @@ -4,6 +4,7 @@ org.springframework.bootstrap.autoconfigure.MessageSourceAutoConfiguration,\ org.springframework.bootstrap.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.bootstrap.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.bootstrap.autoconfigure.data.JpaRepositoriesAutoConfiguration,\ +org.springframework.bootstrap.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ org.springframework.bootstrap.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.bootstrap.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ org.springframework.bootstrap.autoconfigure.web.EmbeddedContainerCustomizerConfiguration,\ diff --git a/spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfigurationTests.java b/spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfigurationTests.java new file mode 100644 index 0000000000..b61451aaef --- /dev/null +++ b/spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfigurationTests.java @@ -0,0 +1,54 @@ +/* + * 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.bootstrap.autoconfigure.jdbc; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Dave Syer + * + */ +public class DataSourceTransactionManagerAutoConfigurationTests { + + private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + + @Test + public void testDataSourceExists() throws Exception { + this.context.register(EmbeddedDatabaseConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class); + this.context.refresh(); + assertNotNull(this.context.getBean(DataSource.class)); + assertNotNull(this.context.getBean(DataSourceTransactionManager.class)); + } + + @Test + public void testNoDataSourceExists() throws Exception { + this.context.register(DataSourceTransactionManagerAutoConfiguration.class); + this.context.refresh(); + assertEquals(0, this.context.getBeanNamesForType(DataSource.class).length); + assertEquals( + 0, + this.context.getBeanNamesForType(DataSourceTransactionManager.class).length); + } + +} diff --git a/spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java b/spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java new file mode 100644 index 0000000000..7cf26e6147 --- /dev/null +++ b/spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java @@ -0,0 +1,65 @@ +/* + * 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.bootstrap.autoconfigure.orm.jpa; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.springframework.bootstrap.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.bootstrap.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.bootstrap.autoconfigure.jdbc.EmbeddedDatabaseConfiguration; +import org.springframework.bootstrap.autoconfigure.orm.jpa.test.City; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.orm.jpa.JpaTransactionManager; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Dave Syer + * + */ +public class HibernateJpaAutoConfigurationTests { + + private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + + @Test + public void testEntityManagerCreated() throws Exception { + this.context.register(EmbeddedDatabaseConfiguration.class, + HibernateJpaAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class); + this.context.refresh(); + assertNotNull(this.context.getBean(DataSource.class)); + assertNotNull(this.context.getBean(JpaTransactionManager.class)); + } + + @Test + public void testDataSourceTransactionManagerNotCreated() throws Exception { + this.context.register(EmbeddedDatabaseConfiguration.class, + HibernateJpaAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class); + this.context.refresh(); + assertNotNull(this.context.getBean(DataSource.class)); + assertTrue(this.context.getBean("transactionManager") instanceof JpaTransactionManager); + } + + @ComponentScan(basePackageClasses = { City.class }) + protected static class TestConfiguration { + + } +} diff --git a/spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/orm/jpa/test/City.java b/spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/orm/jpa/test/City.java new file mode 100644 index 0000000000..6a235d6004 --- /dev/null +++ b/spring-bootstrap/src/test/java/org/springframework/bootstrap/autoconfigure/orm/jpa/test/City.java @@ -0,0 +1,60 @@ +package org.springframework.bootstrap.autoconfigure.orm.jpa.test; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class City implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue + private Long id; + + @Column(nullable = false) + private String name; + + @Column(nullable = false) + private String state; + + @Column(nullable = false) + private String country; + + @Column(nullable = false) + private String map; + + protected City() { + } + + public City(String name, String country) { + super(); + this.name = name; + this.country = country; + } + + public String getName() { + return this.name; + } + + public String getState() { + return this.state; + } + + public String getCountry() { + return this.country; + } + + public String getMap() { + return this.map; + } + + @Override + public String toString() { + return getName() + "," + getState() + "," + getCountry(); + } +}