From 2a22a7af123a0a38b2b8de7368930d85e24ac21b Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 29 Aug 2016 22:53:15 +0100 Subject: [PATCH] Remove ApplicationInfo Rework commit 4a69755b to remove the need for the ApplicationInfo class. The updated code now uses the auto-configuration class to compute a default persistence unit root location Closes gh-6635 --- .../orm/jpa/JpaBaseConfiguration.java | 27 ++++++-- .../main/asciidoc/spring-boot-features.adoc | 4 +- .../resources/commands/crash/login.groovy | 4 +- .../springframework/boot/ApplicationInfo.java | 65 ------------------- .../boot/SpringApplication.java | 4 -- .../orm/jpa/EntityManagerFactoryBuilder.java | 61 +++++++---------- .../org/springframework/boot/BannerTests.java | 11 +--- .../boot/SpringApplicationTests.java | 15 ----- 8 files changed, 52 insertions(+), 139 deletions(-) delete mode 100644 spring-boot/src/main/java/org/springframework/boot/ApplicationInfo.java diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java index 5191e41296..d6b304eb8e 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java @@ -16,18 +16,21 @@ package org.springframework.boot.autoconfigure.orm.jpa; +import java.net.URL; import java.util.List; import java.util.Map; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.boot.ApplicationInfo; import org.springframework.boot.autoconfigure.AutoConfigurationPackages; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -50,6 +53,7 @@ import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.jta.JtaTransactionManager; +import org.springframework.util.ResourceUtils; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @@ -65,6 +69,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter @Import(DataSourceInitializedPublisher.Registrar.class) public abstract class JpaBaseConfiguration implements BeanFactoryAware { + private final Log logger = LogFactory.getLog(getClass()); + private final DataSource dataSource; private final JpaProperties properties; @@ -104,11 +110,9 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { ObjectProvider persistenceUnitManagerProvider) { EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder( jpaVendorAdapter, this.properties.getProperties(), - persistenceUnitManagerProvider.getIfAvailable()); + persistenceUnitManagerProvider.getIfAvailable(), + determinePersistenceUnitRootLocation()); builder.setCallback(getVendorCallback()); - if (this.beanFactory.containsBean("springApplicationInfo")) { - builder.setApplicationInfo(this.beanFactory.getBean(ApplicationInfo.class)); - } return builder; } @@ -186,6 +190,19 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } + private URL determinePersistenceUnitRootLocation() { + Class source = getClass(); + try { + URL url = source.getProtectionDomain().getCodeSource().getLocation(); + return ResourceUtils.extractJarFileURL(url); + } + catch (Exception ex) { + logger.info("Could not determine persistence " + + "unit root location from " + source + " : " + ex); + } + return null; + } + @Configuration @ConditionalOnWebApplication @ConditionalOnClass(WebMvcConfigurerAdapter.class) diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 5a76b80402..13fa1a572a 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -94,8 +94,8 @@ You can also use the `spring.main.banner-mode` property to determine if the bann to be printed on `System.out` (`console`), using the configured logger (`log`) or not at all (`off`). -The printed banner will be available via an `ApplicationInfo` registered as a singleton -bean under the name `springApplicationInfo`. +The printed banner will be registered as a singleton bean under the name +`springBootBanner`. [NOTE] ==== diff --git a/spring-boot-starters/spring-boot-starter-remote-shell/src/main/resources/commands/crash/login.groovy b/spring-boot-starters/spring-boot-starter-remote-shell/src/main/resources/commands/crash/login.groovy index d260b1563d..465bd4a012 100644 --- a/spring-boot-starters/spring-boot-starter-remote-shell/src/main/resources/commands/crash/login.groovy +++ b/spring-boot-starters/spring-boot-starter-remote-shell/src/main/resources/commands/crash/login.groovy @@ -11,9 +11,9 @@ welcome = { -> // Try to print using the banner interface if (beanFactory != null) { try { - def appInfo = beanFactory.getBean("springApplicationInfo") + def banner = beanFactory.getBean("springBootBanner") def out = new java.io.ByteArrayOutputStream() - appInfo.banner.printBanner(environment, null, new java.io.PrintStream(out)) + banner.printBanner(environment, null, new java.io.PrintStream(out)) return out.toString() } catch (Exception ex) { // Ignore diff --git a/spring-boot/src/main/java/org/springframework/boot/ApplicationInfo.java b/spring-boot/src/main/java/org/springframework/boot/ApplicationInfo.java deleted file mode 100644 index ba6b56c9a5..0000000000 --- a/spring-boot/src/main/java/org/springframework/boot/ApplicationInfo.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2012-2016 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; - -/** - * Provide application-related information such as the {@link ApplicationArguments} and - * the {@link Banner}. - * - * @author Stephane Nicoll - * @since 1.4.1 - */ -public final class ApplicationInfo { - - private final Class mainApplicationClass; - - private final ApplicationArguments applicationArguments; - - private final Banner banner; - - protected ApplicationInfo(SpringApplication application, - ApplicationArguments applicationArguments, Banner banner) { - this.mainApplicationClass = application.getMainApplicationClass(); - this.applicationArguments = applicationArguments; - this.banner = banner; - } - - /** - * Returns the main application class that has been deduced or explicitly configured. - * @return the main application class or {@code null} - */ - public Class getMainApplicationClass() { - return this.mainApplicationClass; - } - - /** - * Returns the {@link ApplicationArguments} used to start this instance. - * @return the application arguments - */ - public ApplicationArguments getApplicationArguments() { - return this.applicationArguments; - } - - /** - * Returns the {@link Banner} used by this instance. - * @return the banner or {@code null} - */ - public Banner getBanner() { - return this.banner; - } - -} diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 65d1190299..d38392cdbe 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -359,10 +359,6 @@ public class SpringApplication { if (printedBanner != null) { context.getBeanFactory().registerSingleton("springBootBanner", printedBanner); } - ApplicationInfo applicationInfo = new ApplicationInfo(this, applicationArguments, - printedBanner); - context.getBeanFactory().registerSingleton("springApplicationInfo", - applicationInfo); // Load the sources Set sources = getSources(); diff --git a/spring-boot/src/main/java/org/springframework/boot/orm/jpa/EntityManagerFactoryBuilder.java b/spring-boot/src/main/java/org/springframework/boot/orm/jpa/EntityManagerFactoryBuilder.java index 61a57feecf..03aec6b2c0 100644 --- a/spring-boot/src/main/java/org/springframework/boot/orm/jpa/EntityManagerFactoryBuilder.java +++ b/spring-boot/src/main/java/org/springframework/boot/orm/jpa/EntityManagerFactoryBuilder.java @@ -28,12 +28,10 @@ import javax.sql.DataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.boot.ApplicationInfo; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager; import org.springframework.util.ClassUtils; -import org.springframework.util.ResourceUtils; /** * Convenient builder for JPA EntityManagerFactory instances. Collects common @@ -53,15 +51,15 @@ public class EntityManagerFactoryBuilder { private static final Log logger = LogFactory .getLog(EntityManagerFactoryBuilder.class); - private JpaVendorAdapter jpaVendorAdapter; + private final JpaVendorAdapter jpaVendorAdapter; - private PersistenceUnitManager persistenceUnitManager; + private final PersistenceUnitManager persistenceUnitManager; - private Map jpaProperties; + private final Map jpaProperties; - private EntityManagerFactoryBeanCallback callback; + private final URL persistenceUnitRootLocation; - private Class applicationClass; + private EntityManagerFactoryBeanCallback callback; /** * Create a new instance passing in the common pieces that will be shared if multiple @@ -73,9 +71,27 @@ public class EntityManagerFactoryBuilder { */ public EntityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter, Map jpaProperties, PersistenceUnitManager persistenceUnitManager) { + this(jpaVendorAdapter, jpaProperties, persistenceUnitManager, null); + } + + /** + * Create a new instance passing in the common pieces that will be shared if multiple + * EntityManagerFactory instances are created. + * @param jpaVendorAdapter a vendor adapter + * @param jpaProperties JPA properties to be passed to the persistence provider. + * @param persistenceUnitManager optional source of persistence unit information (can + * be null) + * @param persistenceUnitRootLocation the persistence unit root location to use as a + * fallback (can be null) + * @since 1.4.1 + */ + public EntityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter, + Map jpaProperties, PersistenceUnitManager persistenceUnitManager, + URL persistenceUnitRootLocation) { this.jpaVendorAdapter = jpaVendorAdapter; this.persistenceUnitManager = persistenceUnitManager; this.jpaProperties = new LinkedHashMap(jpaProperties); + this.persistenceUnitRootLocation = persistenceUnitRootLocation; } public Builder dataSource(DataSource dataSource) { @@ -90,33 +106,6 @@ public class EntityManagerFactoryBuilder { this.callback = callback; } - /** - * An optional {@link ApplicationInfo} used to further tune the entity manager. - * @param applicationInfo the application info - */ - public void setApplicationInfo(ApplicationInfo applicationInfo) { - this.applicationClass = applicationInfo.getMainApplicationClass(); - } - - /** - * Determine a persistence unit root location to use if no {@code persistence.xml} or - * {@code orm.xml} are present in the project. - * @return the persistence unit root location or {@code null} - */ - protected String determinePersistenceUnitRootLocation() { - if (this.applicationClass != null) { - try { - URL mainLocation = this.applicationClass.getProtectionDomain() - .getCodeSource().getLocation(); - return ResourceUtils.extractJarFileURL(mainLocation).toString(); - } - catch (Exception ex) { - logger.info("Could not determine persistence unit root location: " + ex); - } - } - return null; - } - /** * A fluent builder for a LocalContainerEntityManagerFactoryBean. */ @@ -220,9 +209,9 @@ public class EntityManagerFactoryBuilder { entityManagerFactoryBean.getJpaPropertyMap() .putAll(EntityManagerFactoryBuilder.this.jpaProperties); entityManagerFactoryBean.getJpaPropertyMap().putAll(this.properties); - String rootLocation = determinePersistenceUnitRootLocation(); + URL rootLocation = EntityManagerFactoryBuilder.this.persistenceUnitRootLocation; if (rootLocation != null) { - entityManagerFactoryBean.setPersistenceUnitRootLocation(rootLocation); + entityManagerFactoryBean.setPersistenceUnitRootLocation(rootLocation.toString()); } if (EntityManagerFactoryBuilder.this.callback != null) { EntityManagerFactoryBuilder.this.callback diff --git a/spring-boot/src/test/java/org/springframework/boot/BannerTests.java b/spring-boot/src/test/java/org/springframework/boot/BannerTests.java index 59b1833e85..b8efaa65b5 100644 --- a/spring-boot/src/test/java/org/springframework/boot/BannerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/BannerTests.java @@ -100,9 +100,6 @@ public class BannerTests { application.setWebEnvironment(false); this.context = application.run(); assertThat(this.context.containsBean("springBootBanner")).isTrue(); - assertThat(this.context.containsBean("springApplicationInfo")).isTrue(); - assertThat(this.context.getBean("springApplicationInfo", ApplicationInfo.class) - .getBanner()).isNotNull(); } @Test @@ -112,9 +109,7 @@ public class BannerTests { Banner banner = mock(Banner.class); application.setBanner(banner); this.context = application.run(); - ApplicationInfo applicationInfo = this.context.getBean("springApplicationInfo", - ApplicationInfo.class); - Banner printedBanner = applicationInfo.getBanner(); + Banner printedBanner = (Banner) this.context.getBean("springBootBanner"); assertThat(ReflectionTestUtils.getField(printedBanner, "banner")) .isEqualTo(banner); verify(banner).printBanner(any(Environment.class), @@ -132,8 +127,6 @@ public class BannerTests { application.setWebEnvironment(false); this.context = application.run(); assertThat(this.context.containsBean("springBootBanner")).isFalse(); - assertThat(this.context.getBean("springApplicationInfo", ApplicationInfo.class) - .getBanner()).isNull(); } @Test @@ -150,8 +143,6 @@ public class BannerTests { this.context = application.run(); assertThat(this.out.toString()).contains("I printed a deprecated banner"); assertThat(this.context.containsBean("springBootBanner")).isFalse(); - assertThat(this.context.getBean("springApplicationInfo", ApplicationInfo.class) - .getBanner()).isNull(); } static class DummyBanner implements Banner { diff --git a/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java b/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java index 16d2ca22a4..10aafc820e 100644 --- a/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -778,21 +778,6 @@ public class SpringApplicationTests { assertThat(System.getProperty("java.awt.headless")).isEqualTo("false"); } - @Test - public void getApplicationInfo() { - TestSpringApplication application = new TestSpringApplication( - ExampleConfig.class); - application.setWebEnvironment(false); - this.context = application.run("foo"); - ApplicationInfo applicationInfo = this.context.getBean(ApplicationInfo.class); - assertThat(application.getMainApplicationClass()) - .isEqualTo(application.getMainApplicationClass()); - assertThat(applicationInfo.getApplicationArguments()).isNotNull(); - assertThat(applicationInfo.getApplicationArguments().getNonOptionArgs()) - .containsExactly("foo"); - assertThat(applicationInfo.getBanner()).isNotNull(); - } - @Test public void getApplicationArgumentsBean() throws Exception { TestSpringApplication application = new TestSpringApplication(