Abandon failure analysis if start of cycle cannot be determined

Previously, BeanCurrentlyInCreationFailureAnalyzer would return
a FailureAnalysis for any BeanCurrentlyInCreationException even if
it could not determine where the cycle begins. This could lead to an
inaccurate diagram of the cycle being output.

This commit updates BeanCurrentlyInCreationFailureAnalyzer so that
it abandons its analysis and returns null if it is unable to determine
where the cycle begins.

Closes gh-8164
pull/9258/merge
Andy Wilkinson 8 years ago
parent 9fc90a809f
commit b9a09fcd64

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -39,28 +39,40 @@ class BeanCurrentlyInCreationFailureAnalyzer
@Override
protected FailureAnalysis analyze(Throwable rootFailure,
BeanCurrentlyInCreationException cause) {
List<BeanInCycle> cycle = new ArrayList<BeanInCycle>();
DependencyCycle dependencyCycle = findCycle(rootFailure);
if (dependencyCycle == null) {
return null;
}
return new FailureAnalysis(buildMessage(dependencyCycle), null, cause);
}
private DependencyCycle findCycle(Throwable rootFailure) {
List<BeanInCycle> beansInCycle = new ArrayList<BeanInCycle>();
Throwable candidate = rootFailure;
int cycleStart = -1;
while (candidate != null) {
BeanInCycle beanInCycle = BeanInCycle.get(candidate);
if (beanInCycle != null) {
int index = cycle.indexOf(beanInCycle);
int index = beansInCycle.indexOf(beanInCycle);
if (index == -1) {
cycle.add(beanInCycle);
beansInCycle.add(beanInCycle);
}
cycleStart = (cycleStart == -1 ? index : cycleStart);
}
candidate = candidate.getCause();
}
String message = buildMessage(cycle, cycleStart);
return new FailureAnalysis(message, null, cause);
if (cycleStart == -1) {
return null;
}
return new DependencyCycle(beansInCycle, cycleStart);
}
private String buildMessage(List<BeanInCycle> beansInCycle, int cycleStart) {
private String buildMessage(DependencyCycle dependencyCycle) {
StringBuilder message = new StringBuilder();
message.append(String.format("The dependencies of some of the beans in the "
+ "application context form a cycle:%n%n"));
List<BeanInCycle> beansInCycle = dependencyCycle.getBeansInCycle();
int cycleStart = dependencyCycle.getCycleStart();
for (int i = 0; i < beansInCycle.size(); i++) {
BeanInCycle beanInCycle = beansInCycle.get(i);
if (i == cycleStart) {
@ -77,6 +89,27 @@ class BeanCurrentlyInCreationFailureAnalyzer
return message.toString();
}
private static final class DependencyCycle {
private final List<BeanInCycle> beansInCycle;
private final int cycleStart;
private DependencyCycle(List<BeanInCycle> beansInCycle, int cycleStart) {
this.beansInCycle = beansInCycle;
this.cycleStart = cycleStart;
}
public List<BeanInCycle> getBeansInCycle() {
return this.beansInCycle;
}
public int getCycleStart() {
return this.cycleStart;
}
}
private static final class BeanInCycle {
private final String name;

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -24,6 +24,7 @@ import java.util.List;
import org.junit.Test;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.diagnostics.FailureAnalyzer;
@ -116,6 +117,12 @@ public class BeanCurrentlyInCreationFailureAnalyzerTests {
assertThat(lines.get(11)).isEqualTo("└─────┘");
}
@Test
public void cycleWithAnUnknownStartIsNotAnalyzed() throws IOException {
assertThat(this.analyzer.analyze(new BeanCurrentlyInCreationException("test")))
.isNull();
}
private List<String> readDescriptionLines(FailureAnalysis analysis)
throws IOException {
BufferedReader lineReader = new BufferedReader(

Loading…
Cancel
Save