From 5b1278d03c868b34cdeed8822b591bcd951be3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Wed, 8 May 2024 10:22:36 +0200 Subject: [PATCH] Refine exception message to include bean name Closes gh-32775 --- .../DefaultBeanRegistrationCodeFragments.java | 5 +-- .../BeanDefinitionMethodGeneratorTests.java | 8 ++--- ...ultBeanRegistrationCodeFragmentsTests.java | 32 +++++++++++++++++-- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java index feddeb21d4..50564ee23a 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java @@ -79,8 +79,9 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme @Override public ClassName getTarget(RegisteredBean registeredBean) { if (hasInstanceSupplier()) { - throw new IllegalStateException("Default code generation is not supported for bean definitions " - + "declaring an instance supplier callback: " + registeredBean.getMergedBeanDefinition()); + String resourceDescription = registeredBean.getMergedBeanDefinition().getResourceDescription(); + throw new IllegalStateException("Error processing bean with name '" + registeredBean.getBeanName() + "'" + + (resourceDescription != null ? " defined in " + resourceDescription : "") + ": instance supplier is not supported"); } Class target = extractDeclaringClass(registeredBean, this.instantiationDescriptor.get()); while (target.getName().startsWith("java.") && registeredBean.isInnerBean()) { diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java index 0cd797b8af..af9bf3793e 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java @@ -692,8 +692,8 @@ class BeanDefinitionMethodGeneratorTests { this.methodGeneratorFactory, registeredBean, null, List.of()); assertThatIllegalStateException().isThrownBy(() -> generator.generateBeanDefinitionMethod( - this.generationContext, this.beanRegistrationsCode)).withMessageStartingWith( - "Default code generation is not supported for bean definitions declaring an instance supplier callback"); + this.generationContext, this.beanRegistrationsCode)).withMessage( + "Error processing bean with name 'testBean': instance supplier is not supported"); } @Test @@ -729,8 +729,8 @@ class BeanDefinitionMethodGeneratorTests { this.methodGeneratorFactory, registeredBean, null, List.of(aotContribution)); assertThatIllegalStateException().isThrownBy(() -> generator.generateBeanDefinitionMethod( - this.generationContext, this.beanRegistrationsCode)).withMessageStartingWith( - "Default code generation is not supported for bean definitions declaring an instance supplier callback"); + this.generationContext, this.beanRegistrationsCode)).withMessage( + "Error processing bean with name 'testBean': instance supplier is not supported"); } @Test diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragmentsTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragmentsTests.java index d6f77e1b0f..1333b2f160 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragmentsTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragmentsTests.java @@ -48,6 +48,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -65,6 +66,28 @@ class DefaultBeanRegistrationCodeFragmentsTests { private final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + @Test + public void getTargetWithInstanceSupplier() { + RootBeanDefinition beanDefinition = new RootBeanDefinition(SimpleBean.class); + beanDefinition.setInstanceSupplier(SimpleBean::new); + RegisteredBean registeredBean = registerTestBean(beanDefinition); + BeanRegistrationCodeFragments codeFragments = createInstance(registeredBean); + assertThatIllegalStateException().isThrownBy(() -> codeFragments.getTarget(registeredBean)) + .withMessageContaining("Error processing bean with name 'testBean': instance supplier is not supported"); + } + + @Test + public void getTargetWithInstanceSupplierAndResourceDescription() { + RootBeanDefinition beanDefinition = new RootBeanDefinition(SimpleBean.class); + beanDefinition.setInstanceSupplier(SimpleBean::new); + beanDefinition.setResourceDescription("my test resource"); + RegisteredBean registeredBean = registerTestBean(beanDefinition); + BeanRegistrationCodeFragments codeFragments = createInstance(registeredBean); + assertThatIllegalStateException().isThrownBy(() -> codeFragments.getTarget(registeredBean)) + .withMessageContaining("Error processing bean with name 'testBean' defined in my test resource: " + + "instance supplier is not supported"); + } + @Test void getTargetOnConstructor() { RegisteredBean registeredBean = registerTestBean(SimpleBean.class, @@ -257,13 +280,16 @@ class DefaultBeanRegistrationCodeFragmentsTests { return RegisteredBean.of(this.beanFactory, "testBean"); } - private RegisteredBean registerTestBean(ResolvableType beanType, @Nullable Executable constructorOrFactoryMethod) { RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setTargetType(beanType); - this.beanFactory.registerBeanDefinition("testBean", - applyConstructorOrFactoryMethod(beanDefinition, constructorOrFactoryMethod)); + return registerTestBean(applyConstructorOrFactoryMethod( + beanDefinition, constructorOrFactoryMethod)); + } + + private RegisteredBean registerTestBean(RootBeanDefinition beanDefinition) { + this.beanFactory.registerBeanDefinition("testBean", beanDefinition); return RegisteredBean.of(this.beanFactory, "testBean"); }