Home / Class/ BeanCurrentlyInCreationFailureAnalyzerTests Class — spring-boot Architecture

BeanCurrentlyInCreationFailureAnalyzerTests Class — spring-boot Architecture

Architecture documentation for the BeanCurrentlyInCreationFailureAnalyzerTests class in BeanCurrentlyInCreationFailureAnalyzerTests.java from the spring-boot codebase.

Entity Profile

Relationship Graph

Source Code

core/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/BeanCurrentlyInCreationFailureAnalyzerTests.java lines 47–326

class BeanCurrentlyInCreationFailureAnalyzerTests {

	private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

	private final BeanCurrentlyInCreationFailureAnalyzer analyzer = new BeanCurrentlyInCreationFailureAnalyzer(
			this.context.getBeanFactory());

	@Test
	void cyclicBeanMethods() throws IOException {
		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)).isEmpty();
		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.getAction()).isNotNull();
	}

	@Test
	void cycleWithAutowiredFields() throws IOException {
		FailureAnalysis analysis = performAnalysis(CycleWithAutowiredFields.class);
		assertThat(analysis.getDescription())
			.startsWith("The dependencies of some of the beans in the application context form a cycle:");
		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)).isEmpty();
		assertThat(lines.get(2)).isEqualTo("┌─────┐");
		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("└─────┘");
		assertThat(analysis.getAction()).isNotNull();
	}

	@Test
	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)).isEmpty();
		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("└─────┘");
		assertThat(analysis.getAction()).isNotNull();
	}

	@Test
	void testSelfReferenceCycle() throws IOException {
		FailureAnalysis analysis = performAnalysis(SelfReferenceBeanConfiguration.class);
		List<String> lines = readDescriptionLines(analysis);
		assertThat(lines).hasSize(5);
		assertThat(lines.get(0))
			.isEqualTo("The dependencies of some of the beans in the application context form a cycle:");
		assertThat(lines.get(1)).isEmpty();
		assertThat(lines.get(2)).isEqualTo("┌──->──┐");
		assertThat(lines.get(3)).startsWith("|  bean defined in " + SelfReferenceBeanConfiguration.class.getName());
		assertThat(lines.get(4)).isEqualTo("└──<-──┘");
		assertThat(analysis.getAction()).isNotNull();
	}

	@Test
	void cycleWithAnUnknownStartIsNotAnalyzed() {
		assertThat(this.analyzer.analyze(new BeanCurrentlyInCreationException("test"))).isNull();
	}

	@Test
	void cycleWithCircularReferencesAllowed() {
		FailureAnalysis analysis = performAnalysis(CyclicBeanMethodsConfiguration.class, true);
		assertThat(analysis.getAction()).contains("Despite circular references being allowed");
	}

	@Test
	void cycleWithCircularReferencesProhibited() {
		FailureAnalysis analysis = performAnalysis(CyclicBeanMethodsConfiguration.class, false);
		assertThat(analysis.getAction()).contains("As a last resort");
	}

	private List<String> readDescriptionLines(FailureAnalysis analysis) throws IOException {
		try (BufferedReader reader = new BufferedReader(new StringReader(analysis.getDescription()))) {
			return reader.lines().toList();
		}
	}

	private FailureAnalysis performAnalysis(Class<?> configuration) {
		return performAnalysis(configuration, true);
	}

	private FailureAnalysis performAnalysis(Class<?> configuration, boolean allowCircularReferences) {
		FailureAnalysis analysis = this.analyzer.analyze(createFailure(configuration, allowCircularReferences));
		assertThat(analysis).isNotNull();
		return analysis;
	}

	private Exception createFailure(Class<?> configuration, boolean allowCircularReferences) {
		try {
			this.context.register(configuration);
			AbstractAutowireCapableBeanFactory beanFactory = (AbstractAutowireCapableBeanFactory) this.context
				.getBeanFactory();
			beanFactory.setAllowCircularReferences(allowCircularReferences);
			this.context.refresh();
			fail("Expected failure did not occur");
			throw new AssertionError("This should not be reached");
		}
		catch (Exception ex) {
			return ex;
		}
	}

	@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
	static class CyclicBeanMethodsConfiguration {

		@Bean
		BeanThree three(BeanOne one) {
			return new BeanThree();
		}

		@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
		static class InnerConfiguration {

			@Bean
			BeanTwo two(BeanThree three) {
				return new BeanTwo();
			}

			@Configuration(proxyBeanMethods = false)
			static class InnerInnerConfiguration {

				@Bean
				BeanOne one(BeanTwo two) {
					return new BeanOne();
				}

			}

		}

	}

	@Configuration(proxyBeanMethods = false)
	static class CycleReferencedViaOtherBeansConfiguration {

		@Bean
		BeanOne one(BeanTwo two) {
			return new BeanOne();
		}

		@Bean
		BeanTwo two(BeanThree three) {
			return new BeanTwo();
		}

		@Bean
		BeanThree three(BeanOne beanOne) {
			return new BeanThree();
		}

		@Configuration(proxyBeanMethods = false)
		static class InnerConfiguration {

			@Bean
			RefererTwo refererTwo() {
				return new RefererTwo();
			}

			@Configuration(proxyBeanMethods = false)
			static class InnerInnerConfiguration {

				@Bean
				RefererOne refererOne() {
					return new RefererOne();
				}

			}

		}

	}

	@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
	static class CycleWithAutowiredFields {

		@Bean
		BeanOne one(BeanTwo two) {
			return new BeanOne();
		}

		@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
		static class BeanTwoConfiguration {

			@SuppressWarnings("unused")
			@Autowired
			private BeanThree three;

			@Bean
			BeanTwo two() {
				return new BeanTwo();
			}

		}

		@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
		static class BeanThreeConfiguration {

			@Bean
			BeanThree three(BeanOne one) {
				return new BeanThree();
			}

		}

	}

	@Configuration(proxyBeanMethods = false)
	static class SelfReferenceBeanConfiguration {

		@Bean
		SelfReferenceBean bean(SelfReferenceBean bean) {
			return new SelfReferenceBean();
		}

	}

	static class RefererOne {

		@Autowired
		RefererTwo refererTwo;

	}

	static class RefererTwo {

		@Autowired
		BeanOne beanOne;

	}

	static class BeanOne {

	}

	static class BeanTwo {

	}

	static class BeanThree {

	}

	static class SelfReferenceBean {

		@Autowired
		SelfReferenceBean bean;

	}

}

Domain

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free