Merge branch '1.5.x'

This commit is contained in:
Phillip Webb 2016-10-11 23:42:14 -07:00
commit 01900c8342
25 changed files with 130 additions and 118 deletions

View File

@ -89,14 +89,13 @@ public class AutoConfigurationReportEndpoint extends AbstractEndpoint<Report> {
add(this.negativeMatches, entry.getKey(), entry.getValue()); add(this.negativeMatches, entry.getKey(), entry.getValue());
} }
} }
this.parent = report.getParent() != null ? new Report(report.getParent()) boolean hasParent = report.getParent() != null;
: null; this.parent = (hasParent ? new Report(report.getParent()) : null);
} }
private void add(Map<String, MessageAndConditions> map, String source, private void add(Map<String, MessageAndConditions> map, String source,
ConditionAndOutcomes conditionAndOutcomes) { ConditionAndOutcomes conditionAndOutcomes) {
String name = ClassUtils.getShortName(source); String name = ClassUtils.getShortName(source);
map.put(name, new MessageAndConditions(conditionAndOutcomes)); map.put(name, new MessageAndConditions(conditionAndOutcomes));
} }

View File

@ -42,7 +42,8 @@ public abstract class AbstractDatabaseInitializer {
private final ResourceLoader resourceLoader; private final ResourceLoader resourceLoader;
protected AbstractDatabaseInitializer(DataSource dataSource, ResourceLoader resourceLoader) { protected AbstractDatabaseInitializer(DataSource dataSource,
ResourceLoader resourceLoader) {
Assert.notNull(dataSource, "DataSource must not be null"); Assert.notNull(dataSource, "DataSource must not be null");
Assert.notNull(resourceLoader, "ResourceLoader must not be null"); Assert.notNull(resourceLoader, "ResourceLoader must not be null");
this.dataSource = dataSource; this.dataSource = dataSource;
@ -51,17 +52,18 @@ public abstract class AbstractDatabaseInitializer {
@PostConstruct @PostConstruct
protected void initialize() { protected void initialize() {
if (isEnabled()) { if (!isEnabled()) {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); return;
String schemaLocation = getSchemaLocation();
if (schemaLocation.contains(PLATFORM_PLACEHOLDER)) {
String platform = getDatabaseName();
schemaLocation = schemaLocation.replace(PLATFORM_PLACEHOLDER, platform);
}
populator.addScript(this.resourceLoader.getResource(schemaLocation));
populator.setContinueOnError(true);
DatabasePopulatorUtils.execute(populator, this.dataSource);
} }
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
String schemaLocation = getSchemaLocation();
if (schemaLocation.contains(PLATFORM_PLACEHOLDER)) {
String platform = getDatabaseName();
schemaLocation = schemaLocation.replace(PLATFORM_PLACEHOLDER, platform);
}
populator.addScript(this.resourceLoader.getResource(schemaLocation));
populator.setContinueOnError(true);
DatabasePopulatorUtils.execute(populator, this.dataSource);
} }
protected abstract boolean isEnabled(); protected abstract boolean isEnabled();
@ -70,11 +72,10 @@ public abstract class AbstractDatabaseInitializer {
protected String getDatabaseName() { protected String getDatabaseName() {
try { try {
String databaseProductName = JdbcUtils.extractDatabaseMetaData( String productName = JdbcUtils.commonDatabaseName(JdbcUtils
this.dataSource, "getDatabaseProductName").toString(); .extractDatabaseMetaData(this.dataSource, "getDatabaseProductName")
databaseProductName = JdbcUtils.commonDatabaseName(databaseProductName); .toString());
DatabaseDriver databaseDriver = DatabaseDriver.fromProductName( DatabaseDriver databaseDriver = DatabaseDriver.fromProductName(productName);
databaseProductName);
if (databaseDriver == DatabaseDriver.UNKNOWN) { if (databaseDriver == DatabaseDriver.UNKNOWN) {
throw new IllegalStateException("Unable to detect database type"); throw new IllegalStateException("Unable to detect database type");
} }

View File

@ -32,8 +32,8 @@ public class BatchDatabaseInitializer extends AbstractDatabaseInitializer {
private final BatchProperties properties; private final BatchProperties properties;
public BatchDatabaseInitializer(DataSource dataSource, public BatchDatabaseInitializer(DataSource dataSource, ResourceLoader resourceLoader,
ResourceLoader resourceLoader, BatchProperties properties) { BatchProperties properties) {
super(dataSource, resourceLoader); super(dataSource, resourceLoader);
Assert.notNull(properties, "BatchProperties must not be null"); Assert.notNull(properties, "BatchProperties must not be null");
this.properties = properties; this.properties = properties;

View File

@ -65,8 +65,7 @@ public class RepositoryRestProperties {
/** /**
* Strategy to use to determine which repositories get exposed. * Strategy to use to determine which repositories get exposed.
*/ */
private RepositoryDetectionStrategies detectionStrategy = private RepositoryDetectionStrategies detectionStrategy = RepositoryDetectionStrategies.DEFAULT;
RepositoryDetectionStrategies.DEFAULT;
/** /**
* Content type to use as a default when none is specified. * Content type to use as a default when none is specified.

View File

@ -41,7 +41,7 @@ import org.springframework.jms.support.destination.DestinationResolver;
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@Configuration @Configuration
@ConditionalOnClass({Message.class, JmsTemplate.class}) @ConditionalOnClass({ Message.class, JmsTemplate.class })
@ConditionalOnBean(ConnectionFactory.class) @ConditionalOnBean(ConnectionFactory.class)
@EnableConfigurationProperties(JmsProperties.class) @EnableConfigurationProperties(JmsProperties.class)
@Import(JmsAnnotationDrivenConfiguration.class) @Import(JmsAnnotationDrivenConfiguration.class)

View File

@ -135,8 +135,8 @@ public class JmsProperties {
public static class Template { public static class Template {
/** /**
* Default destination to use on send/receive operations that do not * Default destination to use on send/receive operations that do not have a
* have a destination parameter. * destination parameter.
*/ */
private String defaultDestination; private String defaultDestination;
@ -156,16 +156,14 @@ public class JmsProperties {
private Integer priority; private Integer priority;
/** /**
* Time-to-live of a message when sending in milliseconds. Enable * Time-to-live of a message when sending in milliseconds. Enable QoS when set.
* QoS when set.
*/ */
private Long timeToLive; private Long timeToLive;
/** /**
* Enable explicit QoS when sending a message. When enabled, the * Enable explicit QoS when sending a message. When enabled, the delivery mode,
* delivery mode, priority and time-to-live properties will be * priority and time-to-live properties will be used when sending a message. QoS
* used when sending a message. QoS is automatically enabled when * is automatically enabled when at least one of those settings is customized.
* at least one of those settings is customized.
*/ */
private Boolean qosEnabled; private Boolean qosEnabled;
@ -291,8 +289,8 @@ public class JmsProperties {
NON_PERSISTENT(1), NON_PERSISTENT(1),
/* /*
* Instructs the JMS provider to log the message to stable storage as part of * Instructs the JMS provider to log the message to stable storage as part of the
* the client's send operation. * client's send operation.
*/ */
PERSISTENT(2); PERSISTENT(2);

View File

@ -658,15 +658,15 @@ public class ServerProperties
private Charset uriEncoding; private Charset uriEncoding;
/** /**
* Maximum number of connections that the server will accept and process * Maximum number of connections that the server will accept and process at any
* at any given time. Once the limit has been reached, the operating system * given time. Once the limit has been reached, the operating system may still
* may still accept connections based on the "acceptCount" property. * accept connections based on the "acceptCount" property.
*/ */
private int maxConnections = 0; private int maxConnections = 0;
/** /**
* Maximum queue length for incoming connection requests when all possible * Maximum queue length for incoming connection requests when all possible request
* request processing threads are in use. * processing threads are in use.
*/ */
private int acceptCount = 0; private int acceptCount = 0;
@ -827,34 +827,37 @@ public class ServerProperties
public void customize(Connector connector) { public void customize(Connector connector) {
ProtocolHandler handler = connector.getProtocolHandler(); ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) { if (handler instanceof AbstractProtocol) {
AbstractProtocol protocol = (AbstractProtocol) handler; AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
protocol.setBacklog(Tomcat.this.acceptCount); protocol.setBacklog(Tomcat.this.acceptCount);
} }
} }
}); });
} }
private void customizeMaxConnections(TomcatEmbeddedServletContainerFactory factory) { private void customizeMaxConnections(
TomcatEmbeddedServletContainerFactory factory) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override @Override
public void customize(Connector connector) { public void customize(Connector connector) {
ProtocolHandler handler = connector.getProtocolHandler(); ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) { if (handler instanceof AbstractProtocol) {
AbstractProtocol protocol = (AbstractProtocol) handler; AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
protocol.setMaxConnections(Tomcat.this.maxConnections); protocol.setMaxConnections(Tomcat.this.maxConnections);
} }
} }
}); });
} }
private void customizeConnectionTimeout( private void customizeConnectionTimeout(
TomcatEmbeddedServletContainerFactory factory, int connectionTimeout) { TomcatEmbeddedServletContainerFactory factory, int connectionTimeout) {
for (Connector connector : factory.getAdditionalTomcatConnectors()) { for (Connector connector : factory.getAdditionalTomcatConnectors()) {
if (connector.getProtocolHandler() instanceof AbstractProtocol) { ProtocolHandler handler = connector.getProtocolHandler();
AbstractProtocol<?> handler = (AbstractProtocol<?>) connector if (handler instanceof AbstractProtocol) {
.getProtocolHandler(); AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
handler.setConnectionTimeout(connectionTimeout); protocol.setConnectionTimeout(connectionTimeout);
} }
} }
} }
@ -1108,6 +1111,7 @@ public class ServerProperties
JettyEmbeddedServletContainerFactory factory, JettyEmbeddedServletContainerFactory factory,
final int connectionTimeout) { final int connectionTimeout) {
factory.addServerCustomizers(new JettyServerCustomizer() { factory.addServerCustomizers(new JettyServerCustomizer() {
@Override @Override
public void customize(Server server) { public void customize(Server server) {
for (org.eclipse.jetty.server.Connector connector : server for (org.eclipse.jetty.server.Connector connector : server
@ -1118,6 +1122,7 @@ public class ServerProperties
} }
} }
} }
}); });
} }

View File

@ -19,7 +19,6 @@ package org.springframework.boot.autoconfigure.data.cassandra;
import java.util.Set; import java.util.Set;
import com.datastax.driver.core.Session; import com.datastax.driver.core.Session;
import org.junit.After; import org.junit.After;
import org.junit.Test; import org.junit.Test;

View File

@ -191,7 +191,8 @@ public class NoSuchBeanDefinitionFailureAnalyzerTests {
private void assertClassDisabled(FailureAnalysis analysis, String description, private void assertClassDisabled(FailureAnalysis analysis, String description,
String methodName) { String methodName) {
String expected = String.format("Bean method '%s' not loaded because", methodName); String expected = String.format("Bean method '%s' not loaded because",
methodName);
assertThat(analysis.getDescription()).contains(expected); assertThat(analysis.getDescription()).contains(expected);
assertThat(analysis.getDescription()).contains(description); assertThat(analysis.getDescription()).contains(description);
} }

View File

@ -56,14 +56,13 @@ public class EmbeddedDataSourceConfigurationTests {
@Test @Test
public void generateUniqueName() throws Exception { public void generateUniqueName() throws Exception {
this.context = load("spring.datasource.generate-unique-name=true"); this.context = load("spring.datasource.generate-unique-name=true");
AnnotationConfigApplicationContext context2 = AnnotationConfigApplicationContext context2 = load(
load("spring.datasource.generate-unique-name=true"); "spring.datasource.generate-unique-name=true");
try { try {
DataSource dataSource = this.context.getBean(DataSource.class); DataSource dataSource = this.context.getBean(DataSource.class);
DataSource dataSource2 = context2.getBean(DataSource.class); DataSource dataSource2 = context2.getBean(DataSource.class);
assertThat(getDatabaseName(dataSource)) assertThat(getDatabaseName(dataSource))
.isNotEqualTo(getDatabaseName(dataSource2)); .isNotEqualTo(getDatabaseName(dataSource2));
System.out.println(dataSource2);
} }
finally { finally {
context2.close(); context2.close();

View File

@ -259,8 +259,7 @@ public class JmsAutoConfigurationTests {
"spring.jms.template.default-destination=testQueue", "spring.jms.template.default-destination=testQueue",
"spring.jms.template.delivery-delay=500", "spring.jms.template.delivery-delay=500",
"spring.jms.template.delivery-mode=non-persistent", "spring.jms.template.delivery-mode=non-persistent",
"spring.jms.template.priority=6", "spring.jms.template.priority=6", "spring.jms.template.time-to-live=6000",
"spring.jms.template.time-to-live=6000",
"spring.jms.template.receive-timeout=2000"); "spring.jms.template.receive-timeout=2000");
JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class);
assertThat(jmsTemplate.getMessageConverter()) assertThat(jmsTemplate.getMessageConverter())

View File

@ -444,9 +444,9 @@ public class ServerPropertiesTests {
TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory(); TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory();
this.properties.customize(container); this.properties.customize(container);
TomcatEmbeddedServletContainer embeddedContainer = TomcatEmbeddedServletContainer embeddedContainer = (TomcatEmbeddedServletContainer) container
(TomcatEmbeddedServletContainer) container.getEmbeddedServletContainer(); .getEmbeddedServletContainer();
assertThat(((AbstractProtocol) embeddedContainer.getTomcat().getConnector() assertThat(((AbstractProtocol<?>) embeddedContainer.getTomcat().getConnector()
.getProtocolHandler()).getBacklog()).isEqualTo(10); .getProtocolHandler()).getBacklog()).isEqualTo(10);
} }
@ -458,9 +458,9 @@ public class ServerPropertiesTests {
TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory(); TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory();
this.properties.customize(container); this.properties.customize(container);
TomcatEmbeddedServletContainer embeddedContainer = TomcatEmbeddedServletContainer embeddedContainer = (TomcatEmbeddedServletContainer) container
(TomcatEmbeddedServletContainer) container.getEmbeddedServletContainer(); .getEmbeddedServletContainer();
assertThat(((AbstractProtocol) embeddedContainer.getTomcat().getConnector() assertThat(((AbstractProtocol<?>) embeddedContainer.getTomcat().getConnector()
.getProtocolHandler()).getMaxConnections()).isEqualTo(5); .getProtocolHandler()).getMaxConnections()).isEqualTo(5);
} }

View File

@ -56,8 +56,7 @@ public class WarCommandIT {
assertThat(invocation.getOutput()).contains("Tomcat started"); assertThat(invocation.getOutput()).contains("Tomcat started");
assertThat(invocation.getOutput()) assertThat(invocation.getOutput())
.contains("/WEB-INF/lib-provided/tomcat-embed-core"); .contains("/WEB-INF/lib-provided/tomcat-embed-core");
assertThat(invocation.getOutput()) assertThat(invocation.getOutput()).contains("WEB-INF/classes!/root.properties");
.contains("WEB-INF/classes!/root.properties");
process.destroy(); process.destroy();
} }

View File

@ -289,10 +289,9 @@ abstract class ArchiveCommand extends OptionParsingCommand {
return libraries; return libraries;
} }
protected void writeClasspathEntry(JarWriter writer, protected void writeClasspathEntry(JarWriter writer, MatchedResource entry)
MatchedResource entry) throws IOException { throws IOException {
writer.writeEntry(entry.getName(), writer.writeEntry(entry.getName(), new FileInputStream(entry.getFile()));
new FileInputStream(entry.getFile()));
} }
protected abstract LibraryScope getLibraryScope(File file); protected abstract LibraryScope getLibraryScope(File file);

View File

@ -18,7 +18,6 @@ package sample.hibernate52.service;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import sample.hibernate52.domain.City; import sample.hibernate52.domain.City;
import sample.hibernate52.service.CityRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;

View File

@ -24,8 +24,6 @@ import sample.hibernate52.domain.Hotel;
import sample.hibernate52.domain.HotelSummary; import sample.hibernate52.domain.HotelSummary;
import sample.hibernate52.domain.Rating; import sample.hibernate52.domain.Rating;
import sample.hibernate52.domain.RatingCount; import sample.hibernate52.domain.RatingCount;
import sample.hibernate52.service.CityRepository;
import sample.hibernate52.service.HotelRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;

View File

@ -23,7 +23,6 @@ import org.hamcrest.TypeSafeMatcher;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import sample.web.thymeleaf3.SampleWebThymeleaf3Application;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;

View File

@ -478,8 +478,11 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
} }
@Override @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException { throws BeansException {
if (bean instanceof FactoryBean) {
return bean;
}
return createSpyIfNecessary(bean, beanName); return createSpyIfNecessary(bean, beanName);
} }

View File

@ -42,7 +42,6 @@ import org.springframework.boot.configurationsample.lombok.LombokInnerClassPrope
import org.springframework.boot.configurationsample.lombok.LombokSimpleDataProperties; import org.springframework.boot.configurationsample.lombok.LombokSimpleDataProperties;
import org.springframework.boot.configurationsample.lombok.LombokSimpleProperties; import org.springframework.boot.configurationsample.lombok.LombokSimpleProperties;
import org.springframework.boot.configurationsample.lombok.SimpleLombokPojo; import org.springframework.boot.configurationsample.lombok.SimpleLombokPojo;
import org.springframework.boot.configurationsample.method.DeprecatedClassMethodConfig;
import org.springframework.boot.configurationsample.method.DeprecatedMethodConfig; import org.springframework.boot.configurationsample.method.DeprecatedMethodConfig;
import org.springframework.boot.configurationsample.method.EmptyTypeMethodConfig; import org.springframework.boot.configurationsample.method.EmptyTypeMethodConfig;
import org.springframework.boot.configurationsample.method.InvalidMethodConfig; import org.springframework.boot.configurationsample.method.InvalidMethodConfig;
@ -290,8 +289,7 @@ public class ConfigurationMetadataAnnotationProcessorTests {
public void deprecatedMethodConfig() throws Exception { public void deprecatedMethodConfig() throws Exception {
Class<DeprecatedMethodConfig> type = DeprecatedMethodConfig.class; Class<DeprecatedMethodConfig> type = DeprecatedMethodConfig.class;
ConfigurationMetadata metadata = compile(type); ConfigurationMetadata metadata = compile(type);
assertThat(metadata) assertThat(metadata).has(Metadata.withGroup("foo").fromSource(type));
.has(Metadata.withGroup("foo").fromSource(type));
assertThat(metadata).has(Metadata.withProperty("foo.name", String.class) assertThat(metadata).has(Metadata.withProperty("foo.name", String.class)
.fromSource(DeprecatedMethodConfig.Foo.class) .fromSource(DeprecatedMethodConfig.Foo.class)
.withDeprecation(null, null)); .withDeprecation(null, null));
@ -301,16 +299,18 @@ public class ConfigurationMetadataAnnotationProcessorTests {
} }
@Test @Test
@SuppressWarnings("deprecation")
public void deprecatedMethodConfigOnClass() throws Exception { public void deprecatedMethodConfigOnClass() throws Exception {
Class<DeprecatedClassMethodConfig> type = DeprecatedClassMethodConfig.class; Class<?> type = org.springframework.boot.configurationsample.method.DeprecatedClassMethodConfig.class;
ConfigurationMetadata metadata = compile(type); ConfigurationMetadata metadata = compile(type);
assertThat(metadata) assertThat(metadata).has(Metadata.withGroup("foo").fromSource(type));
.has(Metadata.withGroup("foo").fromSource(type));
assertThat(metadata).has(Metadata.withProperty("foo.name", String.class) assertThat(metadata).has(Metadata.withProperty("foo.name", String.class)
.fromSource(DeprecatedClassMethodConfig.Foo.class) .fromSource(
org.springframework.boot.configurationsample.method.DeprecatedClassMethodConfig.Foo.class)
.withDeprecation(null, null)); .withDeprecation(null, null));
assertThat(metadata).has(Metadata.withProperty("foo.flag", Boolean.class) assertThat(metadata).has(Metadata.withProperty("foo.flag", Boolean.class)
.fromSource(DeprecatedClassMethodConfig.Foo.class) .fromSource(
org.springframework.boot.configurationsample.method.DeprecatedClassMethodConfig.Foo.class)
.withDeprecation(null, null)); .withDeprecation(null, null));
} }

View File

@ -52,6 +52,7 @@ public class DeprecatedClassMethodConfig {
public void setFlag(boolean flag) { public void setFlag(boolean flag) {
this.flag = flag; this.flag = flag;
} }
} }
} }

View File

@ -51,8 +51,16 @@ public class RunProcess {
private volatile long endTime; private volatile long endTime;
/** /**
* Creates new {@link RunProcess} instance for the specified command * Creates new {@link RunProcess} instance for the specified command.
* and working directory. * @param command the program to execute and it's arguments
*/
public RunProcess(String... command) {
this(null, command);
}
/**
* Creates new {@link RunProcess} instance for the specified working directory and
* command.
* @param workingDirectory the working directory of the child process or {@code null} * @param workingDirectory the working directory of the child process or {@code null}
* to run in the working directory of the current Java process * to run in the working directory of the current Java process
* @param command the program to execute and it's arguments * @param command the program to execute and it's arguments
@ -62,14 +70,6 @@ public class RunProcess {
this.command = command; this.command = command;
} }
/**
* Creates new {@link RunProcess} instance for the specified command.
* @param command the program to execute and it's arguments
*/
public RunProcess(String... command) {
this(null, command);
}
public int run(boolean waitForProcess, String... args) throws IOException { public int run(boolean waitForProcess, String... args) throws IOException {
return run(waitForProcess, Arrays.asList(args)); return run(waitForProcess, Arrays.asList(args));
} }

View File

@ -149,8 +149,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/** /**
* Flag to indicate if the run processes should be forked. {@code fork} is * Flag to indicate if the run processes should be forked. {@code fork} is
* automatically enabled if an agent, jvmArguments or working directory are * automatically enabled if an agent, jvmArguments or working directory are specified,
* specified, or if devtools is present. * or if devtools is present.
* @since 1.2 * @since 1.2
*/ */
@Parameter(property = "fork") @Parameter(property = "fork")
@ -206,7 +206,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
} }
private boolean hasWorkingDirectorySet() { private boolean hasWorkingDirectorySet() {
return (this.workingDirectory != null); return this.workingDirectory != null;
} }
private void findAgent() { private void findAgent() {

View File

@ -64,9 +64,11 @@ public class RunMojo extends AbstractRunMojo {
} }
@Override @Override
protected void runWithForkedJvm(File workingDirectory, List<String> args) throws MojoExecutionException { protected void runWithForkedJvm(File workingDirectory, List<String> args)
throws MojoExecutionException {
try { try {
RunProcess runProcess = new RunProcess(workingDirectory, new JavaExecutable().toString()); RunProcess runProcess = new RunProcess(workingDirectory,
new JavaExecutable().toString());
Runtime.getRuntime() Runtime.getRuntime()
.addShutdownHook(new Thread(new RunProcessKiller(runProcess))); .addShutdownHook(new Thread(new RunProcessKiller(runProcess)));
int exitCode = runProcess.run(true, args.toArray(new String[args.size()])); int exitCode = runProcess.run(true, args.toArray(new String[args.size()]));

View File

@ -30,9 +30,9 @@ import org.springframework.context.annotation.Configuration;
* standard {@code @Configuration} annotation so that configuration can be found * standard {@code @Configuration} annotation so that configuration can be found
* automatically (for example in tests). * automatically (for example in tests).
* <p> * <p>
* Application should only ever include <em>one</em> * Application should only ever include <em>one</em> {@code @SpringBootConfiguration} and
* {@code @SpringBootConfiguration} and most idiomatic Spring Boot applications * most idiomatic Spring Boot applications will inherit it from
* will inherit it from {@code @SpringBootApplication}. * {@code @SpringBootApplication}.
* *
* @author Phillip Webb * @author Phillip Webb
* @since 1.4.0 * @since 1.4.0

View File

@ -39,40 +39,42 @@ class BeanCurrentlyInCreationFailureAnalyzer
@Override @Override
protected FailureAnalysis analyze(Throwable rootFailure, protected FailureAnalysis analyze(Throwable rootFailure,
BeanCurrentlyInCreationException cause) { BeanCurrentlyInCreationException cause) {
List<BeanInCycle> beansInCycle = new ArrayList<BeanInCycle>(); List<BeanInCycle> cycle = new ArrayList<BeanInCycle>();
Throwable candidate = rootFailure; Throwable candidate = rootFailure;
int cycleStart = -1; int cycleStart = -1;
while (candidate != null) { while (candidate != null) {
if (candidate instanceof BeanCreationException) { BeanInCycle beanInCycle = BeanInCycle.get(candidate);
BeanCreationException creationEx = (BeanCreationException) candidate; if (beanInCycle != null) {
if (StringUtils.hasText(creationEx.getBeanName())) { int index = cycle.indexOf(beanInCycle);
BeanInCycle beanInCycle = new BeanInCycle(creationEx); if (index == -1) {
int index = beansInCycle.indexOf(beanInCycle); cycle.add(beanInCycle);
if (index == -1) {
beansInCycle.add(beanInCycle);
}
else {
cycleStart = index;
}
} }
cycleStart = (cycleStart == -1 ? index : cycleStart);
} }
candidate = candidate.getCause(); candidate = candidate.getCause();
} }
String message = buildMessage(cycle, cycleStart);
return new FailureAnalysis(message, null, cause);
}
private String buildMessage(List<BeanInCycle> beansInCycle, int cycleStart) {
StringBuilder message = new StringBuilder(); StringBuilder message = new StringBuilder();
message.append(String.format("The dependencies of some of the beans in the " message.append(String.format("The dependencies of some of the beans in the "
+ "application context form a cycle:%n%n")); + "application context form a cycle:%n%n"));
for (int i = 0; i < beansInCycle.size(); i++) { for (int i = 0; i < beansInCycle.size(); i++) {
BeanInCycle beanInCycle = beansInCycle.get(i);
if (i == cycleStart) { if (i == cycleStart) {
message.append(String.format("┌─────┐%n")); message.append(String.format("┌─────┐%n"));
} }
else if (i > 0) { else if (i > 0) {
message.append(String.format("%s ↓%n", i < cycleStart ? " " : "")); String leftSide = (i < cycleStart ? " " : "");
message.append(String.format("%s ↓%n", leftSide));
} }
message.append(String.format("%s %s%n", i < cycleStart ? " " : "|", String leftSide = i < cycleStart ? " " : "|";
beansInCycle.get(i))); message.append(String.format("%s %s%n", leftSide, beanInCycle));
} }
message.append(String.format("└─────┘%n")); message.append(String.format("└─────┘%n"));
return new FailureAnalysis(message.toString(), null, cause); return message.toString();
} }
private static final class BeanInCycle { private static final class BeanInCycle {
@ -114,14 +116,10 @@ class BeanCurrentlyInCreationFailureAnalyzer
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (obj == null) { if (obj == null || getClass() != obj.getClass()) {
return false; return false;
} }
if (getClass() != obj.getClass()) { return this.name.equals(((BeanInCycle) obj).name);
return false;
}
BeanInCycle other = (BeanInCycle) obj;
return this.name.equals(other.name);
} }
@Override @Override
@ -129,6 +127,20 @@ class BeanCurrentlyInCreationFailureAnalyzer
return this.name + this.description; return this.name + this.description;
} }
public static BeanInCycle get(Throwable ex) {
if (ex instanceof BeanCreationException) {
return get((BeanCreationException) ex);
}
return null;
}
private static BeanInCycle get(BeanCreationException ex) {
if (StringUtils.hasText(ex.getBeanName())) {
return new BeanInCycle(ex);
}
return null;
}
} }
} }