Merge branch '3.2.x'

Closes gh-40584
This commit is contained in:
Moritz Halbritter
2024-04-30 15:11:48 +02:00
6 changed files with 137 additions and 6 deletions

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2012-2024 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot;
/**
* Exception thrown when the AOT initializer couldn't be found.
*
* @author Moritz Halbritter
* @since 3.2.6
*/
public class AotInitializerNotFoundException extends RuntimeException {
private final Class<?> mainClass;
public AotInitializerNotFoundException(Class<?> mainClass, String initializerClassName) {
super("Startup with AOT mode enabled failed: AOT initializer %s could not be found"
.formatted(initializerClassName));
this.mainClass = mainClass;
}
public Class<?> getMainClass() {
return this.mainClass;
}
}

View File

@@ -439,10 +439,9 @@ public class SpringApplication {
initializers.stream().filter(AotApplicationContextInitializer.class::isInstance).toList());
if (aotInitializers.isEmpty()) {
String initializerClassName = this.mainApplicationClass.getName() + "__ApplicationContextInitializer";
Assert.state(ClassUtils.isPresent(initializerClassName, getClassLoader()),
"You are starting the application with AOT mode enabled but AOT processing hasn't happened. "
+ "Please build your application with enabled AOT processing first, "
+ "or remove the system property 'spring.aot.enabled' to run the application in regular mode");
if (!ClassUtils.isPresent(initializerClassName, getClassLoader())) {
throw new AotInitializerNotFoundException(this.mainApplicationClass, initializerClassName);
}
aotInitializers.add(AotApplicationContextInitializer.forInitializerClasses(initializerClassName));
}
initializers.removeAll(aotInitializers);

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2012-2024 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.diagnostics.analyzer;
import org.springframework.boot.AotInitializerNotFoundException;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
/**
* An {@link AbstractFailureAnalyzer} that performs analysis of failures caused by a
* {@link AotInitializerNotFoundException}.
*
* @author Moritz Halbritter
*/
class AotInitializerNotFoundFailureAnalyzer extends AbstractFailureAnalyzer<AotInitializerNotFoundException> {
@Override
protected FailureAnalysis analyze(Throwable rootFailure, AotInitializerNotFoundException cause) {
return new FailureAnalysis(cause.getMessage(), "Consider the following:\n"
+ "\tDid you build the application with enabled AOT processing?\n"
+ "\tIs the main class %s correct?\n".formatted(cause.getMainClass().getName())
+ "\tIf you want to run the application in regular mode, remove the system property 'spring.aot.enabled'",
cause);
}
}

View File

@@ -64,6 +64,7 @@ org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.context.config.ConfigDataNotFoundFailureAnalyzer,\
org.springframework.boot.context.properties.IncompatibleConfigurationFailureAnalyzer,\
org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.AotInitializerNotFoundFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\

View File

@@ -1445,8 +1445,8 @@ class SpringApplicationTests {
application.setMainApplicationClass(TestSpringApplication.class);
System.setProperty(AotDetector.AOT_ENABLED, "true");
try {
assertThatIllegalStateException().isThrownBy(application::run)
.withMessageContaining("but AOT processing hasn't happened");
assertThatExceptionOfType(AotInitializerNotFoundException.class).isThrownBy(application::run)
.withMessageMatching("^.+AOT initializer .+ could not be found$");
}
finally {
System.clearProperty(AotDetector.AOT_ENABLED);

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2012-2024 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.diagnostics.analyzer;
import org.junit.jupiter.api.Test;
import org.springframework.boot.AotInitializerNotFoundException;
import org.springframework.boot.diagnostics.FailureAnalysis;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link AotInitializerNotFoundFailureAnalyzer}.
*
* @author Moritz Halbritter
*/
class AotInitializerNotFoundFailureAnalyzerTests {
@Test
void shouldAnalyze() {
FailureAnalysis analysis = analyze();
assertThat(analysis.getDescription()).isEqualTo(
"Startup with AOT mode enabled failed: AOT initializer class org.springframework.boot.diagnostics.analyzer.AotInitializerNotFoundFailureAnalyzerTests__ApplicationContextInitializer could not be found");
assertThat(analysis.getAction()).isEqualTo(
"""
Consider the following:
\tDid you build the application with enabled AOT processing?
\tIs the main class org.springframework.boot.diagnostics.analyzer.AotInitializerNotFoundFailureAnalyzerTests correct?
\tIf you want to run the application in regular mode, remove the system property 'spring.aot.enabled'""");
}
private FailureAnalysis analyze() {
return new AotInitializerNotFoundFailureAnalyzer()
.analyze(new AotInitializerNotFoundException(AotInitializerNotFoundFailureAnalyzerTests.class,
AotInitializerNotFoundFailureAnalyzerTests.class + "__ApplicationContextInitializer"));
}
}