Provide dedicated AOT exception hierarchy
This commit adds a number of catch point that provides additional context when an AOT processor fails to execute. Amongst other things, this makes sure that the bean name and its descriptor is consistently provided in the error message when available. Closes gh-32777
This commit is contained in:
@@ -21,11 +21,14 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.beans.factory.aot.AotException;
|
||||
import org.springframework.beans.factory.aot.AotProcessingException;
|
||||
import org.springframework.beans.factory.aot.AotServices;
|
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
|
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
|
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationCode;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A collection of {@link BeanFactoryInitializationAotContribution AOT
|
||||
@@ -63,8 +66,7 @@ class BeanFactoryInitializationAotContributions {
|
||||
List<BeanFactoryInitializationAotProcessor> processors) {
|
||||
List<BeanFactoryInitializationAotContribution> contributions = new ArrayList<>();
|
||||
for (BeanFactoryInitializationAotProcessor processor : processors) {
|
||||
BeanFactoryInitializationAotContribution contribution = processor
|
||||
.processAheadOfTime(beanFactory);
|
||||
BeanFactoryInitializationAotContribution contribution = processAheadOfTime(processor, beanFactory);
|
||||
if (contribution != null) {
|
||||
contributions.add(contribution);
|
||||
}
|
||||
@@ -72,6 +74,22 @@ class BeanFactoryInitializationAotContributions {
|
||||
return Collections.unmodifiableList(contributions);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private BeanFactoryInitializationAotContribution processAheadOfTime(BeanFactoryInitializationAotProcessor processor,
|
||||
DefaultListableBeanFactory beanFactory) {
|
||||
|
||||
try {
|
||||
return processor.processAheadOfTime(beanFactory);
|
||||
}
|
||||
catch (AotException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new AotProcessingException("Error executing '" +
|
||||
processor.getClass().getName() + "': " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
void applyTo(GenerationContext generationContext,
|
||||
BeanFactoryInitializationCode beanFactoryInitializationCode) {
|
||||
for (BeanFactoryInitializationAotContribution contribution : this.contributions) {
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
|
||||
import org.springframework.aot.test.generate.TestGenerationContext;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
|
||||
import org.springframework.beans.factory.aot.AotProcessingException;
|
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
|
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
|
||||
@@ -94,6 +95,7 @@ import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link ApplicationContextAotGenerator}.
|
||||
@@ -587,6 +589,22 @@ class ApplicationContextAotGeneratorTests {
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ExceptionHanding {
|
||||
|
||||
@Test
|
||||
void failureProcessingBeanFactoryAotContribution() {
|
||||
GenericApplicationContext applicationContext = new GenericApplicationContext();
|
||||
applicationContext.registerBeanDefinition("test",
|
||||
new RootBeanDefinition(FailingBeanFactoryInitializationAotContribution.class));
|
||||
assertThatExceptionOfType(AotProcessingException.class)
|
||||
.isThrownBy(() -> processAheadOfTime(applicationContext))
|
||||
.withMessageStartingWith("Error executing '")
|
||||
.withMessageContaining(FailingBeanFactoryInitializationAotContribution.class.getName())
|
||||
.withMessageContaining("Test exception");
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerBeanPostProcessor(GenericApplicationContext applicationContext,
|
||||
String beanName, Class<?> beanPostProcessorClass) {
|
||||
|
||||
@@ -676,4 +694,12 @@ class ApplicationContextAotGeneratorTests {
|
||||
|
||||
}
|
||||
|
||||
static class FailingBeanFactoryInitializationAotContribution implements BeanFactoryInitializationAotProcessor {
|
||||
|
||||
@Override
|
||||
public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) {
|
||||
throw new IllegalStateException("Test exception");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.aot.test.generate.TestGenerationContext;
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.factory.aot.AotProcessingException;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -40,7 +41,7 @@ import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link RuntimeHintsBeanFactoryInitializationAotProcessor}.
|
||||
@@ -119,9 +120,9 @@ class RuntimeHintsBeanFactoryInitializationAotProcessorTests {
|
||||
void shouldRejectRuntimeHintsRegistrarWithoutDefaultConstructor() {
|
||||
GenericApplicationContext applicationContext = createApplicationContext(
|
||||
ConfigurationWithIllegalRegistrar.class);
|
||||
assertThatThrownBy(() -> this.generator.processAheadOfTime(
|
||||
applicationContext, this.generationContext))
|
||||
.isInstanceOf(BeanInstantiationException.class);
|
||||
assertThatExceptionOfType(AotProcessingException.class)
|
||||
.isThrownBy(() -> this.generator.processAheadOfTime(applicationContext, this.generationContext))
|
||||
.havingCause().isInstanceOf(BeanInstantiationException.class);
|
||||
}
|
||||
|
||||
private void assertThatSampleRegistrarContributed() {
|
||||
|
||||
Reference in New Issue
Block a user