Browse Source

Add checks for factories files

META-INF/spring.factories and META-INF/spring/aot.factories in the
main source set are now checked. The checks verify that:

- Each class listed in the values exists in the source set's output
- The classes are listed alphabetically
- Nested classes are identified using their binary name

Closes gh-44676
pull/42891/head
Andy Wilkinson 9 months ago
parent
commit
3a6e4e9e58
  1. 39
      buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java
  2. 32
      buildSrc/src/main/java/org/springframework/boot/build/springframework/CheckAotFactories.java
  3. 178
      buildSrc/src/main/java/org/springframework/boot/build/springframework/CheckFactoriesFile.java
  4. 32
      buildSrc/src/main/java/org/springframework/boot/build/springframework/CheckSpringFactories.java
  5. 2
      spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/aot.factories
  6. 2
      spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
  7. 6
      spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/aot.factories
  8. 4
      spring-boot-project/spring-boot-devtools/src/main/resources/META-INF/spring.factories
  9. 2
      spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories
  10. 2
      spring-boot-project/spring-boot-test/src/main/resources/META-INF/spring/aot.factories
  11. 2
      spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories
  12. 4
      spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/aot.factories
  13. 10
      spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories
  14. 12
      spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories

39
buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java

@ -32,6 +32,7 @@ import io.spring.javaformat.gradle.tasks.CheckFormat; @@ -32,6 +32,7 @@ import io.spring.javaformat.gradle.tasks.CheckFormat;
import io.spring.javaformat.gradle.tasks.Format;
import org.gradle.api.JavaVersion;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.artifacts.Dependency;
@ -54,6 +55,8 @@ import org.gradle.external.javadoc.CoreJavadocOptions; @@ -54,6 +55,8 @@ import org.gradle.external.javadoc.CoreJavadocOptions;
import org.springframework.boot.build.architecture.ArchitecturePlugin;
import org.springframework.boot.build.classpath.CheckClasspathForProhibitedDependencies;
import org.springframework.boot.build.optional.OptionalDependenciesPlugin;
import org.springframework.boot.build.springframework.CheckAotFactories;
import org.springframework.boot.build.springframework.CheckSpringFactories;
import org.springframework.boot.build.testing.TestFailuresPlugin;
import org.springframework.boot.build.toolchain.ToolchainPlugin;
import org.springframework.util.StringUtils;
@ -98,6 +101,19 @@ import org.springframework.util.StringUtils; @@ -98,6 +101,19 @@ import org.springframework.util.StringUtils;
* <li>{@code Implementation-Version}
* </ul>
* <li>{@code spring-boot-parent} is used for dependency management</li>
* <li>Additional checks are configured:
* <ul>
* <li>For all source sets:
* <ul>
* <li>Prohibited dependencies on the compile classpath
* <li>Prohibited dependencies on the runtime classpath
* </ul>
* <li>For the {@code main} source set:
* <ul>
* <li>{@code META-INF/spring/aot.factories}
* <li>{@code META-INF/spring.factories}
* </ul>
* </ul>
* </ul>
*
* <p/>
@ -123,6 +139,7 @@ class JavaConventions { @@ -123,6 +139,7 @@ class JavaConventions {
configureDependencyManagement(project);
configureToolchain(project);
configureProhibitedDependencyChecks(project);
configureFactoriesFilesChecks(project);
});
}
@ -304,4 +321,26 @@ class JavaConventions { @@ -304,4 +321,26 @@ class JavaConventions {
project.getTasks().getByName(JavaBasePlugin.CHECK_TASK_NAME).dependsOn(checkClasspathForProhibitedDependencies);
}
private void configureFactoriesFilesChecks(Project project) {
SourceSetContainer sourceSets = project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets();
sourceSets.matching((sourceSet) -> SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName()))
.configureEach((main) -> {
TaskProvider<Task> check = project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME);
TaskProvider<CheckAotFactories> checkAotFactories = project.getTasks()
.register("checkAotFactories", CheckAotFactories.class, (task) -> {
task.setSource(main.getResources());
task.setClasspath(main.getOutput().getClassesDirs());
task.setDescription("Checks the META-INF/spring/aot.factories file of the main source set.");
});
check.configure((task) -> task.dependsOn(checkAotFactories));
TaskProvider<CheckSpringFactories> checkSpringFactories = project.getTasks()
.register("checkSpringFactories", CheckSpringFactories.class, (task) -> {
task.setSource(main.getResources());
task.setClasspath(main.getOutput().getClassesDirs());
task.setDescription("Checks the META-INF/spring.factories file of the main source set.");
});
check.configure((task) -> task.dependsOn(checkSpringFactories));
});
}
}

32
buildSrc/src/main/java/org/springframework/boot/build/springframework/CheckAotFactories.java

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
/*
* Copyright 2012-2025 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.build.springframework;
import org.gradle.api.Task;
/**
* {@link Task} that checks {@code META-INF/spring/aot.factories}.
*
* @author Andy Wilkinson
*/
public abstract class CheckAotFactories extends CheckFactoriesFile {
public CheckAotFactories() {
super("META-INF/spring/aot.factories");
}
}

178
buildSrc/src/main/java/org/springframework/boot/build/springframework/CheckFactoriesFile.java

@ -0,0 +1,178 @@ @@ -0,0 +1,178 @@
/*
* Copyright 2012-2025 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.build.springframework;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.Task;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SkipWhenEmpty;
import org.gradle.api.tasks.TaskAction;
import org.gradle.language.base.plugins.LifecycleBasePlugin;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.StringUtils;
/**
* {@link Task} that checks files loaded by {@link SpringFactoriesLoader}.
*
* @author Andy Wilkinson
*/
public abstract class CheckFactoriesFile extends DefaultTask {
private final String path;
private FileCollection sourceFiles = getProject().getObjects().fileCollection();
private FileCollection classpath = getProject().getObjects().fileCollection();
protected CheckFactoriesFile(String path) {
this.path = path;
getOutputDirectory().convention(getProject().getLayout().getBuildDirectory().dir(getName()));
setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
}
@InputFiles
@SkipWhenEmpty
@PathSensitive(PathSensitivity.RELATIVE)
public FileTree getSource() {
return this.sourceFiles.getAsFileTree().matching((filter) -> filter.include(this.path));
}
public void setSource(Object source) {
this.sourceFiles = getProject().getObjects().fileCollection().from(source);
}
@Classpath
public FileCollection getClasspath() {
return this.classpath;
}
public void setClasspath(Object classpath) {
this.classpath = getProject().getObjects().fileCollection().from(classpath);
}
@OutputDirectory
public abstract DirectoryProperty getOutputDirectory();
@TaskAction
void execute() {
getSource().forEach(this::check);
}
private void check(File factoriesFile) {
Properties factories = load(factoriesFile);
Map<String, List<String>> problems = new LinkedHashMap<>();
for (String key : factories.stringPropertyNames()) {
List<String> values = Arrays
.asList(StringUtils.commaDelimitedListToStringArray(factories.getProperty(key)));
for (String value : values) {
boolean found = find(value);
if (!found) {
List<String> problemsForKey = problems.computeIfAbsent(key, (k) -> new ArrayList<>());
String binaryName = binaryNameOf(value);
found = find(binaryName);
if (found) {
problemsForKey
.add("'%s' should be listed using its binary name '%s'".formatted(value, binaryName));
}
else {
problemsForKey.add("'%s' was not found".formatted(value));
}
}
}
List<String> sortedValues = new ArrayList<>(values);
Collections.sort(sortedValues);
if (!sortedValues.equals(values)) {
List<String> problemsForKey = problems.computeIfAbsent(key, (k) -> new ArrayList<>());
problemsForKey.add("Entries should be sorted alphabetically");
}
}
File outputFile = getOutputDirectory().file("failure-report.txt").get().getAsFile();
writeReport(factoriesFile, problems, outputFile);
if (!problems.isEmpty()) {
throw new GradleException("%s check failed. See '%s' for details".formatted(this.path, outputFile));
}
}
private boolean find(String className) {
for (File root : this.classpath.getFiles()) {
String classFilePath = className.replace(".", "/") + ".class";
if (new File(root, classFilePath).isFile()) {
return true;
}
}
return false;
}
private String binaryNameOf(String className) {
int lastDotIndex = className.lastIndexOf('.');
return className.substring(0, lastDotIndex) + "$" + className.substring(lastDotIndex + 1);
}
private Properties load(File aotFactories) {
Properties properties = new Properties();
try (FileInputStream input = new FileInputStream(aotFactories)) {
properties.load(input);
return properties;
}
catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
private void writeReport(File factoriesFile, Map<String, List<String>> problems, File outputFile) {
outputFile.getParentFile().mkdirs();
StringBuilder report = new StringBuilder();
if (!problems.isEmpty()) {
report.append("Found problems in '%s':%n".formatted(factoriesFile));
problems.forEach((key, problemsForKey) -> {
report.append(" - %s:%n".formatted(key));
problemsForKey.forEach((problem) -> report.append(" - %s%n".formatted(problem)));
});
}
try {
Files.writeString(outputFile.toPath(), report.toString(), StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING);
}
catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
}

32
buildSrc/src/main/java/org/springframework/boot/build/springframework/CheckSpringFactories.java

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
/*
* Copyright 2012-2025 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.build.springframework;
import org.gradle.api.Task;
/**
* {@link Task} that checks {@code META-INF/spring.factories}.
*
* @author Andy Wilkinson
*/
public abstract class CheckSpringFactories extends CheckFactoriesFile {
public CheckSpringFactories() {
super("META-INF/spring.factories");
}
}

2
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/aot.factories

@ -1,2 +1,2 @@ @@ -1,2 +1,2 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.boot.actuate.autoconfigure.metrics.ServiceLevelObjectiveBoundary.ServiceLevelObjectiveBoundaryHints
org.springframework.boot.actuate.autoconfigure.metrics.ServiceLevelObjectiveBoundary$ServiceLevelObjectiveBoundaryHints

2
spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

@ -37,8 +37,8 @@ org.springframework.boot.autoconfigure.ssl.BundleContentNotWatchableFailureAnaly @@ -37,8 +37,8 @@ org.springframework.boot.autoconfigure.ssl.BundleContentNotWatchableFailureAnaly
# Template Availability Providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider

6
spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/aot.factories

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider.FreeMarkerTemplateAvailabilityRuntimeHints,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider.GroovyTemplateAvailabilityRuntimeHints,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.JacksonAutoConfigurationRuntimeHints,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider$FreeMarkerTemplateAvailabilityRuntimeHints,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider$GroovyTemplateAvailabilityRuntimeHints,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonAutoConfigurationRuntimeHints,\
org.springframework.boot.autoconfigure.template.TemplateRuntimeHints
org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=\

4
spring-boot-project/spring-boot-devtools/src/main/resources/META-INF/spring.factories

@ -4,8 +4,8 @@ org.springframework.boot.devtools.restart.RestartScopeInitializer @@ -4,8 +4,8 @@ org.springframework.boot.devtools.restart.RestartScopeInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.devtools.restart.RestartApplicationListener,\
org.springframework.boot.devtools.logger.DevToolsLogFactory.Listener
org.springframework.boot.devtools.logger.DevToolsLogFactory$Listener,\
org.springframework.boot.devtools.restart.RestartApplicationListener
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\

2
spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories

@ -20,8 +20,8 @@ org.springframework.boot.docker.compose.service.connection.mysql.MySqlJdbcDocker @@ -20,8 +20,8 @@ org.springframework.boot.docker.compose.service.connection.mysql.MySqlJdbcDocker
org.springframework.boot.docker.compose.service.connection.mysql.MySqlR2dbcDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.neo4j.Neo4jDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.oracle.OracleFreeJdbcDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.oracle.OracleXeJdbcDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.oracle.OracleFreeR2dbcDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.oracle.OracleXeJdbcDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.oracle.OracleXeR2dbcDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.otlp.OpenTelemetryMetricsDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.otlp.OpenTelemetryTracingDockerComposeConnectionDetailsFactory,\

2
spring-boot-project/spring-boot-test/src/main/resources/META-INF/spring/aot.factories

@ -1,2 +1,2 @@ @@ -1,2 +1,2 @@
org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=\
org.springframework.boot.test.context.SpringBootContextLoader.MainMethodBeanFactoryInitializationAotProcessor
org.springframework.boot.test.context.SpringBootContextLoader$MainMethodBeanFactoryInitializationAotProcessor

2
spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories

@ -14,8 +14,8 @@ org.springframework.boot.testcontainers.service.connection.activemq.ArtemisConta @@ -14,8 +14,8 @@ org.springframework.boot.testcontainers.service.connection.activemq.ArtemisConta
org.springframework.boot.testcontainers.service.connection.amqp.RabbitContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.cassandra.CassandraContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.couchbase.CouchbaseContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.flyway.FlywayContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.elasticsearch.ElasticsearchContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.flyway.FlywayContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.jdbc.JdbcContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.kafka.KafkaContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.ldap.OpenLdapContainerConnectionDetailsFactory,\

4
spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/aot.factories

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter=\
org.springframework.boot.testcontainers.service.connection.ConnectionDetailsRegistrar.ServiceConnectionBeanRegistrationExcludeFilter
org.springframework.boot.testcontainers.service.connection.ConnectionDetailsRegistrar$ServiceConnectionBeanRegistrationExcludeFilter
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory.ContainerConnectionDetailsFactoriesRuntimeHints
org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory$ContainerConnectionDetailsFactoriesRuntimeHints

10
spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
# Logging Systems
org.springframework.boot.logging.LoggingSystemFactory=\
org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,\
org.springframework.boot.logging.java.JavaLoggingSystem.Factory
org.springframework.boot.logging.java.JavaLoggingSystem$Factory,\
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem$Factory,\
org.springframework.boot.logging.logback.LogbackLoggingSystem$Factory
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
@ -98,10 +98,10 @@ org.springframework.boot.r2dbc.init.R2dbcScriptDatabaseInitializerDetector @@ -98,10 +98,10 @@ org.springframework.boot.r2dbc.init.R2dbcScriptDatabaseInitializerDetector
# Depends On Database Initialization Detectors
org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector=\
org.springframework.boot.sql.init.dependency.AnnotationDependsOnDatabaseInitializationDetector,\
org.springframework.boot.jdbc.SpringJdbcDependsOnDatabaseInitializationDetector,\
org.springframework.boot.jooq.JooqDependsOnDatabaseInitializationDetector,\
org.springframework.boot.orm.jpa.JpaDependsOnDatabaseInitializationDetector
org.springframework.boot.orm.jpa.JpaDependsOnDatabaseInitializationDetector,\
org.springframework.boot.sql.init.dependency.AnnotationDependsOnDatabaseInitializationDetector
# Resource Locator Protocol Resolvers
org.springframework.core.io.ProtocolResolver=\

12
spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.boot.SpringApplication.SpringApplicationRuntimeHints,\
org.springframework.boot.SpringApplicationBannerPrinter.SpringApplicationBannerPrinterRuntimeHints,\
org.springframework.boot.WebApplicationType.WebApplicationTypeRuntimeHints,\
org.springframework.boot.SpringApplication$SpringApplicationRuntimeHints,\
org.springframework.boot.SpringApplicationBannerPrinter$SpringApplicationBannerPrinterRuntimeHints,\
org.springframework.boot.WebApplicationType$WebApplicationTypeRuntimeHints,\
org.springframework.boot.context.config.ConfigDataLocationRuntimeHints,\
org.springframework.boot.context.config.ConfigDataPropertiesRuntimeHints,\
org.springframework.boot.env.PropertySourceRuntimeHints,\
@ -10,12 +10,12 @@ org.springframework.boot.json.JacksonRuntimeHints,\ @@ -10,12 +10,12 @@ org.springframework.boot.json.JacksonRuntimeHints,\
org.springframework.boot.logging.java.JavaLoggingSystemRuntimeHints,\
org.springframework.boot.logging.logback.LogbackRuntimeHints,\
org.springframework.boot.web.client.ClientHttpRequestFactoriesRuntimeHints,\
org.springframework.boot.web.embedded.undertow.UndertowWebServer.UndertowWebServerRuntimeHints,\
org.springframework.boot.web.server.MimeMappings.MimeMappingsRuntimeHints
org.springframework.boot.web.embedded.undertow.UndertowWebServer$UndertowWebServerRuntimeHints,\
org.springframework.boot.web.server.MimeMappings$MimeMappingsRuntimeHints
org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=\
org.springframework.boot.context.properties.ConfigurationPropertiesBeanFactoryInitializationAotProcessor,\
org.springframework.boot.jackson.JsonComponentModule.JsonComponentBeanFactoryInitializationAotProcessor
org.springframework.boot.jackson.JsonComponentModule$JsonComponentBeanFactoryInitializationAotProcessor
org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\
org.springframework.boot.context.properties.ConfigurationPropertiesBeanRegistrationAotProcessor,\

Loading…
Cancel
Save