Commit 2a22a7af authored by Phillip Webb's avatar Phillip Webb Committed by Stephane Nicoll

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
parent b488a3d9
...@@ -16,18 +16,21 @@ ...@@ -16,18 +16,21 @@
package org.springframework.boot.autoconfigure.orm.jpa; package org.springframework.boot.autoconfigure.orm.jpa;
import java.net.URL;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource; 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.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.ApplicationInfo;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages; import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
...@@ -50,6 +53,7 @@ import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; ...@@ -50,6 +53,7 @@ import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager; 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.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
...@@ -65,6 +69,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter ...@@ -65,6 +69,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
@Import(DataSourceInitializedPublisher.Registrar.class) @Import(DataSourceInitializedPublisher.Registrar.class)
public abstract class JpaBaseConfiguration implements BeanFactoryAware { public abstract class JpaBaseConfiguration implements BeanFactoryAware {
private final Log logger = LogFactory.getLog(getClass());
private final DataSource dataSource; private final DataSource dataSource;
private final JpaProperties properties; private final JpaProperties properties;
...@@ -104,11 +110,9 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { ...@@ -104,11 +110,9 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware {
ObjectProvider<PersistenceUnitManager> persistenceUnitManagerProvider) { ObjectProvider<PersistenceUnitManager> persistenceUnitManagerProvider) {
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder( EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(
jpaVendorAdapter, this.properties.getProperties(), jpaVendorAdapter, this.properties.getProperties(),
persistenceUnitManagerProvider.getIfAvailable()); persistenceUnitManagerProvider.getIfAvailable(),
determinePersistenceUnitRootLocation());
builder.setCallback(getVendorCallback()); builder.setCallback(getVendorCallback());
if (this.beanFactory.containsBean("springApplicationInfo")) {
builder.setApplicationInfo(this.beanFactory.getBean(ApplicationInfo.class));
}
return builder; return builder;
} }
...@@ -186,6 +190,19 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { ...@@ -186,6 +190,19 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; 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 @Configuration
@ConditionalOnWebApplication @ConditionalOnWebApplication
@ConditionalOnClass(WebMvcConfigurerAdapter.class) @ConditionalOnClass(WebMvcConfigurerAdapter.class)
......
...@@ -94,8 +94,8 @@ You can also use the `spring.main.banner-mode` property to determine if the bann ...@@ -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 to be printed on `System.out` (`console`), using the configured logger (`log`) or not
at all (`off`). at all (`off`).
The printed banner will be available via an `ApplicationInfo` registered as a singleton The printed banner will be registered as a singleton bean under the name
bean under the name `springApplicationInfo`. `springBootBanner`.
[NOTE] [NOTE]
==== ====
......
...@@ -11,9 +11,9 @@ welcome = { -> ...@@ -11,9 +11,9 @@ welcome = { ->
// Try to print using the banner interface // Try to print using the banner interface
if (beanFactory != null) { if (beanFactory != null) {
try { try {
def appInfo = beanFactory.getBean("springApplicationInfo") def banner = beanFactory.getBean("springBootBanner")
def out = new java.io.ByteArrayOutputStream() 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() return out.toString()
} catch (Exception ex) { } catch (Exception ex) {
// Ignore // Ignore
......
/*
* 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;
}
}
...@@ -359,10 +359,6 @@ public class SpringApplication { ...@@ -359,10 +359,6 @@ public class SpringApplication {
if (printedBanner != null) { if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner); context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
} }
ApplicationInfo applicationInfo = new ApplicationInfo(this, applicationArguments,
printedBanner);
context.getBeanFactory().registerSingleton("springApplicationInfo",
applicationInfo);
// Load the sources // Load the sources
Set<Object> sources = getSources(); Set<Object> sources = getSources();
......
...@@ -28,12 +28,10 @@ import javax.sql.DataSource; ...@@ -28,12 +28,10 @@ import javax.sql.DataSource;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.boot.ApplicationInfo;
import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager; import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.ResourceUtils;
/** /**
* Convenient builder for JPA EntityManagerFactory instances. Collects common * Convenient builder for JPA EntityManagerFactory instances. Collects common
...@@ -53,15 +51,15 @@ public class EntityManagerFactoryBuilder { ...@@ -53,15 +51,15 @@ public class EntityManagerFactoryBuilder {
private static final Log logger = LogFactory private static final Log logger = LogFactory
.getLog(EntityManagerFactoryBuilder.class); .getLog(EntityManagerFactoryBuilder.class);
private JpaVendorAdapter jpaVendorAdapter; private final JpaVendorAdapter jpaVendorAdapter;
private PersistenceUnitManager persistenceUnitManager; private final PersistenceUnitManager persistenceUnitManager;
private Map<String, Object> jpaProperties; private final Map<String, Object> 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 * Create a new instance passing in the common pieces that will be shared if multiple
...@@ -73,9 +71,27 @@ public class EntityManagerFactoryBuilder { ...@@ -73,9 +71,27 @@ public class EntityManagerFactoryBuilder {
*/ */
public EntityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter, public EntityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
Map<String, ?> jpaProperties, PersistenceUnitManager persistenceUnitManager) { Map<String, ?> 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<String, ?> jpaProperties, PersistenceUnitManager persistenceUnitManager,
URL persistenceUnitRootLocation) {
this.jpaVendorAdapter = jpaVendorAdapter; this.jpaVendorAdapter = jpaVendorAdapter;
this.persistenceUnitManager = persistenceUnitManager; this.persistenceUnitManager = persistenceUnitManager;
this.jpaProperties = new LinkedHashMap<String, Object>(jpaProperties); this.jpaProperties = new LinkedHashMap<String, Object>(jpaProperties);
this.persistenceUnitRootLocation = persistenceUnitRootLocation;
} }
public Builder dataSource(DataSource dataSource) { public Builder dataSource(DataSource dataSource) {
...@@ -90,33 +106,6 @@ public class EntityManagerFactoryBuilder { ...@@ -90,33 +106,6 @@ public class EntityManagerFactoryBuilder {
this.callback = callback; 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. * A fluent builder for a LocalContainerEntityManagerFactoryBean.
*/ */
...@@ -220,9 +209,9 @@ public class EntityManagerFactoryBuilder { ...@@ -220,9 +209,9 @@ public class EntityManagerFactoryBuilder {
entityManagerFactoryBean.getJpaPropertyMap() entityManagerFactoryBean.getJpaPropertyMap()
.putAll(EntityManagerFactoryBuilder.this.jpaProperties); .putAll(EntityManagerFactoryBuilder.this.jpaProperties);
entityManagerFactoryBean.getJpaPropertyMap().putAll(this.properties); entityManagerFactoryBean.getJpaPropertyMap().putAll(this.properties);
String rootLocation = determinePersistenceUnitRootLocation(); URL rootLocation = EntityManagerFactoryBuilder.this.persistenceUnitRootLocation;
if (rootLocation != null) { if (rootLocation != null) {
entityManagerFactoryBean.setPersistenceUnitRootLocation(rootLocation); entityManagerFactoryBean.setPersistenceUnitRootLocation(rootLocation.toString());
} }
if (EntityManagerFactoryBuilder.this.callback != null) { if (EntityManagerFactoryBuilder.this.callback != null) {
EntityManagerFactoryBuilder.this.callback EntityManagerFactoryBuilder.this.callback
......
...@@ -100,9 +100,6 @@ public class BannerTests { ...@@ -100,9 +100,6 @@ public class BannerTests {
application.setWebEnvironment(false); application.setWebEnvironment(false);
this.context = application.run(); this.context = application.run();
assertThat(this.context.containsBean("springBootBanner")).isTrue(); assertThat(this.context.containsBean("springBootBanner")).isTrue();
assertThat(this.context.containsBean("springApplicationInfo")).isTrue();
assertThat(this.context.getBean("springApplicationInfo", ApplicationInfo.class)
.getBanner()).isNotNull();
} }
@Test @Test
...@@ -112,9 +109,7 @@ public class BannerTests { ...@@ -112,9 +109,7 @@ public class BannerTests {
Banner banner = mock(Banner.class); Banner banner = mock(Banner.class);
application.setBanner(banner); application.setBanner(banner);
this.context = application.run(); this.context = application.run();
ApplicationInfo applicationInfo = this.context.getBean("springApplicationInfo", Banner printedBanner = (Banner) this.context.getBean("springBootBanner");
ApplicationInfo.class);
Banner printedBanner = applicationInfo.getBanner();
assertThat(ReflectionTestUtils.getField(printedBanner, "banner")) assertThat(ReflectionTestUtils.getField(printedBanner, "banner"))
.isEqualTo(banner); .isEqualTo(banner);
verify(banner).printBanner(any(Environment.class), verify(banner).printBanner(any(Environment.class),
...@@ -132,8 +127,6 @@ public class BannerTests { ...@@ -132,8 +127,6 @@ public class BannerTests {
application.setWebEnvironment(false); application.setWebEnvironment(false);
this.context = application.run(); this.context = application.run();
assertThat(this.context.containsBean("springBootBanner")).isFalse(); assertThat(this.context.containsBean("springBootBanner")).isFalse();
assertThat(this.context.getBean("springApplicationInfo", ApplicationInfo.class)
.getBanner()).isNull();
} }
@Test @Test
...@@ -150,8 +143,6 @@ public class BannerTests { ...@@ -150,8 +143,6 @@ public class BannerTests {
this.context = application.run(); this.context = application.run();
assertThat(this.out.toString()).contains("I printed a deprecated banner"); assertThat(this.out.toString()).contains("I printed a deprecated banner");
assertThat(this.context.containsBean("springBootBanner")).isFalse(); assertThat(this.context.containsBean("springBootBanner")).isFalse();
assertThat(this.context.getBean("springApplicationInfo", ApplicationInfo.class)
.getBanner()).isNull();
} }
static class DummyBanner implements Banner { static class DummyBanner implements Banner {
......
...@@ -778,21 +778,6 @@ public class SpringApplicationTests { ...@@ -778,21 +778,6 @@ public class SpringApplicationTests {
assertThat(System.getProperty("java.awt.headless")).isEqualTo("false"); 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 @Test
public void getApplicationArgumentsBean() throws Exception { public void getApplicationArgumentsBean() throws Exception {
TestSpringApplication application = new TestSpringApplication( TestSpringApplication application = new TestSpringApplication(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment