@ -16,11 +16,21 @@
package org.springframework.boot.diagnostics.analyzer ;
package org.springframework.boot.diagnostics.analyzer ;
import java.io.BufferedReader ;
import java.io.IOException ;
import java.io.StringReader ;
import java.util.ArrayList ;
import java.util.List ;
import org.junit.Test ;
import org.junit.Test ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.boot.diagnostics.FailureAnalysis ;
import org.springframework.boot.diagnostics.FailureAnalysis ;
import org.springframework.boot.diagnostics.FailureAnalyzer ;
import org.springframework.boot.diagnostics.FailureAnalyzer ;
import org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzerTests.CycleWithAutowiredFields.BeanThreeConfiguration ;
import org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzerTests.CycleWithAutowiredFields.BeanTwoConfiguration ;
import org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzerTests.CyclicBeanMethodsConfiguration.InnerConfiguration ;
import org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzerTests.CyclicBeanMethodsConfiguration.InnerConfiguration.InnerInnerConfiguration ;
import org.springframework.context.ConfigurableApplicationContext ;
import org.springframework.context.ConfigurableApplicationContext ;
import org.springframework.context.annotation.AnnotationConfigApplicationContext ;
import org.springframework.context.annotation.AnnotationConfigApplicationContext ;
import org.springframework.context.annotation.Bean ;
import org.springframework.context.annotation.Bean ;
@ -39,10 +49,25 @@ public class BeanCurrentlyInCreationFailureAnalyzerTests {
private final FailureAnalyzer analyzer = new BeanCurrentlyInCreationFailureAnalyzer ( ) ;
private final FailureAnalyzer analyzer = new BeanCurrentlyInCreationFailureAnalyzer ( ) ;
@Test
@Test
public void cyclicBeanMethods ( ) {
public void cyclicBeanMethods ( ) throws IOException {
FailureAnalysis analysis = performAnalysis ( CyclicBeanMethodsConfiguration . class ) ;
FailureAnalysis analysis = performAnalysis ( CyclicBeanMethodsConfiguration . class ) ;
List < String > lines = readDescriptionLines ( analysis ) ;
assertThat ( lines ) . hasSize ( 9 ) ;
assertThat ( lines . get ( 0 ) ) . isEqualTo (
"The dependencies of some of the beans in the application context form a cycle:" ) ;
assertThat ( lines . get ( 1 ) ) . isEqualTo ( "" ) ;
assertThat ( lines . get ( 2 ) ) . isEqualTo ( "┌─────┐" ) ;
assertThat ( lines . get ( 3 ) ) . startsWith (
"| one defined in " + InnerInnerConfiguration . class . getName ( ) ) ;
assertThat ( lines . get ( 4 ) ) . isEqualTo ( "↑ ↓" ) ;
assertThat ( lines . get ( 5 ) )
. startsWith ( "| two defined in " + InnerConfiguration . class . getName ( ) ) ;
assertThat ( lines . get ( 6 ) ) . isEqualTo ( "↑ ↓" ) ;
assertThat ( lines . get ( 7 ) ) . startsWith (
"| three defined in " + CyclicBeanMethodsConfiguration . class . getName ( ) ) ;
assertThat ( lines . get ( 8 ) ) . isEqualTo ( "└─────┘" ) ;
assertThat ( analysis . getDescription ( ) ) . startsWith (
assertThat ( analysis . getDescription ( ) ) . startsWith (
"There is a circular dependency between 3 beans in the application context:" ) ;
"The dependencies of some of the beans in the application context form a cycle :") ;
assertThat ( analysis . getDescription ( ) ) . contains (
assertThat ( analysis . getDescription ( ) ) . contains (
"one defined in " + CyclicBeanMethodsConfiguration . class . getName ( ) ) ;
"one defined in " + CyclicBeanMethodsConfiguration . class . getName ( ) ) ;
assertThat ( analysis . getDescription ( ) ) . contains (
assertThat ( analysis . getDescription ( ) ) . contains (
@ -52,22 +77,74 @@ public class BeanCurrentlyInCreationFailureAnalyzerTests {
}
}
@Test
@Test
public void cycleWithAutowiredFields ( ) {
public void cycleWithAutowiredFields ( ) throws IOException {
FailureAnalysis analysis = performAnalysis ( CycleWithAutowiredFields . class ) ;
FailureAnalysis analysis = performAnalysis ( CycleWithAutowiredFields . class ) ;
assertThat ( analysis . getDescription ( ) ) . startsWith (
assertThat ( analysis . getDescription ( ) ) . startsWith (
"There is a circular dependency between 3 beans in the application context:" ) ;
"The dependencies of some of the beans in the application context form a cycle:" ) ;
assertThat ( analysis . getDescription ( ) ) . contains ( "three defined in "
List < String > lines = readDescriptionLines ( analysis ) ;
+ CycleWithAutowiredFields . BeanThreeConfiguration . class . getName ( ) ) ;
assertThat ( lines ) . hasSize ( 9 ) ;
assertThat ( analysis . getDescription ( ) )
assertThat ( lines . get ( 0 ) ) . isEqualTo (
. contains ( "one defined in " + CycleWithAutowiredFields . class . getName ( ) ) ;
"The dependencies of some of the beans in the application context form a cycle:" ) ;
assertThat ( analysis . getDescription ( ) )
assertThat ( lines . get ( 1 ) ) . isEqualTo ( "" ) ;
. contains ( CycleWithAutowiredFields . BeanTwoConfiguration . class . getName ( )
assertThat ( lines . get ( 2 ) ) . isEqualTo ( "┌─────┐" ) ;
+ " (field private " + BeanThree . class . getName ( ) ) ;
assertThat ( lines . get ( 3 ) ) . startsWith (
"| three defined in " + BeanThreeConfiguration . class . getName ( ) ) ;
assertThat ( lines . get ( 4 ) ) . isEqualTo ( "↑ ↓" ) ;
assertThat ( lines . get ( 5 ) ) . startsWith (
"| one defined in " + CycleWithAutowiredFields . class . getName ( ) ) ;
assertThat ( lines . get ( 6 ) ) . isEqualTo ( "↑ ↓" ) ;
assertThat ( lines . get ( 7 ) ) . startsWith ( "| " + BeanTwoConfiguration . class . getName ( )
+ " (field private " + BeanThree . class . getName ( ) ) ;
assertThat ( lines . get ( 8 ) ) . isEqualTo ( "└─────┘" ) ;
}
@Test
public void cycleReferencedViaOtherBeans ( ) throws IOException {
FailureAnalysis analysis = performAnalysis (
CycleReferencedViaOtherBeansConfiguration . class ) ;
List < String > lines = readDescriptionLines ( analysis ) ;
assertThat ( lines ) . hasSize ( 12 ) ;
assertThat ( lines . get ( 0 ) ) . isEqualTo (
"The dependencies of some of the beans in the application context form a cycle:" ) ;
assertThat ( lines . get ( 1 ) ) . isEqualTo ( "" ) ;
assertThat ( lines . get ( 2 ) )
. contains ( "refererOne " + "(field " + RefererTwo . class . getName ( ) ) ;
assertThat ( lines . get ( 3 ) ) . isEqualTo ( " ↓" ) ;
assertThat ( lines . get ( 4 ) )
. contains ( "refererTwo " + "(field " + BeanOne . class . getName ( ) ) ;
assertThat ( lines . get ( 5 ) ) . isEqualTo ( "┌─────┐" ) ;
assertThat ( lines . get ( 6 ) ) . startsWith ( "| one defined in "
+ CycleReferencedViaOtherBeansConfiguration . class . getName ( ) ) ;
assertThat ( lines . get ( 7 ) ) . isEqualTo ( "↑ ↓" ) ;
assertThat ( lines . get ( 8 ) ) . startsWith ( "| two defined in "
+ CycleReferencedViaOtherBeansConfiguration . class . getName ( ) ) ;
assertThat ( lines . get ( 9 ) ) . isEqualTo ( "↑ ↓" ) ;
assertThat ( lines . get ( 10 ) ) . startsWith ( "| three defined in "
+ CycleReferencedViaOtherBeansConfiguration . class . getName ( ) ) ;
assertThat ( lines . get ( 11 ) ) . isEqualTo ( "└─────┘" ) ;
}
private List < String > readDescriptionLines ( FailureAnalysis analysis )
throws IOException {
BufferedReader lineReader = new BufferedReader (
new StringReader ( analysis . getDescription ( ) ) ) ;
try {
List < String > lines = new ArrayList < String > ( ) ;
String line ;
while ( ( line = lineReader . readLine ( ) ) ! = null ) {
lines . add ( line ) ;
}
return lines ;
}
finally {
lineReader . close ( ) ;
}
}
}
private FailureAnalysis performAnalysis ( Class < ? > configuration ) {
private FailureAnalysis performAnalysis ( Class < ? > configuration ) {
FailureAnalysis analysis = this . analyzer . analyze ( createFailure ( configuration ) ) ;
FailureAnalysis analysis = this . analyzer . analyze ( createFailure ( configuration ) ) ;
assertThat ( analysis ) . isNotNull ( ) ;
assertThat ( analysis ) . isNotNull ( ) ;
System . out . println ( analysis . getDescription ( ) ) ;
return analysis ;
return analysis ;
}
}
@ -89,9 +166,39 @@ public class BeanCurrentlyInCreationFailureAnalyzerTests {
return null ;
return null ;
}
}
@ Configuration
@ org.springframework.context.annotation. Configuration
static class CyclicBeanMethodsConfiguration {
static class CyclicBeanMethodsConfiguration {
@Bean
public BeanThree three ( BeanOne one ) {
return new BeanThree ( ) ;
}
@org.springframework.context.annotation.Configuration
static class InnerConfiguration {
@Bean
public BeanTwo two ( BeanThree three ) {
return new BeanTwo ( ) ;
}
@Configuration
static class InnerInnerConfiguration {
@Bean
public BeanOne one ( BeanTwo two ) {
return new BeanOne ( ) ;
}
}
}
}
@Configuration
static class CycleReferencedViaOtherBeansConfiguration {
@Bean
@Bean
public BeanOne one ( BeanTwo two ) {
public BeanOne one ( BeanTwo two ) {
return new BeanOne ( ) ;
return new BeanOne ( ) ;
@ -103,13 +210,33 @@ public class BeanCurrentlyInCreationFailureAnalyzerTests {
}
}
@Bean
@Bean
public BeanThree three ( BeanOne o ne) {
public BeanThree three ( BeanOne beanO ne) {
return new BeanThree ( ) ;
return new BeanThree ( ) ;
}
}
@Configuration
static class InnerConfiguration {
@Bean
public RefererTwo refererTwo ( ) {
return new RefererTwo ( ) ;
}
@Configuration
static class InnerInnerConfiguration {
@Bean
public RefererOne refererOne ( ) {
return new RefererOne ( ) ;
}
}
}
}
}
@Configuration
@ org.springframework.context.annotation. Configuration
public static class CycleWithAutowiredFields {
public static class CycleWithAutowiredFields {
@Bean
@Bean
@ -127,6 +254,7 @@ public class BeanCurrentlyInCreationFailureAnalyzerTests {
public BeanTwo two ( ) {
public BeanTwo two ( ) {
return new BeanTwo ( ) ;
return new BeanTwo ( ) ;
}
}
}
}
public static class BeanThreeConfiguration {
public static class BeanThreeConfiguration {
@ -135,10 +263,25 @@ public class BeanCurrentlyInCreationFailureAnalyzerTests {
public BeanThree three ( BeanOne one ) {
public BeanThree three ( BeanOne one ) {
return new BeanThree ( ) ;
return new BeanThree ( ) ;
}
}
}
}
}
}
static class RefererOne {
@Autowired
RefererTwo refererTwo ;
}
static class RefererTwo {
@Autowired
BeanOne beanOne ;
}
static class BeanOne {
static class BeanOne {
}
}