Browse Source

Add nullability annotations to core/spring-boot

See gh-46587
pull/46595/head
Moritz Halbritter 9 months ago
parent
commit
1b3e9e679f
  1. 4
      config/checkstyle/checkstyle-suppressions.xml
  2. 4
      core/spring-boot/src/main/java/org/springframework/boot/ApplicationArguments.java
  3. 13
      core/spring-boot/src/main/java/org/springframework/boot/ApplicationContextFactory.java
  4. 6
      core/spring-boot/src/main/java/org/springframework/boot/ApplicationEnvironment.java
  5. 10
      core/spring-boot/src/main/java/org/springframework/boot/ApplicationInfoPropertySource.java
  6. 20
      core/spring-boot/src/main/java/org/springframework/boot/ApplicationProperties.java
  7. 6
      core/spring-boot/src/main/java/org/springframework/boot/Banner.java
  8. 21
      core/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java
  9. 11
      core/spring-boot/src/main/java/org/springframework/boot/BootstrapContext.java
  10. 14
      core/spring-boot/src/main/java/org/springframework/boot/BootstrapRegistry.java
  11. 4
      core/spring-boot/src/main/java/org/springframework/boot/ClearCachesApplicationListener.java
  12. 6
      core/spring-boot/src/main/java/org/springframework/boot/DefaultApplicationArguments.java
  13. 22
      core/spring-boot/src/main/java/org/springframework/boot/DefaultApplicationContextFactory.java
  14. 19
      core/spring-boot/src/main/java/org/springframework/boot/DefaultBootstrapContext.java
  15. 7
      core/spring-boot/src/main/java/org/springframework/boot/DefaultPropertiesPropertySource.java
  16. 6
      core/spring-boot/src/main/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessor.java
  17. 27
      core/spring-boot/src/main/java/org/springframework/boot/ResourceBanner.java
  18. 108
      core/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java
  19. 5
      core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationAotProcessor.java
  20. 23
      core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java
  21. 6
      core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationHook.java
  22. 8
      core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationRunListener.java
  23. 16
      core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationRunListeners.java
  24. 4
      core/spring-boot/src/main/java/org/springframework/boot/SpringBootBanner.java
  25. 16
      core/spring-boot/src/main/java/org/springframework/boot/SpringBootExceptionHandler.java
  26. 7
      core/spring-boot/src/main/java/org/springframework/boot/StartupInfoLogger.java
  27. 6
      core/spring-boot/src/main/java/org/springframework/boot/WebApplicationType.java
  28. 4
      core/spring-boot/src/main/java/org/springframework/boot/admin/SpringApplicationAdminMXBean.java
  29. 6
      core/spring-boot/src/main/java/org/springframework/boot/admin/SpringApplicationAdminMXBeanRegistrar.java
  30. 3
      core/spring-boot/src/main/java/org/springframework/boot/admin/package-info.java
  31. 10
      core/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java
  32. 10
      core/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java
  33. 3
      core/spring-boot/src/main/java/org/springframework/boot/ansi/package-info.java
  34. 6
      core/spring-boot/src/main/java/org/springframework/boot/availability/ApplicationAvailability.java
  35. 7
      core/spring-boot/src/main/java/org/springframework/boot/availability/ApplicationAvailabilityBean.java
  36. 3
      core/spring-boot/src/main/java/org/springframework/boot/availability/package-info.java
  37. 3
      core/spring-boot/src/main/java/org/springframework/boot/builder/ParentContextCloserApplicationListener.java
  38. 29
      core/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java
  39. 3
      core/spring-boot/src/main/java/org/springframework/boot/builder/package-info.java
  40. 9
      core/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java
  41. 6
      core/spring-boot/src/main/java/org/springframework/boot/cloud/CloudPlatform.java
  42. 3
      core/spring-boot/src/main/java/org/springframework/boot/cloud/package-info.java
  43. 11
      core/spring-boot/src/main/java/org/springframework/boot/context/ApplicationPidFileWriter.java
  44. 13
      core/spring-boot/src/main/java/org/springframework/boot/context/ConfigurationWarningsApplicationContextInitializer.java
  45. 7
      core/spring-boot/src/main/java/org/springframework/boot/context/TypeExcludeFilter.java
  46. 10
      core/spring-boot/src/main/java/org/springframework/boot/context/annotation/Configurations.java
  47. 6
      core/spring-boot/src/main/java/org/springframework/boot/context/annotation/ImportCandidates.java
  48. 3
      core/spring-boot/src/main/java/org/springframework/boot/context/annotation/package-info.java
  49. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigData.java
  50. 14
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataActivationContext.java
  51. 7
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java
  52. 49
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentContributor.java
  53. 19
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentContributorPlaceholdersResolver.java
  54. 29
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentContributors.java
  55. 15
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessor.java
  56. 6
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentUpdateListener.java
  57. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataException.java
  58. 13
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataImporter.java
  59. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLoader.java
  60. 6
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLoaders.java
  61. 27
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocation.java
  62. 8
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationNotFoundException.java
  63. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationResolverContext.java
  64. 9
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationResolvers.java
  65. 11
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationRuntimeHints.java
  66. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataNotFoundException.java
  67. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataNotFoundFailureAnalyzer.java
  68. 18
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataProperties.java
  69. 13
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataPropertiesRuntimeHints.java
  70. 18
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataResourceNotFoundException.java
  71. 6
      core/spring-boot/src/main/java/org/springframework/boot/context/config/FileExtensionHint.java
  72. 20
      core/spring-boot/src/main/java/org/springframework/boot/context/config/InactiveConfigDataAccessException.java
  73. 14
      core/spring-boot/src/main/java/org/springframework/boot/context/config/InvalidConfigDataPropertyException.java
  74. 14
      core/spring-boot/src/main/java/org/springframework/boot/context/config/Profiles.java
  75. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/config/ProfilesValidator.java
  76. 19
      core/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataLocationResolver.java
  77. 14
      core/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataReference.java
  78. 8
      core/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataResource.java
  79. 6
      core/spring-boot/src/main/java/org/springframework/boot/context/config/SystemEnvironmentConfigDataLocationResolver.java
  80. 8
      core/spring-boot/src/main/java/org/springframework/boot/context/config/SystemEnvironmentConfigDataResource.java
  81. 3
      core/spring-boot/src/main/java/org/springframework/boot/context/config/package-info.java
  82. 12
      core/spring-boot/src/main/java/org/springframework/boot/context/event/ApplicationFailedEvent.java
  83. 8
      core/spring-boot/src/main/java/org/springframework/boot/context/event/ApplicationReadyEvent.java
  84. 8
      core/spring-boot/src/main/java/org/springframework/boot/context/event/ApplicationStartedEvent.java
  85. 7
      core/spring-boot/src/main/java/org/springframework/boot/context/event/EventPublishingRunListener.java
  86. 3
      core/spring-boot/src/main/java/org/springframework/boot/context/event/package-info.java
  87. 21
      core/spring-boot/src/main/java/org/springframework/boot/context/logging/LoggingApplicationListener.java
  88. 3
      core/spring-boot/src/main/java/org/springframework/boot/context/logging/package-info.java
  89. 10
      core/spring-boot/src/main/java/org/springframework/boot/context/metrics/buffering/BufferedStartupStep.java
  90. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/metrics/buffering/BufferingApplicationStartup.java
  91. 3
      core/spring-boot/src/main/java/org/springframework/boot/context/metrics/buffering/package-info.java
  92. 3
      core/spring-boot/src/main/java/org/springframework/boot/context/package-info.java
  93. 10
      core/spring-boot/src/main/java/org/springframework/boot/context/properties/BindMethodAttribute.java
  94. 6
      core/spring-boot/src/main/java/org/springframework/boot/context/properties/BoundConfigurationProperties.java
  95. 45
      core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java
  96. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanFactoryInitializationAotProcessor.java
  97. 4
      core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrationAotProcessor.java
  98. 24
      core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java
  99. 7
      core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java
  100. 7
      core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesCharSequenceToObjectConverter.java
  101. Some files were not shown because too many files have changed in this diff Show More

4
config/checkstyle/checkstyle-suppressions.xml

@ -86,4 +86,8 @@ @@ -86,4 +86,8 @@
<suppress files="ConfigurationPropertyCaching\.java" checks="SpringJavadoc" message="\@since"/>
<suppress files="StructuredLoggingJsonMembersCustomizer\.java" checks="SpringJavadoc" message="\@since"/>
<suppress files="FieldValues\.java" checks="SimplifyBooleanExpression" />
<!-- jspecify: https://github.com/spring-io/spring-javaformat/issues/454 -->
<suppress files="PemPrivateKeyParser\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
<suppress files="Bindable\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
<suppress files="LambdaSafe\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
</suppressions>

4
core/spring-boot/src/main/java/org/springframework/boot/ApplicationArguments.java

@ -19,6 +19,8 @@ package org.springframework.boot; @@ -19,6 +19,8 @@ package org.springframework.boot;
import java.util.List;
import java.util.Set;
import org.jspecify.annotations.Nullable;
/**
* Provides access to the arguments that were used to run a {@link SpringApplication}.
*
@ -63,7 +65,7 @@ public interface ApplicationArguments { @@ -63,7 +65,7 @@ public interface ApplicationArguments {
* @param name the name of the option
* @return a list of option values for the given name
*/
List<String> getOptionValues(String name);
@Nullable List<String> getOptionValues(String name);
/**
* Return the collection of non-option arguments parsed.

13
core/spring-boot/src/main/java/org/springframework/boot/ApplicationContextFactory.java

@ -18,6 +18,8 @@ package org.springframework.boot; @@ -18,6 +18,8 @@ package org.springframework.boot;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
@ -46,11 +48,12 @@ public interface ApplicationContextFactory { @@ -46,11 +48,12 @@ public interface ApplicationContextFactory {
* Return the {@link Environment} type expected to be set on the
* {@link #create(WebApplicationType) created} application context. The result of this
* method can be used to convert an existing environment instance to the correct type.
* @param webApplicationType the web application type
* @param webApplicationType the web application type or {@code null}
* @return the expected application context type or {@code null} to use the default
* @since 2.6.14
*/
default Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
default @Nullable Class<? extends ConfigurableEnvironment> getEnvironmentType(
@Nullable WebApplicationType webApplicationType) {
return null;
}
@ -59,11 +62,11 @@ public interface ApplicationContextFactory { @@ -59,11 +62,11 @@ public interface ApplicationContextFactory {
* {@link #create(WebApplicationType) created} application context. The result of this
* method must match the type returned by
* {@link #getEnvironmentType(WebApplicationType)}.
* @param webApplicationType the web application type
* @param webApplicationType the web application type or {@code null}
* @return an environment instance or {@code null} to use the default
* @since 2.6.14
*/
default ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
default @Nullable ConfigurableEnvironment createEnvironment(@Nullable WebApplicationType webApplicationType) {
return null;
}
@ -73,7 +76,7 @@ public interface ApplicationContextFactory { @@ -73,7 +76,7 @@ public interface ApplicationContextFactory {
* @param webApplicationType the web application type
* @return the newly created application context
*/
ConfigurableApplicationContext create(WebApplicationType webApplicationType);
ConfigurableApplicationContext create(@Nullable WebApplicationType webApplicationType);
/**
* Creates an {@code ApplicationContextFactory} that will create contexts by

6
core/spring-boot/src/main/java/org/springframework/boot/ApplicationEnvironment.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.core.env.ConfigurablePropertyResolver;
import org.springframework.core.env.MutablePropertySources;
@ -29,12 +31,12 @@ import org.springframework.core.env.StandardEnvironment; @@ -29,12 +31,12 @@ import org.springframework.core.env.StandardEnvironment;
class ApplicationEnvironment extends StandardEnvironment {
@Override
protected String doGetActiveProfilesProperty() {
protected @Nullable String doGetActiveProfilesProperty() {
return null;
}
@Override
protected String doGetDefaultProfilesProperty() {
protected @Nullable String doGetDefaultProfilesProperty() {
return null;
}

10
core/spring-boot/src/main/java/org/springframework/boot/ApplicationInfoPropertySource.java

@ -19,6 +19,8 @@ package org.springframework.boot; @@ -19,6 +19,8 @@ package org.springframework.boot;
import java.util.HashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginLookup;
import org.springframework.boot.system.ApplicationPid;
@ -38,7 +40,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL @@ -38,7 +40,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL
static final String NAME = "applicationInfo";
ApplicationInfoPropertySource(Class<?> mainClass) {
ApplicationInfoPropertySource(@Nullable Class<?> mainClass) {
super(NAME, getProperties(readVersion(mainClass)));
}
@ -47,7 +49,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL @@ -47,7 +49,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL
}
@Override
public Origin getOrigin(String key) {
public @Nullable Origin getOrigin(String key) {
return null;
}
@ -56,7 +58,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL @@ -56,7 +58,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL
return true;
}
private static Map<String, Object> getProperties(String applicationVersion) {
private static Map<String, Object> getProperties(@Nullable String applicationVersion) {
Map<String, Object> result = new HashMap<>();
if (StringUtils.hasText(applicationVersion)) {
result.put("spring.application.version", applicationVersion);
@ -68,7 +70,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL @@ -68,7 +70,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL
return result;
}
private static String readVersion(Class<?> applicationClass) {
private static @Nullable String readVersion(@Nullable Class<?> applicationClass) {
Package sourcePackage = (applicationClass != null) ? applicationClass.getPackage() : null;
return (sourcePackage != null) ? sourcePackage.getImplementationVersion() : null;
}

20
core/spring-boot/src/main/java/org/springframework/boot/ApplicationProperties.java

@ -19,12 +19,15 @@ package org.springframework.boot; @@ -19,12 +19,15 @@ package org.springframework.boot;
import java.util.LinkedHashSet;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.boot.Banner.Mode;
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrar;
import org.springframework.boot.logging.LoggingSystemProperty;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
/**
* Spring application properties.
@ -48,7 +51,7 @@ class ApplicationProperties { @@ -48,7 +51,7 @@ class ApplicationProperties {
/**
* Mode used to display the banner when the application runs.
*/
private Banner.Mode bannerMode;
private Banner.@Nullable Mode bannerMode;
/**
* Whether to keep the application alive even if there are no more non-daemon threads.
@ -80,7 +83,7 @@ class ApplicationProperties { @@ -80,7 +83,7 @@ class ApplicationProperties {
* Flag to explicitly request a specific type of web application. If not set,
* auto-detected based on the classpath.
*/
private WebApplicationType webApplicationType;
private @Nullable WebApplicationType webApplicationType;
boolean isAllowBeanDefinitionOverriding() {
return this.allowBeanDefinitionOverriding;
@ -102,12 +105,13 @@ class ApplicationProperties { @@ -102,12 +105,13 @@ class ApplicationProperties {
if (this.bannerMode != null) {
return this.bannerMode;
}
boolean structuredLoggingEnabled = environment
.containsProperty(LoggingSystemProperty.CONSOLE_STRUCTURED_FORMAT.getApplicationPropertyName());
String applicationPropertyName = LoggingSystemProperty.CONSOLE_STRUCTURED_FORMAT.getApplicationPropertyName();
Assert.state(applicationPropertyName != null, "applicationPropertyName must not be null");
boolean structuredLoggingEnabled = environment.containsProperty(applicationPropertyName);
return (structuredLoggingEnabled) ? Mode.OFF : Banner.Mode.CONSOLE;
}
void setBannerMode(Mode bannerMode) {
void setBannerMode(@Nullable Mode bannerMode) {
this.bannerMode = bannerMode;
}
@ -151,18 +155,18 @@ class ApplicationProperties { @@ -151,18 +155,18 @@ class ApplicationProperties {
this.sources = new LinkedHashSet<>(sources);
}
WebApplicationType getWebApplicationType() {
@Nullable WebApplicationType getWebApplicationType() {
return this.webApplicationType;
}
void setWebApplicationType(WebApplicationType webApplicationType) {
void setWebApplicationType(@Nullable WebApplicationType webApplicationType) {
this.webApplicationType = webApplicationType;
}
static class ApplicationPropertiesRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
BindableRuntimeHintsRegistrar.forTypes(ApplicationProperties.class).registerHints(hints, classLoader);
}

6
core/spring-boot/src/main/java/org/springframework/boot/Banner.java

@ -18,6 +18,8 @@ package org.springframework.boot; @@ -18,6 +18,8 @@ package org.springframework.boot;
import java.io.PrintStream;
import org.jspecify.annotations.Nullable;
import org.springframework.core.env.Environment;
/**
@ -34,10 +36,10 @@ public interface Banner { @@ -34,10 +36,10 @@ public interface Banner {
/**
* Print the banner to the specified print stream.
* @param environment the spring environment
* @param sourceClass the source class for the application
* @param sourceClass the source class for the application or {@code null}
* @param out the output print stream
*/
void printBanner(Environment environment, Class<?> sourceClass, PrintStream out);
void printBanner(Environment environment, @Nullable Class<?> sourceClass, PrintStream out);
/**
* An enumeration of possible values for configuring the Banner.

21
core/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java

@ -23,6 +23,7 @@ import java.util.Set; @@ -23,6 +23,7 @@ import java.util.Set;
import java.util.regex.Pattern;
import groovy.lang.Closure;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanDefinitionStoreException;
@ -68,11 +69,11 @@ class BeanDefinitionLoader { @@ -68,11 +69,11 @@ class BeanDefinitionLoader {
private final AbstractBeanDefinitionReader xmlReader;
private final BeanDefinitionReader groovyReader;
private final @Nullable BeanDefinitionReader groovyReader;
private final ClassPathBeanDefinitionScanner scanner;
private ResourceLoader resourceLoader;
private @Nullable ResourceLoader resourceLoader;
/**
* Create a new {@link BeanDefinitionLoader} that will load beans into the specified
@ -86,7 +87,7 @@ class BeanDefinitionLoader { @@ -86,7 +87,7 @@ class BeanDefinitionLoader {
this.sources = sources;
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = new XmlBeanDefinitionReader(registry);
this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
this.groovyReader = isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null;
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
@ -152,7 +153,7 @@ class BeanDefinitionLoader { @@ -152,7 +153,7 @@ class BeanDefinitionLoader {
}
private void load(Class<?> source) {
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
if (this.groovyReader != null && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans());
@ -163,7 +164,9 @@ class BeanDefinitionLoader { @@ -163,7 +164,9 @@ class BeanDefinitionLoader {
}
private void load(Resource source) {
if (source.getFilename().endsWith(".groovy")) {
String filename = source.getFilename();
Assert.state(filename != null, "Source has no filename");
if (filename.endsWith(".groovy")) {
if (this.groovyReader == null) {
throw new BeanDefinitionStoreException("Cannot load Groovy beans without Groovy on classpath");
}
@ -231,7 +234,7 @@ class BeanDefinitionLoader { @@ -231,7 +234,7 @@ class BeanDefinitionLoader {
}
}
private boolean isLoadCandidate(Resource resource) {
private boolean isLoadCandidate(@Nullable Resource resource) {
if (resource == null || !resource.exists()) {
return false;
}
@ -253,7 +256,7 @@ class BeanDefinitionLoader { @@ -253,7 +256,7 @@ class BeanDefinitionLoader {
return true;
}
private Package findPackage(CharSequence source) {
private @Nullable Package findPackage(CharSequence source) {
Package pkg = getClass().getClassLoader().getDefinedPackage(source.toString());
if (pkg != null) {
return pkg;
@ -264,7 +267,9 @@ class BeanDefinitionLoader { @@ -264,7 +267,9 @@ class BeanDefinitionLoader {
Resource[] resources = resolver
.getResources(ClassUtils.convertClassNameToResourcePath(source.toString()) + "/*.class");
for (Resource resource : resources) {
String className = StringUtils.stripFilenameExtension(resource.getFilename());
String filename = resource.getFilename();
Assert.state(filename != null, "No filename available");
String className = StringUtils.stripFilenameExtension(filename);
load(Class.forName(source + "." + className));
break;
}

11
core/spring-boot/src/main/java/org/springframework/boot/BootstrapContext.java

@ -18,6 +18,8 @@ package org.springframework.boot; @@ -18,6 +18,8 @@ package org.springframework.boot;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
@ -41,7 +43,7 @@ public interface BootstrapContext { @@ -41,7 +43,7 @@ public interface BootstrapContext {
* @return the instance managed by the context
* @throws IllegalStateException if the type has not been registered
*/
<T> T get(Class<T> type) throws IllegalStateException;
<T> @Nullable T get(Class<T> type) throws IllegalStateException;
/**
* Return an instance from the context if the type has been registered. The instance
@ -51,7 +53,7 @@ public interface BootstrapContext { @@ -51,7 +53,7 @@ public interface BootstrapContext {
* @param other the instance to use if the type has not been registered
* @return the instance
*/
<T> T getOrElse(Class<T> type, T other);
<T> @Nullable T getOrElse(Class<T> type, @Nullable T other);
/**
* Return an instance from the context if the type has been registered. The instance
@ -61,7 +63,7 @@ public interface BootstrapContext { @@ -61,7 +63,7 @@ public interface BootstrapContext {
* @param other a supplier for the instance to use if the type has not been registered
* @return the instance
*/
<T> T getOrElseSupply(Class<T> type, Supplier<T> other);
<T> @Nullable T getOrElseSupply(Class<T> type, Supplier<@Nullable T> other);
/**
* Return an instance from the context if the type has been registered. The instance
@ -74,7 +76,8 @@ public interface BootstrapContext { @@ -74,7 +76,8 @@ public interface BootstrapContext {
* @throws X if the type has not been registered
* @throws IllegalStateException if the type has not been registered
*/
<T, X extends Throwable> T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier) throws X;
<T, X extends Throwable> @Nullable T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier)
throws X;
/**
* Return if a registration exists for the given type.

14
core/spring-boot/src/main/java/org/springframework/boot/BootstrapRegistry.java

@ -18,6 +18,8 @@ package org.springframework.boot; @@ -18,6 +18,8 @@ package org.springframework.boot;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
@ -78,7 +80,7 @@ public interface BootstrapRegistry { @@ -78,7 +80,7 @@ public interface BootstrapRegistry {
* @param type the instance type
* @return the registered {@link InstanceSupplier} or {@code null}
*/
<T> InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type);
<T> @Nullable InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type);
/**
* Add an {@link ApplicationListener} that will be called with a
@ -101,9 +103,9 @@ public interface BootstrapRegistry { @@ -101,9 +103,9 @@ public interface BootstrapRegistry {
* Factory method used to create the instance when needed.
* @param context the {@link BootstrapContext} which may be used to obtain other
* bootstrap instances.
* @return the instance
* @return the instance or {@code null}
*/
T get(BootstrapContext context);
@Nullable T get(BootstrapContext context);
/**
* Return the scope of the supplied instance.
@ -126,7 +128,7 @@ public interface BootstrapRegistry { @@ -126,7 +128,7 @@ public interface BootstrapRegistry {
return new InstanceSupplier<>() {
@Override
public T get(BootstrapContext context) {
public @Nullable T get(BootstrapContext context) {
return parent.get(context);
}
@ -145,7 +147,7 @@ public interface BootstrapRegistry { @@ -145,7 +147,7 @@ public interface BootstrapRegistry {
* @param instance the instance
* @return a new {@link InstanceSupplier}
*/
static <T> InstanceSupplier<T> of(T instance) {
static <T> InstanceSupplier<T> of(@Nullable T instance) {
return (registry) -> instance;
}
@ -156,7 +158,7 @@ public interface BootstrapRegistry { @@ -156,7 +158,7 @@ public interface BootstrapRegistry {
* @param supplier the supplier that will provide the instance
* @return a new {@link InstanceSupplier}
*/
static <T> InstanceSupplier<T> from(Supplier<T> supplier) {
static <T> InstanceSupplier<T> from(@Nullable Supplier<T> supplier) {
return (registry) -> (supplier != null) ? supplier.get() : null;
}

4
core/spring-boot/src/main/java/org/springframework/boot/ClearCachesApplicationListener.java

@ -18,6 +18,8 @@ package org.springframework.boot; @@ -18,6 +18,8 @@ package org.springframework.boot;
import java.lang.reflect.Method;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.util.ReflectionUtils;
@ -35,7 +37,7 @@ class ClearCachesApplicationListener implements ApplicationListener<ContextRefre @@ -35,7 +37,7 @@ class ClearCachesApplicationListener implements ApplicationListener<ContextRefre
clearClassLoaderCaches(Thread.currentThread().getContextClassLoader());
}
private void clearClassLoaderCaches(ClassLoader classLoader) {
private void clearClassLoaderCaches(@Nullable ClassLoader classLoader) {
if (classLoader == null) {
return;
}

6
core/spring-boot/src/main/java/org/springframework/boot/DefaultApplicationArguments.java

@ -22,6 +22,8 @@ import java.util.HashSet; @@ -22,6 +22,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.core.env.SimpleCommandLinePropertySource;
import org.springframework.util.Assert;
@ -60,7 +62,7 @@ public class DefaultApplicationArguments implements ApplicationArguments { @@ -60,7 +62,7 @@ public class DefaultApplicationArguments implements ApplicationArguments {
}
@Override
public List<String> getOptionValues(String name) {
public @Nullable List<String> getOptionValues(String name) {
List<String> values = this.source.getOptionValues(name);
return (values != null) ? Collections.unmodifiableList(values) : null;
}
@ -82,7 +84,7 @@ public class DefaultApplicationArguments implements ApplicationArguments { @@ -82,7 +84,7 @@ public class DefaultApplicationArguments implements ApplicationArguments {
}
@Override
public List<String> getOptionValues(String name) {
public @Nullable List<String> getOptionValues(String name) {
return super.getOptionValues(name);
}

22
core/spring-boot/src/main/java/org/springframework/boot/DefaultApplicationContextFactory.java

@ -19,12 +19,15 @@ package org.springframework.boot; @@ -19,12 +19,15 @@ package org.springframework.boot;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.AotDetector;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.lang.Contract;
/**
* Default {@link ApplicationContextFactory} implementation that will create an
@ -34,18 +37,25 @@ import org.springframework.core.io.support.SpringFactoriesLoader; @@ -34,18 +37,25 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
*/
class DefaultApplicationContextFactory implements ApplicationContextFactory {
// Method reference is not detected with correct nullability
@SuppressWarnings("NullAway")
@Override
public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
public @Nullable Class<? extends ConfigurableEnvironment> getEnvironmentType(
@Nullable WebApplicationType webApplicationType) {
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::getEnvironmentType, null);
}
// Method reference is not detected with correct nullability
@SuppressWarnings("NullAway")
@Override
public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
public @Nullable ConfigurableEnvironment createEnvironment(@Nullable WebApplicationType webApplicationType) {
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::createEnvironment, null);
}
// Method reference is not detected with correct nullability
@SuppressWarnings("NullAway")
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
public ConfigurableApplicationContext create(@Nullable WebApplicationType webApplicationType) {
try {
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,
this::createDefaultApplicationContext);
@ -63,8 +73,10 @@ class DefaultApplicationContextFactory implements ApplicationContextFactory { @@ -63,8 +73,10 @@ class DefaultApplicationContextFactory implements ApplicationContextFactory {
return new GenericApplicationContext();
}
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
@Contract("_, _, !null -> !null")
private <T> @Nullable T getFromSpringFactories(@Nullable WebApplicationType webApplicationType,
BiFunction<ApplicationContextFactory, @Nullable WebApplicationType, @Nullable T> action,
@Nullable Supplier<T> defaultResult) {
for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
getClass().getClassLoader())) {
T result = action.apply(candidate, webApplicationType);

19
core/spring-boot/src/main/java/org/springframework/boot/DefaultBootstrapContext.java

@ -20,6 +20,8 @@ import java.util.HashMap; @@ -20,6 +20,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
@ -72,7 +74,7 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext { @@ -72,7 +74,7 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
@Override
@SuppressWarnings("unchecked")
public <T> InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type) {
public <T> @Nullable InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type) {
synchronized (this.instanceSuppliers) {
return (InstanceSupplier<T>) this.instanceSuppliers.get(type);
}
@ -84,17 +86,18 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext { @@ -84,17 +86,18 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
}
@Override
public <T> T get(Class<T> type) throws IllegalStateException {
public <T> @Nullable T get(Class<T> type) throws IllegalStateException {
return getOrElseThrow(type, () -> new IllegalStateException(type.getName() + " has not been registered"));
}
@Override
public <T> T getOrElse(Class<T> type, T other) {
@SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability
public <T> @Nullable T getOrElse(Class<T> type, @Nullable T other) {
return getOrElseSupply(type, () -> other);
}
@Override
public <T> T getOrElseSupply(Class<T> type, Supplier<T> other) {
public <T> @Nullable T getOrElseSupply(Class<T> type, Supplier<@Nullable T> other) {
synchronized (this.instanceSuppliers) {
InstanceSupplier<?> instanceSupplier = this.instanceSuppliers.get(type);
return (instanceSupplier != null) ? getInstance(type, instanceSupplier) : other.get();
@ -102,7 +105,8 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext { @@ -102,7 +105,8 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
}
@Override
public <T, X extends Throwable> T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier) throws X {
public <T, X extends Throwable> @Nullable T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier)
throws X {
synchronized (this.instanceSuppliers) {
InstanceSupplier<?> instanceSupplier = this.instanceSuppliers.get(type);
if (instanceSupplier == null) {
@ -113,10 +117,13 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext { @@ -113,10 +117,13 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
}
@SuppressWarnings("unchecked")
private <T> T getInstance(Class<T> type, InstanceSupplier<?> instanceSupplier) {
private <T> @Nullable T getInstance(Class<T> type, InstanceSupplier<?> instanceSupplier) {
T instance = (T) this.instances.get(type);
if (instance == null) {
instance = (T) instanceSupplier.get(this);
if (instance == null) {
return null;
}
if (instanceSupplier.getScope() == Scope.SINGLETON) {
this.instances.put(type, instance);
}

7
core/spring-boot/src/main/java/org/springframework/boot/DefaultPropertiesPropertySource.java

@ -20,6 +20,8 @@ import java.util.HashMap; @@ -20,6 +20,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
@ -56,7 +58,7 @@ public class DefaultPropertiesPropertySource extends MapPropertySource { @@ -56,7 +58,7 @@ public class DefaultPropertiesPropertySource extends MapPropertySource {
* @param propertySource the property source to check
* @return {@code true} if the name matches
*/
public static boolean hasMatchingName(PropertySource<?> propertySource) {
public static boolean hasMatchingName(@Nullable PropertySource<?> propertySource) {
return (propertySource != null) && propertySource.getName().equals(NAME);
}
@ -67,7 +69,8 @@ public class DefaultPropertiesPropertySource extends MapPropertySource { @@ -67,7 +69,8 @@ public class DefaultPropertiesPropertySource extends MapPropertySource {
* @param action the action used to consume the
* {@link DefaultPropertiesPropertySource}
*/
public static void ifNotEmpty(Map<String, Object> source, Consumer<DefaultPropertiesPropertySource> action) {
public static void ifNotEmpty(Map<String, Object> source,
@Nullable Consumer<DefaultPropertiesPropertySource> action) {
if (!CollectionUtils.isEmpty(source) && action != null) {
action.accept(new DefaultPropertiesPropertySource(source));
}

6
core/spring-boot/src/main/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessor.java

@ -19,6 +19,8 @@ package org.springframework.boot; @@ -19,6 +19,8 @@ package org.springframework.boot;
import java.util.ArrayList;
import java.util.Collection;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.SmartInitializingSingleton;
@ -84,7 +86,7 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac @@ -84,7 +86,7 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac
}
}
private Class<?> getBeanType(ConfigurableListableBeanFactory beanFactory, String beanName) {
private @Nullable Class<?> getBeanType(ConfigurableListableBeanFactory beanFactory, String beanName) {
try {
return beanFactory.getType(beanName, false);
}
@ -94,7 +96,7 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac @@ -94,7 +96,7 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac
}
private boolean isExcluded(Collection<LazyInitializationExcludeFilter> filters, String beanName,
AbstractBeanDefinition beanDefinition, Class<?> beanType) {
AbstractBeanDefinition beanDefinition, @Nullable Class<?> beanType) {
if (beanType != null) {
for (LazyInitializationExcludeFilter filter : filters) {
if (filter.isExcluded(beanName, beanDefinition, beanType)) {

27
core/spring-boot/src/main/java/org/springframework/boot/ResourceBanner.java

@ -28,6 +28,7 @@ import java.util.Map; @@ -28,6 +28,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ansi.AnsiPropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
@ -64,7 +65,7 @@ public class ResourceBanner implements Banner { @@ -64,7 +65,7 @@ public class ResourceBanner implements Banner {
}
@Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
public void printBanner(Environment environment, @Nullable Class<?> sourceClass, PrintStream out) {
try (InputStream input = this.resource.getInputStream()) {
String banner = StreamUtils.copyToString(input,
environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));
@ -86,32 +87,32 @@ public class ResourceBanner implements Banner { @@ -86,32 +87,32 @@ public class ResourceBanner implements Banner {
* @param sourceClass the source class
* @return a mutable list of property resolvers
*/
protected List<PropertyResolver> getPropertyResolvers(Environment environment, Class<?> sourceClass) {
protected List<PropertyResolver> getPropertyResolvers(Environment environment, @Nullable Class<?> sourceClass) {
List<PropertyResolver> resolvers = new ArrayList<>();
resolvers.add(new PropertySourcesPropertyResolver(createNullDefaultSources(environment, sourceClass)));
resolvers.add(new PropertySourcesPropertyResolver(createEmptyDefaultSources(environment, sourceClass)));
return resolvers;
}
private MutablePropertySources createNullDefaultSources(Environment environment, Class<?> sourceClass) {
private MutablePropertySources createNullDefaultSources(Environment environment, @Nullable Class<?> sourceClass) {
MutablePropertySources nullDefaultSources = new MutablePropertySources();
if (environment instanceof ConfigurableEnvironment configurableEnvironment) {
configurableEnvironment.getPropertySources().forEach(nullDefaultSources::addLast);
}
nullDefaultSources.addLast(getTitleSource(sourceClass, null));
nullDefaultSources.addLast(getAnsiSource());
nullDefaultSources.addLast(getVersionSource(sourceClass, environment, null));
nullDefaultSources.addLast(getVersionSource(environment, null));
return nullDefaultSources;
}
private MutablePropertySources createEmptyDefaultSources(Environment environment, Class<?> sourceClass) {
private MutablePropertySources createEmptyDefaultSources(Environment environment, @Nullable Class<?> sourceClass) {
MutablePropertySources emptyDefaultSources = new MutablePropertySources();
emptyDefaultSources.addLast(getTitleSource(sourceClass, ""));
emptyDefaultSources.addLast(getVersionSource(sourceClass, environment, ""));
emptyDefaultSources.addLast(getVersionSource(environment, ""));
return emptyDefaultSources;
}
private MapPropertySource getTitleSource(Class<?> sourceClass, String defaultValue) {
private MapPropertySource getTitleSource(@Nullable Class<?> sourceClass, @Nullable String defaultValue) {
String applicationTitle = getApplicationTitle(sourceClass);
Map<String, Object> titleMap = Collections.singletonMap("application.title",
(applicationTitle != null) ? applicationTitle : defaultValue);
@ -124,7 +125,7 @@ public class ResourceBanner implements Banner { @@ -124,7 +125,7 @@ public class ResourceBanner implements Banner {
* @param sourceClass the source class
* @return the application title
*/
protected String getApplicationTitle(Class<?> sourceClass) {
protected @Nullable String getApplicationTitle(@Nullable Class<?> sourceClass) {
Package sourcePackage = (sourceClass != null) ? sourceClass.getPackage() : null;
return (sourcePackage != null) ? sourcePackage.getImplementationTitle() : null;
}
@ -133,11 +134,11 @@ public class ResourceBanner implements Banner { @@ -133,11 +134,11 @@ public class ResourceBanner implements Banner {
return new AnsiPropertySource("ansi", true);
}
private MapPropertySource getVersionSource(Class<?> sourceClass, Environment environment, String defaultValue) {
return new MapPropertySource("version", getVersionsMap(sourceClass, environment, defaultValue));
private MapPropertySource getVersionSource(Environment environment, @Nullable String defaultValue) {
return new MapPropertySource("version", getVersionsMap(environment, defaultValue));
}
private Map<String, Object> getVersionsMap(Class<?> sourceClass, Environment environment, String defaultValue) {
private Map<String, Object> getVersionsMap(Environment environment, @Nullable String defaultValue) {
String appVersion = getApplicationVersion(environment);
String bootVersion = getBootVersion();
Map<String, Object> versions = new HashMap<>();
@ -148,7 +149,7 @@ public class ResourceBanner implements Banner { @@ -148,7 +149,7 @@ public class ResourceBanner implements Banner {
return versions;
}
private String getApplicationVersion(Environment environment) {
private @Nullable String getApplicationVersion(Environment environment) {
return environment.getProperty("spring.application.version");
}
@ -156,7 +157,7 @@ public class ResourceBanner implements Banner { @@ -156,7 +157,7 @@ public class ResourceBanner implements Banner {
return SpringBootVersion.getVersion();
}
private String getVersionString(String version, boolean format, String fallback) {
private @Nullable String getVersionString(@Nullable String version, boolean format, @Nullable String fallback) {
if (version == null) {
return fallback;
}

108
core/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java

@ -41,6 +41,7 @@ import java.util.stream.Stream; @@ -41,6 +41,7 @@ import java.util.stream.Stream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.crac.management.CRaCMXBean;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.AotDetector;
import org.springframework.beans.BeansException;
@ -204,27 +205,27 @@ public class SpringApplication { @@ -204,27 +205,27 @@ public class SpringApplication {
private final Set<Class<?>> primarySources;
private Class<?> mainApplicationClass;
private @Nullable Class<?> mainApplicationClass;
private boolean addCommandLineProperties = true;
private boolean addConversionService = true;
private Banner banner;
private @Nullable Banner banner;
private ResourceLoader resourceLoader;
private @Nullable ResourceLoader resourceLoader;
private BeanNameGenerator beanNameGenerator;
private @Nullable BeanNameGenerator beanNameGenerator;
private ConfigurableEnvironment environment;
private @Nullable ConfigurableEnvironment environment;
private boolean headless = true;
private List<ApplicationContextInitializer<?>> initializers;
private List<ApplicationContextInitializer<?>> initializers = new ArrayList<>();
private List<ApplicationListener<?>> listeners;
private List<ApplicationListener<?>> listeners = new ArrayList<>();
private Map<String, Object> defaultProperties;
private @Nullable Map<String, Object> defaultProperties;
private final List<BootstrapRegistryInitializer> bootstrapRegistryInitializers;
@ -232,7 +233,7 @@ public class SpringApplication { @@ -232,7 +233,7 @@ public class SpringApplication {
private boolean isCustomEnvironment;
private String environmentPrefix;
private @Nullable String environmentPrefix;
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
@ -265,7 +266,7 @@ public class SpringApplication { @@ -265,7 +266,7 @@ public class SpringApplication {
* @see #setSources(Set)
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
public SpringApplication(@Nullable ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "'primarySources' must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
@ -277,7 +278,7 @@ public class SpringApplication { @@ -277,7 +278,7 @@ public class SpringApplication {
this.mainApplicationClass = deduceMainApplicationClass();
}
private Class<?> deduceMainApplicationClass() {
private @Nullable Class<?> deduceMainApplicationClass() {
return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk(this::findMainClass)
.orElse(null);
@ -314,11 +315,11 @@ public class SpringApplication { @@ -314,11 +315,11 @@ public class SpringApplication {
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
startup.started();
Duration timeTakenToStarted = startup.started();
if (this.properties.isLogStartupInfo()) {
new StartupInfoLogger(this.mainApplicationClass, environment).logStarted(getApplicationLog(), startup);
}
listeners.started(context, startup.timeTakenToStarted());
listeners.started(context, timeTakenToStarted);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
@ -373,7 +374,7 @@ public class SpringApplication { @@ -373,7 +374,7 @@ public class SpringApplication {
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
ApplicationArguments applicationArguments, @Nullable Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
addAotGeneratedInitializerIfNecessary(this.initializers);
@ -417,6 +418,7 @@ public class SpringApplication { @@ -417,6 +418,7 @@ public class SpringApplication {
List<ApplicationContextInitializer<?>> aotInitializers = new ArrayList<>(
initializers.stream().filter(AotApplicationContextInitializer.class::isInstance).toList());
if (aotInitializers.isEmpty()) {
Assert.state(this.mainApplicationClass != null, "No application main class found");
String initializerClassName = this.mainApplicationClass.getName() + "__ApplicationContextInitializer";
if (!ClassUtils.isPresent(initializerClassName, getClassLoader())) {
throw new AotInitializerNotFoundException(this.mainApplicationClass, initializerClassName);
@ -458,7 +460,7 @@ public class SpringApplication { @@ -458,7 +460,7 @@ public class SpringApplication {
return getSpringFactoriesInstances(type, null);
}
private <T> List<T> getSpringFactoriesInstances(Class<T> type, ArgumentResolver argumentResolver) {
private <T> List<T> getSpringFactoriesInstances(Class<T> type, @Nullable ArgumentResolver argumentResolver) {
return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
}
@ -507,8 +509,8 @@ public class SpringApplication { @@ -507,8 +509,8 @@ public class SpringApplication {
}
if (this.addCommandLineProperties && args.length > 0) {
String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
if (sources.contains(name)) {
PropertySource<?> source = sources.get(name);
PropertySource<?> source = sources.get(name);
if (source != null) {
CompositePropertySource composite = new CompositePropertySource(name);
composite
.addPropertySource(new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
@ -546,7 +548,7 @@ public class SpringApplication { @@ -546,7 +548,7 @@ public class SpringApplication {
}
}
private Banner printBanner(ConfigurableEnvironment environment) {
private @Nullable Banner printBanner(ConfigurableEnvironment environment) {
if (this.properties.getBannerMode(environment) == Banner.Mode.OFF) {
return null;
}
@ -604,6 +606,8 @@ public class SpringApplication { @@ -604,6 +606,8 @@ public class SpringApplication {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.state(requiredType != null,
() -> "No generic type found for initializr of type " + initializer.getClass());
Assert.state(requiredType.isInstance(context), "Unable to call initializer");
initializer.initialize(context);
}
@ -685,9 +689,9 @@ public class SpringApplication { @@ -685,9 +689,9 @@ public class SpringApplication {
/**
* The ResourceLoader that will be used in the ApplicationContext.
* @return the resourceLoader the resource loader that will be used in the
* ApplicationContext (or null if the default)
* ApplicationContext (or {@code null} if the default)
*/
public ResourceLoader getResourceLoader() {
public @Nullable ResourceLoader getResourceLoader() {
return this.resourceLoader;
}
@ -699,9 +703,13 @@ public class SpringApplication { @@ -699,9 +703,13 @@ public class SpringApplication {
*/
public ClassLoader getClassLoader() {
if (this.resourceLoader != null) {
return this.resourceLoader.getClassLoader();
ClassLoader classLoader = this.resourceLoader.getClassLoader();
Assert.state(classLoader != null, "No classloader found");
return classLoader;
}
return ClassUtils.getDefaultClassLoader();
ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
Assert.state(classLoader != null, "No classloader found");
return classLoader;
}
/**
@ -781,8 +789,8 @@ public class SpringApplication { @@ -781,8 +789,8 @@ public class SpringApplication {
.accept((R) runner);
}
private RuntimeException handleRunFailure(ConfigurableApplicationContext context, Throwable exception,
SpringApplicationRunListeners listeners) {
private RuntimeException handleRunFailure(@Nullable ConfigurableApplicationContext context, Throwable exception,
@Nullable SpringApplicationRunListeners listeners) {
if (exception instanceof AbandonedRunException abandonedRunException) {
return abandonedRunException;
}
@ -808,9 +816,11 @@ public class SpringApplication { @@ -808,9 +816,11 @@ public class SpringApplication {
: new IllegalStateException(exception);
}
private Collection<SpringBootExceptionReporter> getExceptionReporters(ConfigurableApplicationContext context) {
private Collection<SpringBootExceptionReporter> getExceptionReporters(
@Nullable ConfigurableApplicationContext context) {
try {
ArgumentResolver argumentResolver = ArgumentResolver.of(ConfigurableApplicationContext.class, context);
ArgumentResolver argumentResolver = (context != null)
? ArgumentResolver.of(ConfigurableApplicationContext.class, context) : ArgumentResolver.none();
return getSpringFactoriesInstances(SpringBootExceptionReporter.class, argumentResolver);
}
catch (Throwable ex) {
@ -857,7 +867,7 @@ public class SpringApplication { @@ -857,7 +867,7 @@ public class SpringApplication {
}
}
private void handleExitCode(ConfigurableApplicationContext context, Throwable exception) {
private void handleExitCode(@Nullable ConfigurableApplicationContext context, Throwable exception) {
int exitCode = getExitCodeFromException(context, exception);
if (exitCode != 0) {
if (context != null) {
@ -870,7 +880,7 @@ public class SpringApplication { @@ -870,7 +880,7 @@ public class SpringApplication {
}
}
private int getExitCodeFromException(ConfigurableApplicationContext context, Throwable exception) {
private int getExitCodeFromException(@Nullable ConfigurableApplicationContext context, Throwable exception) {
int exitCode = getExitCodeFromMappedException(context, exception);
if (exitCode == 0) {
exitCode = getExitCodeFromExitCodeGeneratorException(exception);
@ -878,7 +888,7 @@ public class SpringApplication { @@ -878,7 +888,7 @@ public class SpringApplication {
return exitCode;
}
private int getExitCodeFromMappedException(ConfigurableApplicationContext context, Throwable exception) {
private int getExitCodeFromMappedException(@Nullable ConfigurableApplicationContext context, Throwable exception) {
if (context == null || !context.isActive()) {
return 0;
}
@ -888,7 +898,7 @@ public class SpringApplication { @@ -888,7 +898,7 @@ public class SpringApplication {
return generators.getExitCode();
}
private int getExitCodeFromExitCodeGeneratorException(Throwable exception) {
private int getExitCodeFromExitCodeGeneratorException(@Nullable Throwable exception) {
if (exception == null) {
return 0;
}
@ -898,7 +908,7 @@ public class SpringApplication { @@ -898,7 +908,7 @@ public class SpringApplication {
return getExitCodeFromExitCodeGeneratorException(exception.getCause());
}
SpringBootExceptionHandler getSpringBootExceptionHandler() {
@Nullable SpringBootExceptionHandler getSpringBootExceptionHandler() {
if (isMainThread(Thread.currentThread())) {
return SpringBootExceptionHandler.forCurrentThread();
}
@ -914,7 +924,7 @@ public class SpringApplication { @@ -914,7 +924,7 @@ public class SpringApplication {
* Returns the main application class that has been deduced or explicitly configured.
* @return the main application class or {@code null}
*/
public Class<?> getMainApplicationClass() {
public @Nullable Class<?> getMainApplicationClass() {
return this.mainApplicationClass;
}
@ -924,7 +934,7 @@ public class SpringApplication { @@ -924,7 +934,7 @@ public class SpringApplication {
* Can be set to {@code null} if there is no explicit application class.
* @param mainApplicationClass the mainApplicationClass to set or {@code null}
*/
public void setMainApplicationClass(Class<?> mainApplicationClass) {
public void setMainApplicationClass(@Nullable Class<?> mainApplicationClass) {
this.mainApplicationClass = mainApplicationClass;
}
@ -933,7 +943,7 @@ public class SpringApplication { @@ -933,7 +943,7 @@ public class SpringApplication {
* @return the type of web application
* @since 2.0.0
*/
public WebApplicationType getWebApplicationType() {
public @Nullable WebApplicationType getWebApplicationType() {
return this.properties.getWebApplicationType();
}
@ -1107,7 +1117,7 @@ public class SpringApplication { @@ -1107,7 +1117,7 @@ public class SpringApplication {
* context.
* @param environment the environment
*/
public void setEnvironment(ConfigurableEnvironment environment) {
public void setEnvironment(@Nullable ConfigurableEnvironment environment) {
this.isCustomEnvironment = true;
this.environment = environment;
}
@ -1191,7 +1201,7 @@ public class SpringApplication { @@ -1191,7 +1201,7 @@ public class SpringApplication {
* @return the environment property prefix
* @since 2.5.0
*/
public String getEnvironmentPrefix() {
public @Nullable String getEnvironmentPrefix() {
return this.environmentPrefix;
}
@ -1213,7 +1223,7 @@ public class SpringApplication { @@ -1213,7 +1223,7 @@ public class SpringApplication {
* @param applicationContextFactory the factory for the context
* @since 2.4.0
*/
public void setApplicationContextFactory(ApplicationContextFactory applicationContextFactory) {
public void setApplicationContextFactory(@Nullable ApplicationContextFactory applicationContextFactory) {
this.applicationContextFactory = (applicationContextFactory != null) ? applicationContextFactory
: ApplicationContextFactory.DEFAULT;
}
@ -1424,7 +1434,7 @@ public class SpringApplication { @@ -1424,7 +1434,7 @@ public class SpringApplication {
public static void withHook(SpringApplicationHook hook, Runnable action) {
withHook(hook, () -> {
action.run();
return null;
return Void.class;
});
}
@ -1598,7 +1608,7 @@ public class SpringApplication { @@ -1598,7 +1608,7 @@ public class SpringApplication {
*/
public static class AbandonedRunException extends RuntimeException {
private final ConfigurableApplicationContext applicationContext;
private final @Nullable ConfigurableApplicationContext applicationContext;
/**
* Create a new {@link AbandonedRunException} instance.
@ -1613,7 +1623,7 @@ public class SpringApplication { @@ -1613,7 +1623,7 @@ public class SpringApplication {
* @param applicationContext the application context that was available when the
* run was abandoned
*/
public AbandonedRunException(ConfigurableApplicationContext applicationContext) {
public AbandonedRunException(@Nullable ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@ -1622,7 +1632,7 @@ public class SpringApplication { @@ -1622,7 +1632,7 @@ public class SpringApplication {
* {@code null} if no context was available.
* @return the application context
*/
public ConfigurableApplicationContext getApplicationContext() {
public @Nullable ConfigurableApplicationContext getApplicationContext() {
return this.applicationContext;
}
@ -1642,7 +1652,7 @@ public class SpringApplication { @@ -1642,7 +1652,7 @@ public class SpringApplication {
}
@Override
public SpringApplicationRunListener getRunListener(SpringApplication springApplication) {
public @Nullable SpringApplicationRunListener getRunListener(SpringApplication springApplication) {
return this.used.compareAndSet(false, true) ? this.delegate.getRunListener(springApplication) : null;
}
@ -1699,11 +1709,11 @@ public class SpringApplication { @@ -1699,11 +1709,11 @@ public class SpringApplication {
*/
abstract static class Startup {
private Duration timeTakenToStarted;
private @Nullable Duration timeTakenToStarted;
protected abstract long startTime();
protected abstract Long processUptime();
protected abstract @Nullable Long processUptime();
protected abstract String action();
@ -1714,6 +1724,8 @@ public class SpringApplication { @@ -1714,6 +1724,8 @@ public class SpringApplication {
}
Duration timeTakenToStarted() {
Assert.state(this.timeTakenToStarted != null,
"timeTakenToStarted is not set. Make sure to call started() before this method");
return this.timeTakenToStarted;
}
@ -1744,7 +1756,7 @@ public class SpringApplication { @@ -1744,7 +1756,7 @@ public class SpringApplication {
}
@Override
protected Long processUptime() {
protected @Nullable Long processUptime() {
try {
return ManagementFactory.getRuntimeMXBean().getUptime();
}
@ -1794,7 +1806,7 @@ public class SpringApplication { @@ -1794,7 +1806,7 @@ public class SpringApplication {
* {@link OrderSourceProvider} used to obtain factory method and target type order
* sources. Based on internal {@link DefaultListableBeanFactory} code.
*/
private class FactoryAwareOrderSourceProvider implements OrderSourceProvider {
private static class FactoryAwareOrderSourceProvider implements OrderSourceProvider {
private final ConfigurableBeanFactory beanFactory;
@ -1806,12 +1818,12 @@ public class SpringApplication { @@ -1806,12 +1818,12 @@ public class SpringApplication {
}
@Override
public Object getOrderSource(Object obj) {
public @Nullable Object getOrderSource(Object obj) {
String beanName = this.instancesToBeanNames.get(obj);
return (beanName != null) ? getOrderSource(beanName, obj.getClass()) : null;
}
private Object getOrderSource(String beanName, Class<?> instanceType) {
private @Nullable Object getOrderSource(String beanName, Class<?> instanceType) {
try {
RootBeanDefinition beanDefinition = (RootBeanDefinition) this.beanFactory
.getMergedBeanDefinition(beanName);

5
core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationAotProcessor.java

@ -59,7 +59,8 @@ public class SpringApplicationAotProcessor extends ContextAotProcessor { @@ -59,7 +59,8 @@ public class SpringApplicationAotProcessor extends ContextAotProcessor {
protected GenericApplicationContext prepareApplicationContext(Class<?> application) {
return new AotProcessorHook(application).run(() -> {
Method mainMethod = application.getMethod("main", String[].class);
return ReflectionUtils.invokeMethod(mainMethod, null, new Object[] { this.applicationArgs });
ReflectionUtils.invokeMethod(mainMethod, null, new Object[] { this.applicationArgs });
return Void.class;
});
}
@ -112,7 +113,7 @@ public class SpringApplicationAotProcessor extends ContextAotProcessor { @@ -112,7 +113,7 @@ public class SpringApplicationAotProcessor extends ContextAotProcessor {
ApplicationContext context = ex.getApplicationContext();
Assert.state(context instanceof GenericApplicationContext,
() -> "AOT processing requires a GenericApplicationContext but got a "
+ context.getClass().getName());
+ ((context != null) ? context.getClass().getName() : "null"));
return (GenericApplicationContext) context;
}
throw new IllegalStateException(

23
core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java

@ -23,6 +23,7 @@ import java.io.UnsupportedEncodingException; @@ -23,6 +23,7 @@ import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@ -45,14 +46,14 @@ class SpringApplicationBannerPrinter { @@ -45,14 +46,14 @@ class SpringApplicationBannerPrinter {
private final ResourceLoader resourceLoader;
private final Banner fallbackBanner;
private final @Nullable Banner fallbackBanner;
SpringApplicationBannerPrinter(ResourceLoader resourceLoader, Banner fallbackBanner) {
SpringApplicationBannerPrinter(ResourceLoader resourceLoader, @Nullable Banner fallbackBanner) {
this.resourceLoader = resourceLoader;
this.fallbackBanner = fallbackBanner;
}
Banner print(Environment environment, Class<?> sourceClass, Log logger) {
Banner print(Environment environment, @Nullable Class<?> sourceClass, Log logger) {
Banner banner = getBanner(environment);
try {
logger.info(createStringFromBanner(banner, environment, sourceClass));
@ -63,7 +64,7 @@ class SpringApplicationBannerPrinter { @@ -63,7 +64,7 @@ class SpringApplicationBannerPrinter {
return new PrintedBanner(banner, sourceClass);
}
Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
Banner print(Environment environment, @Nullable Class<?> sourceClass, PrintStream out) {
Banner banner = getBanner(environment);
banner.printBanner(environment, sourceClass, out);
return new PrintedBanner(banner, sourceClass);
@ -80,7 +81,7 @@ class SpringApplicationBannerPrinter { @@ -80,7 +81,7 @@ class SpringApplicationBannerPrinter {
return DEFAULT_BANNER;
}
private Banner getTextBanner(Environment environment) {
private @Nullable Banner getTextBanner(Environment environment) {
String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION);
Resource resource = this.resourceLoader.getResource(location);
try {
@ -94,8 +95,8 @@ class SpringApplicationBannerPrinter { @@ -94,8 +95,8 @@ class SpringApplicationBannerPrinter {
return null;
}
private String createStringFromBanner(Banner banner, Environment environment, Class<?> mainApplicationClass)
throws UnsupportedEncodingException {
private String createStringFromBanner(Banner banner, Environment environment,
@Nullable Class<?> mainApplicationClass) throws UnsupportedEncodingException {
String charset = environment.getProperty("spring.banner.charset", StandardCharsets.UTF_8.name());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (PrintStream out = new PrintStream(byteArrayOutputStream, false, charset)) {
@ -112,15 +113,15 @@ class SpringApplicationBannerPrinter { @@ -112,15 +113,15 @@ class SpringApplicationBannerPrinter {
private final Banner banner;
private final Class<?> sourceClass;
private final @Nullable Class<?> sourceClass;
PrintedBanner(Banner banner, Class<?> sourceClass) {
PrintedBanner(Banner banner, @Nullable Class<?> sourceClass) {
this.banner = banner;
this.sourceClass = sourceClass;
}
@Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
public void printBanner(Environment environment, @Nullable Class<?> sourceClass, PrintStream out) {
sourceClass = (sourceClass != null) ? sourceClass : this.sourceClass;
this.banner.printBanner(environment, sourceClass, out);
}
@ -130,7 +131,7 @@ class SpringApplicationBannerPrinter { @@ -130,7 +131,7 @@ class SpringApplicationBannerPrinter {
static class SpringApplicationBannerPrinterRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
hints.resources().registerPattern(DEFAULT_BANNER_LOCATION);
}

6
core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationHook.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot;
import org.jspecify.annotations.Nullable;
/**
* Low-level hook that can be used to attach a {@link SpringApplicationRunListener} to a
* {@link SpringApplication} in order to observe or modify its behavior. Hooks are managed
@ -34,8 +36,8 @@ public interface SpringApplicationHook { @@ -34,8 +36,8 @@ public interface SpringApplicationHook {
* Return the {@link SpringApplicationRunListener} that should be hooked into the
* given {@link SpringApplication}.
* @param springApplication the source {@link SpringApplication} instance
* @return the {@link SpringApplicationRunListener} to attach
* @return the {@link SpringApplicationRunListener} to attach or {@code null}
*/
SpringApplicationRunListener getRunListener(SpringApplication springApplication);
@Nullable SpringApplicationRunListener getRunListener(SpringApplication springApplication);
}

8
core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationRunListener.java

@ -18,6 +18,8 @@ package org.springframework.boot; @@ -18,6 +18,8 @@ package org.springframework.boot;
import java.time.Duration;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
@ -80,7 +82,7 @@ public interface SpringApplicationRunListener { @@ -80,7 +82,7 @@ public interface SpringApplicationRunListener {
* @param timeTaken the time taken to start the application or {@code null} if unknown
* @since 2.6.0
*/
default void started(ConfigurableApplicationContext context, Duration timeTaken) {
default void started(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
}
/**
@ -92,7 +94,7 @@ public interface SpringApplicationRunListener { @@ -92,7 +94,7 @@ public interface SpringApplicationRunListener {
* unknown
* @since 2.6.0
*/
default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
default void ready(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
}
/**
@ -102,7 +104,7 @@ public interface SpringApplicationRunListener { @@ -102,7 +104,7 @@ public interface SpringApplicationRunListener {
* @param exception the failure
* @since 2.0.0
*/
default void failed(ConfigurableApplicationContext context, Throwable exception) {
default void failed(@Nullable ConfigurableApplicationContext context, Throwable exception) {
}
}

16
core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationRunListeners.java

@ -21,6 +21,7 @@ import java.util.List; @@ -21,6 +21,7 @@ import java.util.List;
import java.util.function.Consumer;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
@ -50,7 +51,7 @@ class SpringApplicationRunListeners { @@ -50,7 +51,7 @@ class SpringApplicationRunListeners {
this.applicationStartup = applicationStartup;
}
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
void starting(ConfigurableBootstrapContext bootstrapContext, @Nullable Class<?> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
@ -80,16 +81,19 @@ class SpringApplicationRunListeners { @@ -80,16 +81,19 @@ class SpringApplicationRunListeners {
doWithListeners("spring.boot.application.ready", (listener) -> listener.ready(context, timeTaken));
}
void failed(ConfigurableApplicationContext context, Throwable exception) {
void failed(@Nullable ConfigurableApplicationContext context, Throwable exception) {
doWithListeners("spring.boot.application.failed",
(listener) -> callFailedListener(listener, context, exception), (step) -> {
step.tag("exception", exception.getClass().toString());
step.tag("message", exception.getMessage());
String message = exception.getMessage();
if (message != null) {
step.tag("message", message);
}
});
}
private void callFailedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context,
Throwable exception) {
private void callFailedListener(SpringApplicationRunListener listener,
@Nullable ConfigurableApplicationContext context, Throwable exception) {
try {
listener.failed(context, exception);
}
@ -113,7 +117,7 @@ class SpringApplicationRunListeners { @@ -113,7 +117,7 @@ class SpringApplicationRunListeners {
}
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction,
Consumer<StartupStep> stepAction) {
@Nullable Consumer<StartupStep> stepAction) {
StartupStep step = this.applicationStartup.start(stepName);
this.listeners.forEach(listenerAction);
if (stepAction != null) {

4
core/spring-boot/src/main/java/org/springframework/boot/SpringBootBanner.java

@ -18,6 +18,8 @@ package org.springframework.boot; @@ -18,6 +18,8 @@ package org.springframework.boot;
import java.io.PrintStream;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ansi.AnsiColor;
import org.springframework.boot.ansi.AnsiOutput;
import org.springframework.boot.ansi.AnsiStyle;
@ -44,7 +46,7 @@ class SpringBootBanner implements Banner { @@ -44,7 +46,7 @@ class SpringBootBanner implements Banner {
private static final int STRAP_LINE_SIZE = 42;
@Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
public void printBanner(Environment environment, @Nullable Class<?> sourceClass, PrintStream printStream) {
printStream.println();
printStream.println(BANNER);
String version = String.format(" (v%s)", SpringBootVersion.getVersion());

16
core/spring-boot/src/main/java/org/springframework/boot/SpringBootExceptionHandler.java

@ -24,6 +24,8 @@ import java.util.HashSet; @@ -24,6 +24,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jspecify.annotations.Nullable;
/**
* {@link UncaughtExceptionHandler} to suppress handling already logged exceptions and
* dealing with system exit.
@ -42,13 +44,13 @@ class SpringBootExceptionHandler implements UncaughtExceptionHandler { @@ -42,13 +44,13 @@ class SpringBootExceptionHandler implements UncaughtExceptionHandler {
private static final LoggedExceptionHandlerThreadLocal handler = new LoggedExceptionHandlerThreadLocal();
private final UncaughtExceptionHandler parent;
private final @Nullable UncaughtExceptionHandler parent;
private final List<Throwable> loggedExceptions = new ArrayList<>();
private int exitCode = 0;
SpringBootExceptionHandler(UncaughtExceptionHandler parent) {
SpringBootExceptionHandler(@Nullable UncaughtExceptionHandler parent) {
this.parent = parent;
}
@ -85,7 +87,10 @@ class SpringBootExceptionHandler implements UncaughtExceptionHandler { @@ -85,7 +87,10 @@ class SpringBootExceptionHandler implements UncaughtExceptionHandler {
* @param ex the source exception
* @return {@code true} if the exception contains a log configuration message
*/
private boolean isLogConfigurationMessage(Throwable ex) {
private boolean isLogConfigurationMessage(@Nullable Throwable ex) {
if (ex == null) {
return false;
}
if (ex instanceof InvocationTargetException) {
return isLogConfigurationMessage(ex.getCause());
}
@ -100,7 +105,10 @@ class SpringBootExceptionHandler implements UncaughtExceptionHandler { @@ -100,7 +105,10 @@ class SpringBootExceptionHandler implements UncaughtExceptionHandler {
return false;
}
private boolean isRegistered(Throwable ex) {
private boolean isRegistered(@Nullable Throwable ex) {
if (ex == null) {
return false;
}
if (this.loggedExceptions.contains(ex)) {
return true;
}

7
core/spring-boot/src/main/java/org/springframework/boot/StartupInfoLogger.java

@ -19,6 +19,7 @@ package org.springframework.boot; @@ -19,6 +19,7 @@ package org.springframework.boot;
import java.util.concurrent.Callable;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.AotDetector;
import org.springframework.boot.SpringApplication.Startup;
@ -39,11 +40,11 @@ import org.springframework.util.StringUtils; @@ -39,11 +40,11 @@ import org.springframework.util.StringUtils;
*/
class StartupInfoLogger {
private final Class<?> sourceClass;
private final @Nullable Class<?> sourceClass;
private final Environment environment;
StartupInfoLogger(Class<?> sourceClass, Environment environment) {
StartupInfoLogger(@Nullable Class<?> sourceClass, Environment environment) {
this.sourceClass = sourceClass;
this.environment = environment;
}
@ -153,7 +154,7 @@ class StartupInfoLogger { @@ -153,7 +154,7 @@ class StartupInfoLogger {
}
}
private Object callIfPossible(Callable<Object> call) {
private @Nullable Object callIfPossible(Callable<Object> call) {
try {
return call.call();
}

6
core/spring-boot/src/main/java/org/springframework/boot/WebApplicationType.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
@ -73,7 +75,7 @@ public enum WebApplicationType { @@ -73,7 +75,7 @@ public enum WebApplicationType {
static class WebApplicationTypeRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
for (String servletIndicatorClass : SERVLET_INDICATOR_CLASSES) {
registerTypeIfPresent(servletIndicatorClass, classLoader, hints);
}
@ -82,7 +84,7 @@ public enum WebApplicationType { @@ -82,7 +84,7 @@ public enum WebApplicationType {
registerTypeIfPresent(WEBMVC_INDICATOR_CLASS, classLoader, hints);
}
private void registerTypeIfPresent(String typeName, ClassLoader classLoader, RuntimeHints hints) {
private void registerTypeIfPresent(String typeName, @Nullable ClassLoader classLoader, RuntimeHints hints) {
if (ClassUtils.isPresent(typeName, classLoader)) {
hints.reflection().registerType(TypeReference.of(typeName));
}

4
core/spring-boot/src/main/java/org/springframework/boot/admin/SpringApplicationAdminMXBean.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.admin;
import org.jspecify.annotations.Nullable;
/**
* An MBean contract to control and monitor a running {@code SpringApplication} over JMX.
* Intended for internal use only.
@ -47,7 +49,7 @@ public interface SpringApplicationAdminMXBean { @@ -47,7 +49,7 @@ public interface SpringApplicationAdminMXBean {
* @param key the property key
* @return the property value or {@code null} if it does not exist
*/
String getProperty(String key);
@Nullable String getProperty(String key);
/**
* Shutdown the application.

6
core/spring-boot/src/main/java/org/springframework/boot/admin/SpringApplicationAdminMXBeanRegistrar.java

@ -24,6 +24,7 @@ import javax.management.ObjectName; @@ -24,6 +24,7 @@ import javax.management.ObjectName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
@ -55,6 +56,7 @@ public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContext @@ -55,6 +56,7 @@ public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContext
private static final Log logger = LogFactory.getLog(SpringApplicationAdmin.class);
@SuppressWarnings("NullAway.Init")
private ConfigurableApplicationContext applicationContext;
private Environment environment = new StandardEnvironment();
@ -89,7 +91,7 @@ public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContext @@ -89,7 +91,7 @@ public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContext
}
@Override
public boolean supportsSourceType(Class<?> sourceType) {
public boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
@ -139,7 +141,7 @@ public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContext @@ -139,7 +141,7 @@ public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContext
}
@Override
public String getProperty(String key) {
public @Nullable String getProperty(String key) {
return SpringApplicationAdminMXBeanRegistrar.this.environment.getProperty(key);
}

3
core/spring-boot/src/main/java/org/springframework/boot/admin/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Administration support for Spring Boot applications.
*/
@NullMarked
package org.springframework.boot.admin;
import org.jspecify.annotations.NullMarked;

10
core/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java

@ -20,6 +20,8 @@ import java.io.Console; @@ -20,6 +20,8 @@ import java.io.Console;
import java.lang.reflect.Method;
import java.util.Locale;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -37,9 +39,9 @@ public abstract class AnsiOutput { @@ -37,9 +39,9 @@ public abstract class AnsiOutput {
private static Enabled enabled = Enabled.DETECT;
private static Boolean consoleAvailable;
private static @Nullable Boolean consoleAvailable;
private static Boolean ansiCapable;
private static @Nullable Boolean ansiCapable;
private static final String OPERATING_SYSTEM_NAME = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
@ -71,7 +73,7 @@ public abstract class AnsiOutput { @@ -71,7 +73,7 @@ public abstract class AnsiOutput {
* @param consoleAvailable if the console is known to be available or {@code null} to
* use standard detection logic.
*/
public static void setConsoleAvailable(Boolean consoleAvailable) {
public static void setConsoleAvailable(@Nullable Boolean consoleAvailable) {
AnsiOutput.consoleAvailable = consoleAvailable;
}
@ -133,7 +135,7 @@ public abstract class AnsiOutput { @@ -133,7 +135,7 @@ public abstract class AnsiOutput {
}
}
private static void buildDisabled(StringBuilder sb, Object[] elements) {
private static void buildDisabled(StringBuilder sb, @Nullable Object[] elements) {
for (Object element : elements) {
if (!(element instanceof AnsiElement) && element != null) {
sb.append(element);

10
core/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java

@ -23,6 +23,8 @@ import java.util.List; @@ -23,6 +23,8 @@ import java.util.List;
import java.util.Set;
import java.util.function.IntFunction;
import org.jspecify.annotations.Nullable;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;
@ -73,7 +75,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> { @@ -73,7 +75,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> {
}
@Override
public Object getProperty(String name) {
public @Nullable Object getProperty(String name) {
if (StringUtils.hasLength(name)) {
for (Mapping mapping : MAPPINGS) {
String prefix = mapping.getPrefix();
@ -104,7 +106,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> { @@ -104,7 +106,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> {
return this.prefix;
}
abstract AnsiElement getElement(String postfix);
abstract @Nullable AnsiElement getElement(String postfix);
}
@ -121,7 +123,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> { @@ -121,7 +123,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> {
}
@Override
AnsiElement getElement(String postfix) {
@Nullable AnsiElement getElement(String postfix) {
for (Enum<?> candidate : this.enums) {
if (candidate.name().equals(postfix)) {
return (AnsiElement) candidate;
@ -145,7 +147,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> { @@ -145,7 +147,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> {
}
@Override
AnsiElement getElement(String postfix) {
@Nullable AnsiElement getElement(String postfix) {
if (containsOnlyDigits(postfix)) {
try {
return this.factory.apply(Integer.parseInt(postfix));

3
core/spring-boot/src/main/java/org/springframework/boot/ansi/package-info.java

@ -19,4 +19,7 @@ @@ -19,4 +19,7 @@
*
* @see org.springframework.boot.ansi.AnsiOutput
*/
@NullMarked
package org.springframework.boot.ansi;
import org.jspecify.annotations.NullMarked;

6
core/spring-boot/src/main/java/org/springframework/boot/availability/ApplicationAvailability.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.availability;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
/**
@ -67,7 +69,7 @@ public interface ApplicationAvailability { @@ -67,7 +69,7 @@ public interface ApplicationAvailability {
* published yet
* @see #getState(Class, AvailabilityState)
*/
<S extends AvailabilityState> S getState(Class<S> stateType);
<S extends AvailabilityState> @Nullable S getState(Class<S> stateType);
/**
* Return the last {@link AvailabilityChangeEvent} received for a given state type.
@ -76,6 +78,6 @@ public interface ApplicationAvailability { @@ -76,6 +78,6 @@ public interface ApplicationAvailability {
* @return the readiness state or {@code null} if no event of the given type has been
* published yet
*/
<S extends AvailabilityState> AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType);
<S extends AvailabilityState> @Nullable AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType);
}

7
core/spring-boot/src/main/java/org/springframework/boot/availability/ApplicationAvailabilityBean.java

@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentHashMap; @@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
@ -59,14 +60,14 @@ public class ApplicationAvailabilityBean @@ -59,14 +60,14 @@ public class ApplicationAvailabilityBean
}
@Override
public <S extends AvailabilityState> S getState(Class<S> stateType) {
public <S extends AvailabilityState> @Nullable S getState(Class<S> stateType) {
AvailabilityChangeEvent<S> event = getLastChangeEvent(stateType);
return (event != null) ? event.getState() : null;
}
@Override
@SuppressWarnings("unchecked")
public <S extends AvailabilityState> AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType) {
public <S extends AvailabilityState> @Nullable AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType) {
return (AvailabilityChangeEvent<S>) this.events.get(stateType);
}
@ -89,7 +90,7 @@ public class ApplicationAvailabilityBean @@ -89,7 +90,7 @@ public class ApplicationAvailabilityBean
return message;
}
private String getSourceDescription(Object source) {
private String getSourceDescription(@Nullable Object source) {
if (source == null || source instanceof ApplicationEventPublisher) {
return "";
}

3
core/spring-boot/src/main/java/org/springframework/boot/availability/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Support for describing the availability of Spring Boot applications.
*/
@NullMarked
package org.springframework.boot.availability;
import org.jspecify.annotations.NullMarked;

3
core/spring-boot/src/main/java/org/springframework/boot/builder/ParentContextCloserApplicationListener.java

@ -40,8 +40,9 @@ import org.springframework.util.ObjectUtils; @@ -40,8 +40,9 @@ import org.springframework.util.ObjectUtils;
public class ParentContextCloserApplicationListener
implements ApplicationListener<ParentContextAvailableEvent>, ApplicationContextAware, Ordered {
private final int order = Ordered.LOWEST_PRECEDENCE - 10;
private static final int order = Ordered.LOWEST_PRECEDENCE - 10;
@SuppressWarnings("NullAway.Init")
private ApplicationContext context;
@Override

29
core/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java

@ -27,6 +27,8 @@ import java.util.Properties; @@ -27,6 +27,8 @@ import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.boot.ApplicationContextFactory;
@ -44,6 +46,7 @@ import org.springframework.core.env.ConfigurableEnvironment; @@ -44,6 +46,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.metrics.ApplicationStartup;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -76,9 +79,9 @@ public class SpringApplicationBuilder { @@ -76,9 +79,9 @@ public class SpringApplicationBuilder {
private final SpringApplication application;
private volatile ConfigurableApplicationContext context;
private volatile @Nullable ConfigurableApplicationContext context;
private SpringApplicationBuilder parent;
private @Nullable SpringApplicationBuilder parent;
private final AtomicBoolean running = new AtomicBoolean();
@ -86,7 +89,7 @@ public class SpringApplicationBuilder { @@ -86,7 +89,7 @@ public class SpringApplicationBuilder {
private final Map<String, Object> defaultProperties = new LinkedHashMap<>();
private ConfigurableEnvironment environment;
private @Nullable ConfigurableEnvironment environment;
private Set<String> additionalProfiles = new LinkedHashSet<>();
@ -98,7 +101,7 @@ public class SpringApplicationBuilder { @@ -98,7 +101,7 @@ public class SpringApplicationBuilder {
this(null, sources);
}
public SpringApplicationBuilder(ResourceLoader resourceLoader, Class<?>... sources) {
public SpringApplicationBuilder(@Nullable ResourceLoader resourceLoader, Class<?>... sources) {
this.application = createSpringApplication(resourceLoader, sources);
}
@ -111,15 +114,15 @@ public class SpringApplicationBuilder { @@ -111,15 +114,15 @@ public class SpringApplicationBuilder {
* @return the {@link SpringApplication} instance
* @since 2.6.0
*/
protected SpringApplication createSpringApplication(ResourceLoader resourceLoader, Class<?>... sources) {
protected SpringApplication createSpringApplication(@Nullable ResourceLoader resourceLoader, Class<?>... sources) {
return new SpringApplication(resourceLoader, sources);
}
/**
* Accessor for the current application context.
* @return the current application context (or null if not yet running)
* @return the current application context (or {@code null} if not yet running)
*/
public ConfigurableApplicationContext context() {
public @Nullable ConfigurableApplicationContext context() {
return this.context;
}
@ -140,15 +143,19 @@ public class SpringApplicationBuilder { @@ -140,15 +143,19 @@ public class SpringApplicationBuilder {
*/
public ConfigurableApplicationContext run(String... args) {
if (this.running.get()) {
ConfigurableApplicationContext context = this.context;
Assert.state(context != null, "No context set");
// If already created we just return the existing context
return this.context;
return context;
}
configureAsChildIfNecessary(args);
if (this.running.compareAndSet(false, true)) {
// If not already running copy the sources over and then run.
this.context = build().run(args);
}
return this.context;
ConfigurableApplicationContext context = this.context;
Assert.state(context != null, "No context set");
return context;
}
private void configureAsChildIfNecessary(String... args) {
@ -519,10 +526,10 @@ public class SpringApplicationBuilder { @@ -519,10 +526,10 @@ public class SpringApplicationBuilder {
/**
* Environment for the application context.
* @param environment the environment to set.
* @param environment the environment to set
* @return the current builder
*/
public SpringApplicationBuilder environment(ConfigurableEnvironment environment) {
public SpringApplicationBuilder environment(@Nullable ConfigurableEnvironment environment) {
this.application.setEnvironment(environment);
this.environment = environment;
return this;

3
core/spring-boot/src/main/java/org/springframework/boot/builder/package-info.java

@ -20,4 +20,7 @@ @@ -20,4 +20,7 @@
*
* @see org.springframework.boot.builder.SpringApplicationBuilder
*/
@NullMarked
package org.springframework.boot.builder;
import org.jspecify.annotations.NullMarked;

9
core/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java

@ -23,6 +23,7 @@ import java.util.Map; @@ -23,6 +23,7 @@ import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
@ -165,13 +166,13 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost @@ -165,13 +166,13 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost
return properties;
}
private void extractPropertiesFromApplication(Properties properties, Map<String, Object> map) {
private void extractPropertiesFromApplication(Properties properties, @Nullable Map<String, Object> map) {
if (map != null) {
flatten(properties, map, "");
}
}
private void extractPropertiesFromServices(Properties properties, Map<String, Object> map) {
private void extractPropertiesFromServices(Properties properties, @Nullable Map<String, Object> map) {
if (map != null) {
for (Object services : map.values()) {
@SuppressWarnings("unchecked")
@ -190,7 +191,7 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost @@ -190,7 +191,7 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost
}
@SuppressWarnings("unchecked")
private void flatten(Properties properties, Map<String, Object> input, String path) {
private void flatten(Properties properties, Map<String, Object> input, @Nullable String path) {
input.forEach((key, value) -> {
String name = getPropertyName(path, key);
if (value instanceof Map) {
@ -218,7 +219,7 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost @@ -218,7 +219,7 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost
});
}
private String getPropertyName(String path, String key) {
private String getPropertyName(@Nullable String path, String key) {
if (!StringUtils.hasText(path)) {
return key;
}

6
core/spring-boot/src/main/java/org/springframework/boot/cloud/CloudPlatform.java

@ -19,6 +19,8 @@ package org.springframework.boot.cloud; @@ -19,6 +19,8 @@ package org.springframework.boot.cloud;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
@ -198,7 +200,7 @@ public enum CloudPlatform { @@ -198,7 +200,7 @@ public enum CloudPlatform {
return isEnforced(binder.bind(PROPERTY_NAME, String.class).orElse(null));
}
private boolean isEnforced(String platform) {
private boolean isEnforced(@Nullable String platform) {
return name().equalsIgnoreCase(platform);
}
@ -225,7 +227,7 @@ public enum CloudPlatform { @@ -225,7 +227,7 @@ public enum CloudPlatform {
* @param environment the environment
* @return the {@link CloudPlatform} or {@code null}
*/
public static CloudPlatform getActive(Environment environment) {
public static @Nullable CloudPlatform getActive(@Nullable Environment environment) {
if (environment != null) {
for (CloudPlatform cloudPlatform : values()) {
if (cloudPlatform.isActive(environment)) {

3
core/spring-boot/src/main/java/org/springframework/boot/cloud/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Low level support for Cloud deployments.
*/
@NullMarked
package org.springframework.boot.cloud;
import org.jspecify.annotations.NullMarked;

11
core/spring-boot/src/main/java/org/springframework/boot/context/ApplicationPidFileWriter.java

@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicBoolean; @@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
@ -163,7 +164,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli @@ -163,7 +164,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
return Boolean.parseBoolean(value);
}
private String getProperty(SpringApplicationEvent event, List<Property> candidates) {
private @Nullable String getProperty(SpringApplicationEvent event, List<Property> candidates) {
for (Property candidate : candidates) {
String value = candidate.getValue(event);
if (value != null) {
@ -194,7 +195,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli @@ -194,7 +195,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
*/
private interface Property {
String getValue(SpringApplicationEvent event);
@Nullable String getValue(SpringApplicationEvent event);
}
@ -213,7 +214,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli @@ -213,7 +214,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
}
@Override
public String getValue(SpringApplicationEvent event) {
public @Nullable String getValue(SpringApplicationEvent event) {
Environment environment = getEnvironment(event);
if (environment == null) {
return null;
@ -221,7 +222,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli @@ -221,7 +222,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
return environment.getProperty(this.prefix + this.key);
}
private Environment getEnvironment(SpringApplicationEvent event) {
private @Nullable Environment getEnvironment(SpringApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent environmentPreparedEvent) {
return environmentPreparedEvent.getEnvironment();
}
@ -248,7 +249,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli @@ -248,7 +249,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
}
@Override
public String getValue(SpringApplicationEvent event) {
public @Nullable String getValue(SpringApplicationEvent event) {
return SystemProperties.get(this.properties);
}

13
core/spring-boot/src/main/java/org/springframework/boot/context/ConfigurationWarningsApplicationContextInitializer.java

@ -25,6 +25,7 @@ import java.util.Set; @@ -25,6 +25,7 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
@ -118,7 +119,7 @@ public class ConfigurationWarningsApplicationContextInitializer @@ -118,7 +119,7 @@ public class ConfigurationWarningsApplicationContextInitializer
* @param registry the {@link BeanDefinitionRegistry}
* @return a warning message or {@code null}
*/
String getWarning(BeanDefinitionRegistry registry);
@Nullable String getWarning(BeanDefinitionRegistry registry);
}
@ -137,7 +138,7 @@ public class ConfigurationWarningsApplicationContextInitializer @@ -137,7 +138,7 @@ public class ConfigurationWarningsApplicationContextInitializer
}
@Override
public String getWarning(BeanDefinitionRegistry registry) {
public @Nullable String getWarning(BeanDefinitionRegistry registry) {
Set<String> scannedPackages = getComponentScanningPackages(registry);
List<String> problematicPackages = getProblematicPackages(scannedPackages);
if (problematicPackages.isEmpty()) {
@ -172,13 +173,13 @@ public class ConfigurationWarningsApplicationContextInitializer @@ -172,13 +173,13 @@ public class ConfigurationWarningsApplicationContextInitializer
}
}
private void addPackages(Set<String> packages, String[] values) {
private void addPackages(Set<String> packages, String @Nullable [] values) {
if (values != null) {
Collections.addAll(packages, values);
}
}
private void addClasses(Set<String> packages, String[] values) {
private void addClasses(Set<String> packages, String @Nullable [] values) {
if (values != null) {
for (String value : values) {
packages.add(ClassUtils.getPackageName(value));
@ -196,14 +197,14 @@ public class ConfigurationWarningsApplicationContextInitializer @@ -196,14 +197,14 @@ public class ConfigurationWarningsApplicationContextInitializer
return problematicPackages;
}
private boolean isProblematicPackage(String scannedPackage) {
private boolean isProblematicPackage(@Nullable String scannedPackage) {
if (scannedPackage == null || scannedPackage.isEmpty()) {
return true;
}
return PROBLEM_PACKAGES.contains(scannedPackage);
}
private String getDisplayName(String scannedPackage) {
private String getDisplayName(@Nullable String scannedPackage) {
if (scannedPackage == null || scannedPackage.isEmpty()) {
return "the default package";
}

7
core/spring-boot/src/main/java/org/springframework/boot/context/TypeExcludeFilter.java

@ -19,6 +19,8 @@ package org.springframework.boot.context; @@ -19,6 +19,8 @@ package org.springframework.boot.context;
import java.io.IOException;
import java.util.Collection;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@ -49,9 +51,10 @@ import org.springframework.core.type.filter.TypeFilter; @@ -49,9 +51,10 @@ import org.springframework.core.type.filter.TypeFilter;
*/
public class TypeExcludeFilter implements TypeFilter, BeanFactoryAware {
@SuppressWarnings("NullAway.Init")
private BeanFactory beanFactory;
private Collection<TypeExcludeFilter> delegates;
private @Nullable Collection<TypeExcludeFilter> delegates;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
@ -81,7 +84,7 @@ public class TypeExcludeFilter implements TypeFilter, BeanFactoryAware { @@ -81,7 +84,7 @@ public class TypeExcludeFilter implements TypeFilter, BeanFactoryAware {
}
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
throw new IllegalStateException("TypeExcludeFilter " + getClass() + " has not implemented equals");
}

10
core/spring-boot/src/main/java/org/springframework/boot/context/annotation/Configurations.java

@ -30,6 +30,8 @@ import java.util.function.UnaryOperator; @@ -30,6 +30,8 @@ import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportSelector;
@ -61,11 +63,11 @@ public abstract class Configurations { @@ -61,11 +63,11 @@ public abstract class Configurations {
private static final Comparator<Object> COMPARATOR = OrderComparator.INSTANCE
.thenComparing((other) -> other.getClass().getName());
private final UnaryOperator<Collection<Class<?>>> sorter;
private final @Nullable UnaryOperator<Collection<Class<?>>> sorter;
private final Set<Class<?>> classes;
private final Function<Class<?>, String> beanNameGenerator;
private final @Nullable Function<Class<?>, String> beanNameGenerator;
/**
* Create a new {@link Configurations} instance.
@ -85,7 +87,7 @@ public abstract class Configurations { @@ -85,7 +87,7 @@ public abstract class Configurations {
* @param beanNameGenerator an optional function used to generate the bean name
* @since 3.4.0
*/
protected Configurations(UnaryOperator<Collection<Class<?>>> sorter, Collection<Class<?>> classes,
protected Configurations(@Nullable UnaryOperator<Collection<Class<?>>> sorter, Collection<Class<?>> classes,
Function<Class<?>, String> beanNameGenerator) {
Assert.notNull(classes, "'classes' must not be null");
this.sorter = (sorter != null) ? sorter : UnaryOperator.identity();
@ -127,7 +129,7 @@ public abstract class Configurations { @@ -127,7 +129,7 @@ public abstract class Configurations {
* @return the bean name
* @since 3.4.0
*/
public String getBeanName(Class<?> beanClass) {
public @Nullable String getBeanName(Class<?> beanClass) {
return (this.beanNameGenerator != null) ? this.beanNameGenerator.apply(beanClass) : null;
}

6
core/spring-boot/src/main/java/org/springframework/boot/context/annotation/ImportCandidates.java

@ -27,6 +27,8 @@ import java.util.Enumeration; @@ -27,6 +27,8 @@ import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.core.io.UrlResource;
import org.springframework.util.Assert;
@ -76,7 +78,7 @@ public final class ImportCandidates implements Iterable<String> { @@ -76,7 +78,7 @@ public final class ImportCandidates implements Iterable<String> {
* @param classLoader class loader to use for loading
* @return list of names of annotated classes
*/
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
public static ImportCandidates load(Class<?> annotation, @Nullable ClassLoader classLoader) {
Assert.notNull(annotation, "'annotation' must not be null");
ClassLoader classLoaderToUse = decideClassloader(classLoader);
String location = String.format(LOCATION, annotation.getName());
@ -89,7 +91,7 @@ public final class ImportCandidates implements Iterable<String> { @@ -89,7 +91,7 @@ public final class ImportCandidates implements Iterable<String> {
return new ImportCandidates(importCandidates);
}
private static ClassLoader decideClassloader(ClassLoader classLoader) {
private static ClassLoader decideClassloader(@Nullable ClassLoader classLoader) {
if (classLoader == null) {
return ImportCandidates.class.getClassLoader();
}

3
core/spring-boot/src/main/java/org/springframework/boot/context/annotation/package-info.java

@ -18,4 +18,7 @@ @@ -18,4 +18,7 @@
* Classes related to Spring's {@link org.springframework.context.ApplicationContext}
* annotations.
*/
@NullMarked
package org.springframework.boot.context.annotation;
import org.jspecify.annotations.NullMarked;

4
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigData.java

@ -25,6 +25,8 @@ import java.util.List; @@ -25,6 +25,8 @@ import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.util.Assert;
@ -120,7 +122,7 @@ public final class ConfigData { @@ -120,7 +122,7 @@ public final class ConfigData {
* @param propertySource the property source
* @return the options to apply
*/
Options get(PropertySource<?> propertySource);
@Nullable Options get(PropertySource<?> propertySource);
/**
* Create a new {@link PropertySourceOptions} instance that always returns the

14
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataActivationContext.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment;
@ -29,9 +31,9 @@ import org.springframework.core.style.ToStringCreator; @@ -29,9 +31,9 @@ import org.springframework.core.style.ToStringCreator;
*/
class ConfigDataActivationContext {
private final CloudPlatform cloudPlatform;
private final @Nullable CloudPlatform cloudPlatform;
private final Profiles profiles;
private final @Nullable Profiles profiles;
/**
* Create a new {@link ConfigDataActivationContext} instance before any profiles have
@ -50,12 +52,12 @@ class ConfigDataActivationContext { @@ -50,12 +52,12 @@ class ConfigDataActivationContext {
* @param cloudPlatform the cloud platform
* @param profiles the profiles
*/
ConfigDataActivationContext(CloudPlatform cloudPlatform, Profiles profiles) {
ConfigDataActivationContext(@Nullable CloudPlatform cloudPlatform, Profiles profiles) {
this.cloudPlatform = cloudPlatform;
this.profiles = profiles;
}
private CloudPlatform deduceCloudPlatform(Environment environment, Binder binder) {
private @Nullable CloudPlatform deduceCloudPlatform(Environment environment, Binder binder) {
for (CloudPlatform candidate : CloudPlatform.values()) {
if (candidate.isEnforced(binder)) {
return candidate;
@ -77,7 +79,7 @@ class ConfigDataActivationContext { @@ -77,7 +79,7 @@ class ConfigDataActivationContext {
* Return the active {@link CloudPlatform} or {@code null}.
* @return the active cloud platform
*/
CloudPlatform getCloudPlatform() {
@Nullable CloudPlatform getCloudPlatform() {
return this.cloudPlatform;
}
@ -85,7 +87,7 @@ class ConfigDataActivationContext { @@ -85,7 +87,7 @@ class ConfigDataActivationContext {
* Return profile information if it is available.
* @return profile information or {@code null}
*/
Profiles getProfiles() {
@Nullable Profiles getProfiles() {
return this.profiles;
}

7
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironment.java

@ -24,6 +24,7 @@ import java.util.List; @@ -24,6 +24,7 @@ import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.BootstrapRegistry.InstanceSupplier;
import org.springframework.boot.BootstrapRegistry.Scope;
@ -43,6 +44,7 @@ import org.springframework.core.env.PropertySource; @@ -43,6 +44,7 @@ import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.log.LogMessage;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -137,7 +139,7 @@ class ConfigDataEnvironment { @@ -137,7 +139,7 @@ class ConfigDataEnvironment {
*/
ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles,
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
@Nullable ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
Binder binder = Binder.get(environment);
this.logFactory = logFactory;
this.logger = logFactory.getLog(getClass());
@ -321,7 +323,7 @@ class ConfigDataEnvironment { @@ -321,7 +323,7 @@ class ConfigDataEnvironment {
}
private void registerBootstrapBinder(ConfigDataEnvironmentContributors contributors,
ConfigDataActivationContext activationContext, BinderOption... binderOptions) {
@Nullable ConfigDataActivationContext activationContext, BinderOption... binderOptions) {
this.bootstrapContext.register(Binder.class,
InstanceSupplier.from(() -> contributors.getBinder(activationContext, binderOptions))
.withScope(Scope.PROTOTYPE));
@ -336,6 +338,7 @@ class ConfigDataEnvironment { @@ -336,6 +338,7 @@ class ConfigDataEnvironment {
applyContributor(contributors, activationContext, propertySources);
DefaultPropertiesPropertySource.moveToEnd(propertySources);
Profiles profiles = activationContext.getProfiles();
Assert.state(profiles != null, "'profiles' must not be null");
this.logger.trace(LogMessage.format("Setting default profiles: %s", profiles.getDefault()));
this.environment.setDefaultProfiles(StringUtils.toStringArray(profiles.getDefault()));
this.logger.trace(LogMessage.format("Setting active profiles: %s", profiles.getActive()));

49
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentContributor.java

@ -26,6 +26,8 @@ import java.util.NoSuchElementException; @@ -26,6 +26,8 @@ import java.util.NoSuchElementException;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
@ -33,6 +35,7 @@ import org.springframework.boot.origin.OriginLookup; @@ -33,6 +35,7 @@ import org.springframework.boot.origin.OriginLookup;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.lang.Contract;
import org.springframework.util.CollectionUtils;
/**
@ -58,17 +61,17 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -58,17 +61,17 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
private static final ConfigData.Options EMPTY_LOCATION_OPTIONS = ConfigData.Options
.of(ConfigData.Option.IGNORE_IMPORTS);
private final ConfigDataLocation location;
private final @Nullable ConfigDataLocation location;
private final ConfigDataResource resource;
private final @Nullable ConfigDataResource resource;
private final boolean fromProfileSpecificImport;
private final PropertySource<?> propertySource;
private final @Nullable PropertySource<?> propertySource;
private final ConfigurationPropertySource configurationPropertySource;
private final @Nullable ConfigurationPropertySource configurationPropertySource;
private final ConfigDataProperties properties;
private final @Nullable ConfigDataProperties properties;
private final ConfigData.Options configDataOptions;
@ -93,10 +96,12 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -93,10 +96,12 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* @param children the children of this contributor at each {@link ImportPhase}
* @param conversionService the conversion service to use
*/
ConfigDataEnvironmentContributor(Kind kind, ConfigDataLocation location, ConfigDataResource resource,
boolean fromProfileSpecificImport, PropertySource<?> propertySource,
ConfigurationPropertySource configurationPropertySource, ConfigDataProperties properties,
ConfigData.Options configDataOptions, Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children,
ConfigDataEnvironmentContributor(Kind kind, @Nullable ConfigDataLocation location,
@Nullable ConfigDataResource resource, boolean fromProfileSpecificImport,
@Nullable PropertySource<?> propertySource,
@Nullable ConfigurationPropertySource configurationPropertySource,
@Nullable ConfigDataProperties properties, ConfigData.@Nullable Options configDataOptions,
@Nullable Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children,
ConversionService conversionService) {
this.kind = kind;
this.location = location;
@ -118,7 +123,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -118,7 +123,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
return this.kind;
}
ConfigDataLocation getLocation() {
@Nullable ConfigDataLocation getLocation() {
return this.location;
}
@ -127,7 +132,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -127,7 +132,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* @param activationContext the activation context
* @return if the contributor is active
*/
boolean isActive(ConfigDataActivationContext activationContext) {
boolean isActive(@Nullable ConfigDataActivationContext activationContext) {
if (this.kind == Kind.UNBOUND_IMPORT) {
return false;
}
@ -138,7 +143,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -138,7 +143,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* Return the resource that contributed this instance.
* @return the resource or {@code null}
*/
ConfigDataResource getResource() {
@Nullable ConfigDataResource getResource() {
return this.resource;
}
@ -154,7 +159,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -154,7 +159,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* Return the property source for this contributor.
* @return the property source or {@code null}
*/
PropertySource<?> getPropertySource() {
@Nullable PropertySource<?> getPropertySource() {
return this.propertySource;
}
@ -162,7 +167,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -162,7 +167,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* Return the configuration property source for this contributor.
* @return the configuration property source or {@code null}
*/
ConfigurationPropertySource getConfigurationPropertySource() {
@Nullable ConfigurationPropertySource getConfigurationPropertySource() {
return this.configurationPropertySource;
}
@ -239,7 +244,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -239,7 +244,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* @return a new contributor instance
*/
ConfigDataEnvironmentContributor withBoundProperties(Iterable<ConfigDataEnvironmentContributor> contributors,
ConfigDataActivationContext activationContext) {
@Nullable ConfigDataActivationContext activationContext) {
Iterable<ConfigurationPropertySource> sources = Collections.singleton(getConfigurationPropertySource());
PlaceholdersResolver placeholdersResolver = new ConfigDataEnvironmentContributorPlaceholdersResolver(
contributors, activationContext, this, true, this.conversionService);
@ -305,7 +310,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -305,7 +310,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
return contributor;
}
private boolean hasAnyProfileSpecificChildren(List<ConfigDataEnvironmentContributor> contributors) {
@Contract("null -> false")
private boolean hasAnyProfileSpecificChildren(@Nullable List<ConfigDataEnvironmentContributor> contributors) {
if (CollectionUtils.isEmpty(contributors)) {
return false;
}
@ -441,7 +447,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -441,7 +447,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
propertySource, asConfigurationPropertySource(propertySource), null, options, null, conversionService);
}
private static ConfigurationPropertySource asConfigurationPropertySource(PropertySource<?> propertySource) {
private static @Nullable ConfigurationPropertySource asConfigurationPropertySource(
PropertySource<?> propertySource) {
ConfigurationPropertySource configurationPropertySource = ConfigurationPropertySource.from(propertySource);
if (configurationPropertySource != null && propertySource instanceof OriginLookup<?> originLookup) {
configurationPropertySource = configurationPropertySource.withPrefix(originLookup.getPrefix());
@ -521,7 +528,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -521,7 +528,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
* @param activationContext the activation context
* @return the import phase
*/
static ImportPhase get(ConfigDataActivationContext activationContext) {
static ImportPhase get(@Nullable ConfigDataActivationContext activationContext) {
if (activationContext != null && activationContext.getProfiles() != null) {
return AFTER_PROFILE_ACTIVATION;
}
@ -535,13 +542,13 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -535,13 +542,13 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
*/
private final class ContributorIterator implements Iterator<ConfigDataEnvironmentContributor> {
private ImportPhase phase;
private @Nullable ImportPhase phase;
private Iterator<ConfigDataEnvironmentContributor> children;
private Iterator<ConfigDataEnvironmentContributor> current;
private ConfigDataEnvironmentContributor next;
private @Nullable ConfigDataEnvironmentContributor next;
private ContributorIterator() {
this.phase = ImportPhase.AFTER_PROFILE_ACTIVATION;
@ -564,7 +571,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment @@ -564,7 +571,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
return next;
}
private ConfigDataEnvironmentContributor fetchIfNecessary() {
private @Nullable ConfigDataEnvironmentContributor fetchIfNecessary() {
if (this.next != null) {
return this.next;
}

19
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentContributorPlaceholdersResolver.java

@ -16,12 +16,15 @@ @@ -16,12 +16,15 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginLookup;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.PropertySource;
import org.springframework.util.Assert;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.SystemPropertyUtils;
@ -37,19 +40,20 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde @@ -37,19 +40,20 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde
private final Iterable<ConfigDataEnvironmentContributor> contributors;
private final ConfigDataActivationContext activationContext;
private final @Nullable ConfigDataActivationContext activationContext;
private final boolean failOnResolveFromInactiveContributor;
private final PropertyPlaceholderHelper helper;
private final ConfigDataEnvironmentContributor activeContributor;
private final @Nullable ConfigDataEnvironmentContributor activeContributor;
private final ConversionService conversionService;
ConfigDataEnvironmentContributorPlaceholdersResolver(Iterable<ConfigDataEnvironmentContributor> contributors,
ConfigDataActivationContext activationContext, ConfigDataEnvironmentContributor activeContributor,
boolean failOnResolveFromInactiveContributor, ConversionService conversionService) {
@Nullable ConfigDataActivationContext activationContext,
@Nullable ConfigDataEnvironmentContributor activeContributor, boolean failOnResolveFromInactiveContributor,
ConversionService conversionService) {
this.contributors = contributors;
this.activationContext = activationContext;
this.activeContributor = activeContributor;
@ -61,14 +65,14 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde @@ -61,14 +65,14 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde
}
@Override
public Object resolvePlaceholders(Object value) {
public @Nullable Object resolvePlaceholders(@Nullable Object value) {
if (value instanceof String string) {
return this.helper.replacePlaceholders(string, this::resolvePlaceholder);
}
return value;
}
private String resolvePlaceholder(String placeholder) {
private @Nullable String resolvePlaceholder(String placeholder) {
Object result = null;
for (ConfigDataEnvironmentContributor contributor : this.contributors) {
PropertySource<?> propertySource = contributor.getPropertySource();
@ -76,6 +80,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde @@ -76,6 +80,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde
if (value != null && !isActive(contributor)) {
if (this.failOnResolveFromInactiveContributor) {
ConfigDataResource resource = contributor.getResource();
Assert.state(propertySource != null, "'propertySource' can't be null here");
Origin origin = OriginLookup.getOrigin(propertySource, placeholder);
throw new InactiveConfigDataAccessException(propertySource, resource, placeholder, origin);
}
@ -97,7 +102,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde @@ -97,7 +102,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde
.isActive(this.activationContext);
}
private String convertValueIfNecessary(Object value) {
private @Nullable String convertValueIfNecessary(Object value) {
return (value instanceof String string) ? string : this.conversionService.convert(value, String.class);
}

29
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentContributors.java

@ -27,6 +27,7 @@ import java.util.Set; @@ -27,6 +27,7 @@ import java.util.Set;
import java.util.function.Predicate;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
@ -102,7 +103,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen @@ -102,7 +103,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
* imports have been processed
*/
ConfigDataEnvironmentContributors withProcessedImports(ConfigDataImporter importer,
ConfigDataActivationContext activationContext) {
@Nullable ConfigDataActivationContext activationContext) {
ImportPhase importPhase = ImportPhase.get(activationContext);
this.logger.trace(LogMessage.format("Processing imports for phase %s. %s", importPhase,
(activationContext != null) ? activationContext : "no activation context"));
@ -152,8 +153,8 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen @@ -152,8 +153,8 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
return this.bootstrapContext;
}
private ConfigDataEnvironmentContributor getNextToProcess(ConfigDataEnvironmentContributors contributors,
ConfigDataActivationContext activationContext, ImportPhase importPhase) {
private @Nullable ConfigDataEnvironmentContributor getNextToProcess(ConfigDataEnvironmentContributors contributors,
@Nullable ConfigDataActivationContext activationContext, ImportPhase importPhase) {
for (ConfigDataEnvironmentContributor contributor : contributors.getRoot()) {
if (contributor.getKind() == Kind.UNBOUND_IMPORT
|| isActiveWithUnprocessedImports(activationContext, importPhase, contributor)) {
@ -163,7 +164,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen @@ -163,7 +164,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
return null;
}
private boolean isActiveWithUnprocessedImports(ConfigDataActivationContext activationContext,
private boolean isActiveWithUnprocessedImports(@Nullable ConfigDataActivationContext activationContext,
ImportPhase importPhase, ConfigDataEnvironmentContributor contributor) {
return contributor.isActive(activationContext) && contributor.hasUnprocessedImports(importPhase);
}
@ -203,7 +204,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen @@ -203,7 +204,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
* @param options binder options to apply
* @return a binder instance
*/
Binder getBinder(ConfigDataActivationContext activationContext, BinderOption... options) {
Binder getBinder(@Nullable ConfigDataActivationContext activationContext, BinderOption... options) {
return getBinder(activationContext, NO_CONTRIBUTOR_FILTER, options);
}
@ -214,8 +215,8 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen @@ -214,8 +215,8 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
* @param options binder options to apply
* @return a binder instance
*/
Binder getBinder(ConfigDataActivationContext activationContext, Predicate<ConfigDataEnvironmentContributor> filter,
BinderOption... options) {
Binder getBinder(@Nullable ConfigDataActivationContext activationContext,
Predicate<ConfigDataEnvironmentContributor> filter, BinderOption... options) {
return getBinder(activationContext, filter, asBinderOptionsSet(options));
}
@ -224,7 +225,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen @@ -224,7 +225,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
: EnumSet.copyOf(Arrays.asList(options));
}
private Binder getBinder(ConfigDataActivationContext activationContext,
private Binder getBinder(@Nullable ConfigDataActivationContext activationContext,
Predicate<ConfigDataEnvironmentContributor> filter, Set<BinderOption> options) {
boolean failOnInactiveSource = options.contains(BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
Iterable<ConfigurationPropertySource> sources = () -> getBinderSources(
@ -279,12 +280,12 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen @@ -279,12 +280,12 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
private final ConfigDataEnvironmentContributor contributor;
private final ConfigDataActivationContext activationContext;
private final @Nullable ConfigDataActivationContext activationContext;
private volatile Binder binder;
private volatile @Nullable Binder binder;
ContributorConfigDataLocationResolverContext(ConfigDataEnvironmentContributors contributors,
ConfigDataEnvironmentContributor contributor, ConfigDataActivationContext activationContext) {
ConfigDataEnvironmentContributor contributor, @Nullable ConfigDataActivationContext activationContext) {
this.contributors = contributors;
this.contributor = contributor;
this.activationContext = activationContext;
@ -301,7 +302,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen @@ -301,7 +302,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
}
@Override
public ConfigDataResource getParent() {
public @Nullable ConfigDataResource getParent() {
return this.contributor.getResource();
}
@ -314,9 +315,9 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen @@ -314,9 +315,9 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
private class InactiveSourceChecker implements BindHandler {
private final ConfigDataActivationContext activationContext;
private final @Nullable ConfigDataActivationContext activationContext;
InactiveSourceChecker(ConfigDataActivationContext activationContext) {
InactiveSourceChecker(@Nullable ConfigDataActivationContext activationContext) {
this.activationContext = activationContext;
}

15
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessor.java

@ -22,6 +22,7 @@ import java.util.Collections; @@ -22,6 +22,7 @@ import java.util.Collections;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.DefaultBootstrapContext;
@ -63,7 +64,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces @@ -63,7 +64,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
private final ConfigurableBootstrapContext bootstrapContext;
private final ConfigDataEnvironmentUpdateListener environmentUpdateListener;
private final @Nullable ConfigDataEnvironmentUpdateListener environmentUpdateListener;
public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
ConfigurableBootstrapContext bootstrapContext) {
@ -72,7 +73,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces @@ -72,7 +73,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
private ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
ConfigurableBootstrapContext bootstrapContext,
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
@Nullable ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
this.logFactory = logFactory;
this.logger = logFactory.getLog(getClass());
this.bootstrapContext = bootstrapContext;
@ -89,7 +90,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces @@ -89,7 +90,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
postProcessEnvironment(environment, application.getResourceLoader(), application.getAdditionalProfiles());
}
void postProcessEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
void postProcessEnvironment(ConfigurableEnvironment environment, @Nullable ResourceLoader resourceLoader,
Collection<String> additionalProfiles) {
this.logger.trace("Post-processing environment to add config data");
resourceLoader = (resourceLoader != null) ? resourceLoader : new DefaultResourceLoader();
@ -123,7 +124,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces @@ -123,7 +124,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
* @param additionalProfiles any additional profiles that should be applied
*/
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
ConfigurableBootstrapContext bootstrapContext, String... additionalProfiles) {
@Nullable ConfigurableBootstrapContext bootstrapContext, String... additionalProfiles) {
applyTo(environment, resourceLoader, bootstrapContext, Arrays.asList(additionalProfiles));
}
@ -137,8 +138,8 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces @@ -137,8 +138,8 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
* throw-away context
* @param additionalProfiles any additional profiles that should be applied
*/
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
ConfigurableBootstrapContext bootstrapContext, Collection<String> additionalProfiles) {
public static void applyTo(ConfigurableEnvironment environment, @Nullable ResourceLoader resourceLoader,
@Nullable ConfigurableBootstrapContext bootstrapContext, Collection<String> additionalProfiles) {
DeferredLogFactory logFactory = Supplier::get;
bootstrapContext = (bootstrapContext != null) ? bootstrapContext : new DefaultBootstrapContext();
ConfigDataEnvironmentPostProcessor postProcessor = new ConfigDataEnvironmentPostProcessor(logFactory,
@ -160,7 +161,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces @@ -160,7 +161,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
* {@link Environment} updates.
*/
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
ConfigurableBootstrapContext bootstrapContext, Collection<String> additionalProfiles,
@Nullable ConfigurableBootstrapContext bootstrapContext, Collection<String> additionalProfiles,
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
DeferredLogFactory logFactory = Supplier::get;
bootstrapContext = (bootstrapContext != null) ? bootstrapContext : new DefaultBootstrapContext();

6
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentUpdateListener.java

@ -18,6 +18,8 @@ package org.springframework.boot.context.config; @@ -18,6 +18,8 @@ package org.springframework.boot.context.config;
import java.util.EventListener;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.config.ConfigData.Options;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
@ -43,8 +45,8 @@ public interface ConfigDataEnvironmentUpdateListener extends EventListener { @@ -43,8 +45,8 @@ public interface ConfigDataEnvironmentUpdateListener extends EventListener {
* @param location the original {@link ConfigDataLocation} of the source.
* @param resource the {@link ConfigDataResource} of the source.
*/
default void onPropertySourceAdded(PropertySource<?> propertySource, ConfigDataLocation location,
ConfigDataResource resource) {
default void onPropertySourceAdded(PropertySource<?> propertySource, @Nullable ConfigDataLocation location,
@Nullable ConfigDataResource resource) {
}
/**

4
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataException.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
/**
* Abstract base class for configuration data exceptions.
*
@ -30,7 +32,7 @@ public abstract class ConfigDataException extends RuntimeException { @@ -30,7 +32,7 @@ public abstract class ConfigDataException extends RuntimeException {
* @param message the exception message
* @param cause the exception cause
*/
protected ConfigDataException(String message, Throwable cause) {
protected ConfigDataException(String message, @Nullable Throwable cause) {
super(message, cause);
}

13
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataImporter.java

@ -26,6 +26,7 @@ import java.util.Map; @@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.log.LogMessage;
@ -78,7 +79,7 @@ class ConfigDataImporter { @@ -78,7 +79,7 @@ class ConfigDataImporter {
* @param locations the locations to resolve
* @return a map of the loaded locations and data
*/
Map<ConfigDataResolutionResult, ConfigData> resolveAndLoad(ConfigDataActivationContext activationContext,
Map<ConfigDataResolutionResult, ConfigData> resolveAndLoad(@Nullable ConfigDataActivationContext activationContext,
ConfigDataLocationResolverContext locationResolverContext, ConfigDataLoaderContext loaderContext,
List<ConfigDataLocation> locations) {
try {
@ -92,7 +93,7 @@ class ConfigDataImporter { @@ -92,7 +93,7 @@ class ConfigDataImporter {
}
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext locationResolverContext,
Profiles profiles, List<ConfigDataLocation> locations) {
@Nullable Profiles profiles, List<ConfigDataLocation> locations) {
List<ConfigDataResolutionResult> resolved = new ArrayList<>(locations.size());
for (ConfigDataLocation location : locations) {
resolved.addAll(resolve(locationResolverContext, profiles, location));
@ -101,7 +102,7 @@ class ConfigDataImporter { @@ -101,7 +102,7 @@ class ConfigDataImporter {
}
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext locationResolverContext,
Profiles profiles, ConfigDataLocation location) {
@Nullable Profiles profiles, ConfigDataLocation location) {
try {
return this.resolvers.resolve(locationResolverContext, location, profiles);
}
@ -145,14 +146,16 @@ class ConfigDataImporter { @@ -145,14 +146,16 @@ class ConfigDataImporter {
return Collections.unmodifiableMap(result);
}
private void handle(ConfigDataNotFoundException ex, ConfigDataLocation location, ConfigDataResource resource) {
private void handle(ConfigDataNotFoundException ex, ConfigDataLocation location,
@Nullable ConfigDataResource resource) {
if (ex instanceof ConfigDataResourceNotFoundException notFoundException) {
ex = notFoundException.withLocation(location);
}
getNotFoundAction(location, resource).handle(this.logger, ex);
}
private ConfigDataNotFoundAction getNotFoundAction(ConfigDataLocation location, ConfigDataResource resource) {
private ConfigDataNotFoundAction getNotFoundAction(ConfigDataLocation location,
@Nullable ConfigDataResource resource) {
if (location.isOptional() || (resource != null && resource.isOptional())) {
return ConfigDataNotFoundAction.IGNORE;
}

4
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLoader.java

@ -18,6 +18,8 @@ package org.springframework.boot.context.config; @@ -18,6 +18,8 @@ package org.springframework.boot.context.config;
import java.io.IOException;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.BootstrapContext;
import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.ConfigurableBootstrapContext;
@ -61,7 +63,7 @@ public interface ConfigDataLoader<R extends ConfigDataResource> { @@ -61,7 +63,7 @@ public interface ConfigDataLoader<R extends ConfigDataResource> {
* @throws IOException on IO error
* @throws ConfigDataResourceNotFoundException if the resource cannot be found
*/
ConfigData load(ConfigDataLoaderContext context, R resource)
@Nullable ConfigData load(ConfigDataLoaderContext context, R resource)
throws IOException, ConfigDataResourceNotFoundException;
}

6
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLoaders.java

@ -22,6 +22,7 @@ import java.util.Collections; @@ -22,6 +22,7 @@ import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.BootstrapContext;
import org.springframework.boot.BootstrapRegistry;
@ -78,7 +79,7 @@ class ConfigDataLoaders { @@ -78,7 +79,7 @@ class ConfigDataLoaders {
return Collections.unmodifiableList(resourceTypes);
}
private Class<?> getResourceType(ConfigDataLoader<?> loader) {
private @Nullable Class<?> getResourceType(ConfigDataLoader<?> loader) {
return ResolvableType.forClass(loader.getClass()).as(ConfigDataLoader.class).resolveGeneric();
}
@ -90,7 +91,8 @@ class ConfigDataLoaders { @@ -90,7 +91,8 @@ class ConfigDataLoaders {
* @return the loaded {@link ConfigData}
* @throws IOException on IO error
*/
<R extends ConfigDataResource> ConfigData load(ConfigDataLoaderContext context, R resource) throws IOException {
<R extends ConfigDataResource> @Nullable ConfigData load(ConfigDataLoaderContext context, R resource)
throws IOException {
ConfigDataLoader<R> loader = getLoader(context, resource);
this.logger.trace(LogMessage.of(() -> "Loading " + resource + " using loader " + loader.getClass().getName()));
return loader.load(context, resource);

27
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocation.java

@ -16,8 +16,11 @@ @@ -16,8 +16,11 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginProvider;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -44,9 +47,9 @@ public final class ConfigDataLocation implements OriginProvider { @@ -44,9 +47,9 @@ public final class ConfigDataLocation implements OriginProvider {
private final String value;
private final Origin origin;
private final @Nullable Origin origin;
private ConfigDataLocation(boolean optional, String value, Origin origin) {
private ConfigDataLocation(boolean optional, String value, @Nullable Origin origin) {
this.value = value;
this.optional = optional;
this.origin = origin;
@ -93,7 +96,7 @@ public final class ConfigDataLocation implements OriginProvider { @@ -93,7 +96,7 @@ public final class ConfigDataLocation implements OriginProvider {
}
@Override
public Origin getOrigin() {
public @Nullable Origin getOrigin() {
return this.origin;
}
@ -118,7 +121,10 @@ public final class ConfigDataLocation implements OriginProvider { @@ -118,7 +121,10 @@ public final class ConfigDataLocation implements OriginProvider {
String[] values = StringUtils.delimitedListToStringArray(toString(), delimiter);
ConfigDataLocation[] result = new ConfigDataLocation[values.length];
for (int i = 0; i < values.length; i++) {
result[i] = of(values[i]).withOrigin(getOrigin());
int index = i;
ConfigDataLocation configDataLocation = of(values[index]);
Assert.state(configDataLocation != null, () -> "Unable to parse '%s'".formatted(values[index]));
result[i] = configDataLocation.withOrigin(getOrigin());
}
return result;
}
@ -150,7 +156,7 @@ public final class ConfigDataLocation implements OriginProvider { @@ -150,7 +156,7 @@ public final class ConfigDataLocation implements OriginProvider {
* @param origin the origin to set
* @return a new {@link ConfigDataLocation} instance.
*/
ConfigDataLocation withOrigin(Origin origin) {
ConfigDataLocation withOrigin(@Nullable Origin origin) {
return new ConfigDataLocation(this.optional, this.value, origin);
}
@ -160,9 +166,16 @@ public final class ConfigDataLocation implements OriginProvider { @@ -160,9 +166,16 @@ public final class ConfigDataLocation implements OriginProvider {
* @return a {@link ConfigDataLocation} instance or {@code null} if no location was
* provided
*/
public static ConfigDataLocation of(String location) {
public static @Nullable ConfigDataLocation of(@Nullable String location) {
boolean optional = location != null && location.startsWith(OPTIONAL_PREFIX);
String value = (!optional) ? location : location.substring(OPTIONAL_PREFIX.length());
String value;
if (optional) {
Assert.state(location != null, "'location' can't be null here");
value = location.substring(OPTIONAL_PREFIX.length());
}
else {
value = location;
}
if (!StringUtils.hasText(value)) {
return null;
}

8
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationNotFoundException.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.origin.Origin;
import org.springframework.util.Assert;
@ -43,7 +45,7 @@ public class ConfigDataLocationNotFoundException extends ConfigDataNotFoundExcep @@ -43,7 +45,7 @@ public class ConfigDataLocationNotFoundException extends ConfigDataNotFoundExcep
* @param location the location that could not be found
* @param cause the exception cause
*/
public ConfigDataLocationNotFoundException(ConfigDataLocation location, Throwable cause) {
public ConfigDataLocationNotFoundException(ConfigDataLocation location, @Nullable Throwable cause) {
this(location, getMessage(location), cause);
}
@ -54,7 +56,7 @@ public class ConfigDataLocationNotFoundException extends ConfigDataNotFoundExcep @@ -54,7 +56,7 @@ public class ConfigDataLocationNotFoundException extends ConfigDataNotFoundExcep
* @param cause the exception cause
* @since 2.4.7
*/
public ConfigDataLocationNotFoundException(ConfigDataLocation location, String message, Throwable cause) {
public ConfigDataLocationNotFoundException(ConfigDataLocation location, String message, @Nullable Throwable cause) {
super(message, cause);
Assert.notNull(location, "'location' must not be null");
this.location = location;
@ -69,7 +71,7 @@ public class ConfigDataLocationNotFoundException extends ConfigDataNotFoundExcep @@ -69,7 +71,7 @@ public class ConfigDataLocationNotFoundException extends ConfigDataNotFoundExcep
}
@Override
public Origin getOrigin() {
public @Nullable Origin getOrigin() {
return Origin.from(this.location);
}

4
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationResolverContext.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.env.EnvironmentPostProcessor;
@ -41,7 +43,7 @@ public interface ConfigDataLocationResolverContext { @@ -41,7 +43,7 @@ public interface ConfigDataLocationResolverContext {
* or {@code null} if there is no available parent.
* @return the parent location
*/
ConfigDataResource getParent();
@Nullable ConfigDataResource getParent();
/**
* Provides access to the {@link ConfigurableBootstrapContext} shared across all

9
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationResolvers.java

@ -22,6 +22,7 @@ import java.util.List; @@ -22,6 +22,7 @@ import java.util.List;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.BootstrapContext;
import org.springframework.boot.BootstrapRegistry;
@ -84,8 +85,8 @@ class ConfigDataLocationResolvers { @@ -84,8 +85,8 @@ class ConfigDataLocationResolvers {
return Collections.unmodifiableList(reordered);
}
List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext context, ConfigDataLocation location,
Profiles profiles) {
List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext context,
@Nullable ConfigDataLocation location, @Nullable Profiles profiles) {
if (location == null) {
return Collections.emptyList();
}
@ -98,7 +99,7 @@ class ConfigDataLocationResolvers { @@ -98,7 +99,7 @@ class ConfigDataLocationResolvers {
}
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolver<?> resolver,
ConfigDataLocationResolverContext context, ConfigDataLocation location, Profiles profiles) {
ConfigDataLocationResolverContext context, ConfigDataLocation location, @Nullable Profiles profiles) {
List<ConfigDataResolutionResult> resolved = resolve(location, false, () -> resolver.resolve(context, location));
if (profiles == null) {
return resolved;
@ -119,7 +120,7 @@ class ConfigDataLocationResolvers { @@ -119,7 +120,7 @@ class ConfigDataLocationResolvers {
}
@SuppressWarnings("unchecked")
private <T> List<T> nonNullList(List<? extends T> list) {
private <T> List<T> nonNullList(@Nullable List<? extends T> list) {
return (list != null) ? (List<T>) list : Collections.emptyList();
}

11
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationRuntimeHints.java

@ -22,6 +22,7 @@ import java.util.List; @@ -22,6 +22,7 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@ -41,7 +42,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar { @@ -41,7 +42,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
private static final Log logger = LogFactory.getLog(ConfigDataLocationRuntimeHints.class);
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
List<String> fileNames = getFileNames(classLoader);
List<String> locations = getLocations(classLoader);
List<String> extensions = getExtensions(classLoader);
@ -60,7 +61,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar { @@ -60,7 +61,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
* @param classLoader the classloader to use
* @return the configuration file names
*/
protected List<String> getFileNames(ClassLoader classLoader) {
protected List<String> getFileNames(@Nullable ClassLoader classLoader) {
return Arrays.asList(StandardConfigDataLocationResolver.DEFAULT_CONFIG_NAMES);
}
@ -70,7 +71,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar { @@ -70,7 +71,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
* @param classLoader the classloader to use
* @return the configuration file locations
*/
protected List<String> getLocations(ClassLoader classLoader) {
protected List<String> getLocations(@Nullable ClassLoader classLoader) {
List<String> classpathLocations = new ArrayList<>();
for (ConfigDataLocation candidate : ConfigDataEnvironment.DEFAULT_SEARCH_LOCATIONS) {
for (ConfigDataLocation configDataLocation : candidate.split()) {
@ -89,7 +90,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar { @@ -89,7 +90,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
* @param classLoader the classloader to use
* @return the configuration file extensions
*/
protected List<String> getExtensions(ClassLoader classLoader) {
protected List<String> getExtensions(@Nullable ClassLoader classLoader) {
List<String> extensions = new ArrayList<>();
List<PropertySourceLoader> propertySourceLoaders = getSpringFactoriesLoader(classLoader)
.load(PropertySourceLoader.class);
@ -104,7 +105,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar { @@ -104,7 +105,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
return extensions;
}
protected SpringFactoriesLoader getSpringFactoriesLoader(ClassLoader classLoader) {
protected SpringFactoriesLoader getSpringFactoriesLoader(@Nullable ClassLoader classLoader) {
return SpringFactoriesLoader.forDefaultResourceLocation(classLoader);
}

4
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataNotFoundException.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.origin.OriginProvider;
/**
@ -31,7 +33,7 @@ public abstract class ConfigDataNotFoundException extends ConfigDataException im @@ -31,7 +33,7 @@ public abstract class ConfigDataNotFoundException extends ConfigDataException im
* @param message the exception message
* @param cause the exception cause
*/
ConfigDataNotFoundException(String message, Throwable cause) {
ConfigDataNotFoundException(String message, @Nullable Throwable cause) {
super(message, cause);
}

4
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataNotFoundFailureAnalyzer.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.origin.Origin;
@ -48,7 +50,7 @@ class ConfigDataNotFoundFailureAnalyzer extends AbstractFailureAnalyzer<ConfigDa @@ -48,7 +50,7 @@ class ConfigDataNotFoundFailureAnalyzer extends AbstractFailureAnalyzer<ConfigDa
return new FailureAnalysis(message, action.toString(), cause);
}
private ConfigDataLocation getLocation(ConfigDataNotFoundException cause) {
private @Nullable ConfigDataLocation getLocation(ConfigDataNotFoundException cause) {
if (cause instanceof ConfigDataLocationNotFoundException locationNotFoundException) {
return locationNotFoundException.getLocation();
}

18
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataProperties.java

@ -20,6 +20,8 @@ import java.util.Collections; @@ -20,6 +20,8 @@ import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
@ -42,14 +44,14 @@ class ConfigDataProperties { @@ -42,14 +44,14 @@ class ConfigDataProperties {
private final List<ConfigDataLocation> imports;
private final Activate activate;
private final @Nullable Activate activate;
/**
* Create a new {@link ConfigDataProperties} instance.
* @param imports the imports requested
* @param activate the activate properties
*/
ConfigDataProperties(@Name("import") List<ConfigDataLocation> imports, Activate activate) {
ConfigDataProperties(@Nullable @Name("import") List<ConfigDataLocation> imports, @Nullable Activate activate) {
this.imports = (imports != null) ? imports : Collections.emptyList();
this.activate = activate;
}
@ -68,7 +70,7 @@ class ConfigDataProperties { @@ -68,7 +70,7 @@ class ConfigDataProperties {
* @param activationContext the activation context
* @return {@code true} if the config data property source is active
*/
boolean isActive(ConfigDataActivationContext activationContext) {
boolean isActive(@Nullable ConfigDataActivationContext activationContext) {
return this.activate == null || this.activate.isActive(activationContext);
}
@ -86,7 +88,7 @@ class ConfigDataProperties { @@ -86,7 +88,7 @@ class ConfigDataProperties {
* @param binder the binder used to bind the properties
* @return a {@link ConfigDataProperties} instance or {@code null}
*/
static ConfigDataProperties get(Binder binder) {
static @Nullable ConfigDataProperties get(Binder binder) {
return binder.bind(NAME, BINDABLE_PROPERTIES, new ConfigDataLocationBindHandler()).orElse(null);
}
@ -95,7 +97,7 @@ class ConfigDataProperties { @@ -95,7 +97,7 @@ class ConfigDataProperties {
*/
static class Activate {
private final CloudPlatform onCloudPlatform;
private final @Nullable CloudPlatform onCloudPlatform;
private final String[] onProfile;
@ -104,7 +106,7 @@ class ConfigDataProperties { @@ -104,7 +106,7 @@ class ConfigDataProperties {
* @param onCloudPlatform the cloud platform required for activation
* @param onProfile the profile expression required for activation
*/
Activate(CloudPlatform onCloudPlatform, String[] onProfile) {
Activate(@Nullable CloudPlatform onCloudPlatform, String[] onProfile) {
this.onProfile = onProfile;
this.onCloudPlatform = onCloudPlatform;
}
@ -115,7 +117,7 @@ class ConfigDataProperties { @@ -115,7 +117,7 @@ class ConfigDataProperties {
* @param activationContext the activation context
* @return {@code true} if the config data property source is active
*/
boolean isActive(ConfigDataActivationContext activationContext) {
boolean isActive(@Nullable ConfigDataActivationContext activationContext) {
if (activationContext == null) {
return false;
}
@ -129,7 +131,7 @@ class ConfigDataProperties { @@ -129,7 +131,7 @@ class ConfigDataProperties {
return this.onCloudPlatform == null || this.onCloudPlatform == cloudPlatform;
}
private boolean isActive(Profiles profiles) {
private boolean isActive(@Nullable Profiles profiles) {
return ObjectUtils.isEmpty(this.onProfile)
|| (profiles != null && matchesActiveProfiles(profiles::isAccepted));
}

13
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataPropertiesRuntimeHints.java

@ -16,10 +16,15 @@ @@ -16,10 +16,15 @@
package org.springframework.boot.context.config;
import java.lang.reflect.Method;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrar;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
@ -30,11 +35,11 @@ import org.springframework.util.ReflectionUtils; @@ -30,11 +35,11 @@ import org.springframework.util.ReflectionUtils;
class ConfigDataPropertiesRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
BindableRuntimeHintsRegistrar.forTypes(ConfigDataProperties.class).registerHints(hints);
hints.reflection()
.registerMethod(ReflectionUtils.findMethod(ConfigDataLocation.class, "of", String.class),
ExecutableMode.INVOKE);
Method method = ReflectionUtils.findMethod(ConfigDataLocation.class, "of", String.class);
Assert.state(method != null, "'method' must not be null");
hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
}
}

18
core/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataResourceNotFoundException.java

@ -20,6 +20,8 @@ import java.io.File; @@ -20,6 +20,8 @@ import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.origin.Origin;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
@ -35,7 +37,7 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep @@ -35,7 +37,7 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep
private final ConfigDataResource resource;
private final ConfigDataLocation location;
private final @Nullable ConfigDataLocation location;
/**
* Create a new {@link ConfigDataResourceNotFoundException} instance.
@ -50,12 +52,12 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep @@ -50,12 +52,12 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep
* @param resource the resource that could not be found
* @param cause the exception cause
*/
public ConfigDataResourceNotFoundException(ConfigDataResource resource, Throwable cause) {
public ConfigDataResourceNotFoundException(ConfigDataResource resource, @Nullable Throwable cause) {
this(resource, null, cause);
}
private ConfigDataResourceNotFoundException(ConfigDataResource resource, ConfigDataLocation location,
Throwable cause) {
private ConfigDataResourceNotFoundException(ConfigDataResource resource, @Nullable ConfigDataLocation location,
@Nullable Throwable cause) {
super(getMessage(resource, location), cause);
Assert.notNull(resource, "'resource' must not be null");
this.resource = resource;
@ -74,12 +76,12 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep @@ -74,12 +76,12 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep
* Return the original location that was resolved to determine the resource.
* @return the location or {@code null} if no location is available
*/
public ConfigDataLocation getLocation() {
public @Nullable ConfigDataLocation getLocation() {
return this.location;
}
@Override
public Origin getOrigin() {
public @Nullable Origin getOrigin() {
return Origin.from(this.location);
}
@ -97,11 +99,11 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep @@ -97,11 +99,11 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep
return new ConfigDataResourceNotFoundException(this.resource, location, getCause());
}
private static String getMessage(ConfigDataResource resource, ConfigDataLocation location) {
private static String getMessage(ConfigDataResource resource, @Nullable ConfigDataLocation location) {
return String.format("Config data %s cannot be found", getReferenceDescription(resource, location));
}
private static String getReferenceDescription(ConfigDataResource resource, ConfigDataLocation location) {
private static String getReferenceDescription(ConfigDataResource resource, @Nullable ConfigDataLocation location) {
String description = String.format("resource '%s'", resource);
if (location != null) {
description += String.format(" via location '%s'", location);

6
core/spring-boot/src/main/java/org/springframework/boot/context/config/FileExtensionHint.java

@ -19,6 +19,8 @@ package org.springframework.boot.context.config; @@ -19,6 +19,8 @@ package org.springframework.boot.context.config;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
/**
* User-provided hint for an otherwise missing file extension.
*
@ -30,9 +32,9 @@ final class FileExtensionHint { @@ -30,9 +32,9 @@ final class FileExtensionHint {
private static final FileExtensionHint NONE = new FileExtensionHint(null);
private final Matcher matcher;
private final @Nullable Matcher matcher;
private FileExtensionHint(Matcher matcher) {
private FileExtensionHint(@Nullable Matcher matcher) {
this.matcher = matcher;
}

20
core/spring-boot/src/main/java/org/springframework/boot/context/config/InactiveConfigDataAccessException.java

@ -16,11 +16,14 @@ @@ -16,11 +16,14 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.origin.Origin;
import org.springframework.core.env.PropertySource;
import org.springframework.util.Assert;
/**
* Exception thrown when an attempt is made to resolve a property against an inactive
@ -35,11 +38,11 @@ public class InactiveConfigDataAccessException extends ConfigDataException { @@ -35,11 +38,11 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
private final PropertySource<?> propertySource;
private final ConfigDataResource location;
private final @Nullable ConfigDataResource location;
private final String propertyName;
private final Origin origin;
private final @Nullable Origin origin;
/**
* Create a new {@link InactiveConfigDataAccessException} instance.
@ -49,8 +52,8 @@ public class InactiveConfigDataAccessException extends ConfigDataException { @@ -49,8 +52,8 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
* @param propertyName the name of the property
* @param origin the origin or the property or {@code null}
*/
InactiveConfigDataAccessException(PropertySource<?> propertySource, ConfigDataResource location,
String propertyName, Origin origin) {
InactiveConfigDataAccessException(PropertySource<?> propertySource, @Nullable ConfigDataResource location,
String propertyName, @Nullable Origin origin) {
super(getMessage(propertySource, location, propertyName, origin), null);
this.propertySource = propertySource;
this.location = location;
@ -58,8 +61,8 @@ public class InactiveConfigDataAccessException extends ConfigDataException { @@ -58,8 +61,8 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
this.origin = origin;
}
private static String getMessage(PropertySource<?> propertySource, ConfigDataResource location, String propertyName,
Origin origin) {
private static String getMessage(PropertySource<?> propertySource, @Nullable ConfigDataResource location,
String propertyName, @Nullable Origin origin) {
StringBuilder message = new StringBuilder("Inactive property source '");
message.append(propertySource.getName());
if (location != null) {
@ -90,7 +93,7 @@ public class InactiveConfigDataAccessException extends ConfigDataException { @@ -90,7 +93,7 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
* source was not loaded from {@link ConfigData}.
* @return the config data location or {@code null}
*/
public ConfigDataResource getLocation() {
public @Nullable ConfigDataResource getLocation() {
return this.location;
}
@ -106,7 +109,7 @@ public class InactiveConfigDataAccessException extends ConfigDataException { @@ -106,7 +109,7 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
* Return the origin or the property or {@code null}.
* @return the property origin
*/
public Origin getOrigin() {
public @Nullable Origin getOrigin() {
return this.origin;
}
@ -122,6 +125,7 @@ public class InactiveConfigDataAccessException extends ConfigDataException { @@ -122,6 +125,7 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
if (property != null) {
PropertySource<?> propertySource = contributor.getPropertySource();
ConfigDataResource location = contributor.getResource();
Assert.state(propertySource != null, "'propertySource' must not be null");
throw new InactiveConfigDataAccessException(propertySource, location, name.toString(),
property.getOrigin());
}

14
core/spring-boot/src/main/java/org/springframework/boot/context/config/InvalidConfigDataPropertyException.java

@ -22,6 +22,8 @@ import java.util.LinkedHashSet; @@ -22,6 +22,8 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
@ -60,12 +62,12 @@ public class InvalidConfigDataPropertyException extends ConfigDataException { @@ -60,12 +62,12 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
private final ConfigurationProperty property;
private final ConfigurationPropertyName replacement;
private final @Nullable ConfigurationPropertyName replacement;
private final ConfigDataResource location;
private final @Nullable ConfigDataResource location;
InvalidConfigDataPropertyException(ConfigurationProperty property, boolean profileSpecific,
ConfigurationPropertyName replacement, ConfigDataResource location) {
@Nullable ConfigurationPropertyName replacement, @Nullable ConfigDataResource location) {
super(getMessage(property, profileSpecific, replacement, location), null);
this.property = property;
this.replacement = replacement;
@ -85,7 +87,7 @@ public class InvalidConfigDataPropertyException extends ConfigDataException { @@ -85,7 +87,7 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
* the source was not loaded from {@link ConfigData}.
* @return the config data location or {@code null}
*/
public ConfigDataResource getLocation() {
public @Nullable ConfigDataResource getLocation() {
return this.location;
}
@ -94,7 +96,7 @@ public class InvalidConfigDataPropertyException extends ConfigDataException { @@ -94,7 +96,7 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
* replacement is available.
* @return the replacement property name
*/
public ConfigurationPropertyName getReplacement() {
public @Nullable ConfigurationPropertyName getReplacement() {
return this.replacement;
}
@ -126,7 +128,7 @@ public class InvalidConfigDataPropertyException extends ConfigDataException { @@ -126,7 +128,7 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
}
private static String getMessage(ConfigurationProperty property, boolean profileSpecific,
ConfigurationPropertyName replacement, ConfigDataResource location) {
@Nullable ConfigurationPropertyName replacement, @Nullable ConfigDataResource location) {
StringBuilder message = new StringBuilder("Property '");
message.append(property.getName());
if (location != null) {

14
core/spring-boot/src/main/java/org/springframework/boot/context/config/Profiles.java

@ -28,6 +28,8 @@ import java.util.List; @@ -28,6 +28,8 @@ import java.util.List;
import java.util.Set;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
@ -77,7 +79,7 @@ public class Profiles implements Iterable<String> { @@ -77,7 +79,7 @@ public class Profiles implements Iterable<String> {
* @param binder the binder for profile properties
* @param additionalProfiles any additional active profiles
*/
Profiles(Environment environment, Binder binder, Collection<String> additionalProfiles) {
Profiles(Environment environment, Binder binder, @Nullable Collection<String> additionalProfiles) {
ProfilesValidator validator = ProfilesValidator.get(binder);
if (additionalProfiles != null) {
validator.validate(additionalProfiles, () -> "Invalid profile property value found in additional profiles");
@ -89,7 +91,7 @@ public class Profiles implements Iterable<String> { @@ -89,7 +91,7 @@ public class Profiles implements Iterable<String> {
}
private List<String> getActivatedProfiles(Environment environment, Binder binder, ProfilesValidator validator,
Collection<String> additionalProfiles) {
@Nullable Collection<String> additionalProfiles) {
return asUniqueItemList(getProfiles(environment, binder, validator, Type.ACTIVE), additionalProfiles);
}
@ -117,7 +119,7 @@ public class Profiles implements Iterable<String> { @@ -117,7 +119,7 @@ public class Profiles implements Iterable<String> {
return boundProfiles.orElse(type.getDefaultValue());
}
private boolean hasProgrammaticallySetProfiles(Type type, String environmentPropertyValue,
private boolean hasProgrammaticallySetProfiles(Type type, @Nullable String environmentPropertyValue,
Set<String> environmentPropertyProfiles, Set<String> environmentProfiles) {
if (!StringUtils.hasLength(environmentPropertyValue)) {
return !type.getDefaultValue().equals(environmentProfiles);
@ -134,7 +136,7 @@ public class Profiles implements Iterable<String> { @@ -134,7 +136,7 @@ public class Profiles implements Iterable<String> {
return result;
}
private List<String> expandProfiles(List<String> profiles) {
private List<String> expandProfiles(@Nullable List<String> profiles) {
Deque<String> stack = new ArrayDeque<>();
asReversedList(profiles).forEach(stack::push);
Set<String> expandedProfiles = new LinkedHashSet<>();
@ -147,7 +149,7 @@ public class Profiles implements Iterable<String> { @@ -147,7 +149,7 @@ public class Profiles implements Iterable<String> {
return asUniqueItemList(expandedProfiles);
}
private List<String> asReversedList(List<String> list) {
private List<String> asReversedList(@Nullable List<String> list) {
if (CollectionUtils.isEmpty(list)) {
return Collections.emptyList();
}
@ -160,7 +162,7 @@ public class Profiles implements Iterable<String> { @@ -160,7 +162,7 @@ public class Profiles implements Iterable<String> {
return asUniqueItemList(profiles, null);
}
private List<String> asUniqueItemList(Collection<String> profiles, Collection<String> additional) {
private List<String> asUniqueItemList(Collection<String> profiles, @Nullable Collection<String> additional) {
LinkedHashSet<String> uniqueItems = new LinkedHashSet<>();
if (!CollectionUtils.isEmpty(additional)) {
uniqueItems.addAll(additional);

4
core/spring-boot/src/main/java/org/springframework/boot/context/config/ProfilesValidator.java

@ -22,6 +22,8 @@ import java.util.Map; @@ -22,6 +22,8 @@ import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.bind.BindContext;
import org.springframework.boot.context.properties.bind.BindHandler;
import org.springframework.boot.context.properties.bind.Bindable;
@ -61,7 +63,7 @@ final class ProfilesValidator implements BindHandler { @@ -61,7 +63,7 @@ final class ProfilesValidator implements BindHandler {
}
}
private void validate(Object value) {
private void validate(@Nullable Object value) {
if (!this.validate) {
return;
}

19
core/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataLocationResolver.java

@ -30,6 +30,7 @@ import java.util.regex.Pattern; @@ -30,6 +30,7 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.config.LocationResourceLoader.ResourceType;
import org.springframework.boot.context.properties.bind.Binder;
@ -67,7 +68,7 @@ public class StandardConfigDataLocationResolver @@ -67,7 +68,7 @@ public class StandardConfigDataLocationResolver
private static final Pattern URL_PREFIX = Pattern.compile("^([a-zA-Z][a-zA-Z0-9*]*?:)(.*$)");
private static final String NO_PROFILE = null;
private static final @Nullable String NO_PROFILE = null;
private final Log logger;
@ -186,7 +187,7 @@ public class StandardConfigDataLocationResolver @@ -186,7 +187,7 @@ public class StandardConfigDataLocationResolver
}
private Set<StandardConfigDataReference> getReferencesForDirectory(ConfigDataLocation configDataLocation,
String directory, String profile) {
String directory, @Nullable String profile) {
Set<StandardConfigDataReference> references = new LinkedHashSet<>();
for (String name : this.configNames) {
Deque<StandardConfigDataReference> referencesForName = getReferencesForConfigName(name, configDataLocation,
@ -197,7 +198,7 @@ public class StandardConfigDataLocationResolver @@ -197,7 +198,7 @@ public class StandardConfigDataLocationResolver
}
private Deque<StandardConfigDataReference> getReferencesForConfigName(String name,
ConfigDataLocation configDataLocation, String directory, String profile) {
ConfigDataLocation configDataLocation, String directory, @Nullable String profile) {
Deque<StandardConfigDataReference> references = new ArrayDeque<>();
for (PropertySourceLoader propertySourceLoader : this.propertySourceLoaders) {
for (String extension : propertySourceLoader.getFileExtensions()) {
@ -212,7 +213,7 @@ public class StandardConfigDataLocationResolver @@ -212,7 +213,7 @@ public class StandardConfigDataLocationResolver
}
private Set<StandardConfigDataReference> getReferencesForFile(ConfigDataLocation configDataLocation, String file,
String profile) {
@Nullable String profile) {
FileExtensionHint fileExtensionHint = FileExtensionHint.from(file);
if (fileExtensionHint.isPresent()) {
file = FileExtensionHint.removeFrom(file) + fileExtensionHint;
@ -242,7 +243,7 @@ public class StandardConfigDataLocationResolver @@ -242,7 +243,7 @@ public class StandardConfigDataLocationResolver
+ "check the location prefix if a different resolver is expected");
}
private String getLoadableFileExtension(PropertySourceLoader loader, String file) {
private @Nullable String getLoadableFileExtension(PropertySourceLoader loader, String file) {
for (String fileExtension : loader.getFileExtensions()) {
if (StringUtils.endsWithIgnoreCase(file, fileExtension)) {
return fileExtension;
@ -285,13 +286,17 @@ public class StandardConfigDataLocationResolver @@ -285,13 +286,17 @@ public class StandardConfigDataLocationResolver
}
private Set<StandardConfigDataResource> resolveNonPatternEmptyDirectories(StandardConfigDataReference reference) {
Resource resource = this.resourceLoader.getResource(reference.getDirectory());
String directory = reference.getDirectory();
Assert.state(directory != null, "'directory' must not be null");
Resource resource = this.resourceLoader.getResource(directory);
return (resource instanceof ClassPathResource || !resource.exists()) ? Collections.emptySet()
: Collections.singleton(new StandardConfigDataResource(reference, resource, true));
}
private Set<StandardConfigDataResource> resolvePatternEmptyDirectories(StandardConfigDataReference reference) {
Resource[] subdirectories = this.resourceLoader.getResources(reference.getDirectory(), ResourceType.DIRECTORY);
String directory = reference.getDirectory();
Assert.state(directory != null, "'directory' must not be null");
Resource[] subdirectories = this.resourceLoader.getResources(directory, ResourceType.DIRECTORY);
ConfigDataLocation location = reference.getConfigDataLocation();
if (!location.isOptional() && ObjectUtils.isEmpty(subdirectories)) {
String message = String.format("Config data location '%s' contains no subdirectories", location);

14
core/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataReference.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.util.StringUtils;
@ -31,9 +33,9 @@ class StandardConfigDataReference { @@ -31,9 +33,9 @@ class StandardConfigDataReference {
private final String resourceLocation;
private final String directory;
private final @Nullable String directory;
private final String profile;
private final @Nullable String profile;
private final PropertySourceLoader propertySourceLoader;
@ -48,8 +50,8 @@ class StandardConfigDataReference { @@ -48,8 +50,8 @@ class StandardConfigDataReference {
* @param propertySourceLoader the property source loader that should be used for this
* reference
*/
StandardConfigDataReference(ConfigDataLocation configDataLocation, String directory, String root, String profile,
String extension, PropertySourceLoader propertySourceLoader) {
StandardConfigDataReference(ConfigDataLocation configDataLocation, @Nullable String directory, String root,
@Nullable String profile, @Nullable String extension, PropertySourceLoader propertySourceLoader) {
this.configDataLocation = configDataLocation;
String profileSuffix = (StringUtils.hasText(profile)) ? "-" + profile : "";
this.resourceLocation = root + profileSuffix + ((extension != null) ? "." + extension : "");
@ -70,11 +72,11 @@ class StandardConfigDataReference { @@ -70,11 +72,11 @@ class StandardConfigDataReference {
return !this.configDataLocation.isOptional() && this.directory != null;
}
String getDirectory() {
@Nullable String getDirectory() {
return this.directory;
}
String getProfile() {
@Nullable String getProfile() {
return this.profile;
}

8
core/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataResource.java

@ -19,6 +19,8 @@ package org.springframework.boot.context.config; @@ -19,6 +19,8 @@ package org.springframework.boot.context.config;
import java.io.File;
import java.io.IOException;
import org.jspecify.annotations.Nullable;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.FileUrlResource;
@ -81,7 +83,7 @@ public class StandardConfigDataResource extends ConfigDataResource { @@ -81,7 +83,7 @@ public class StandardConfigDataResource extends ConfigDataResource {
* @return the profile or {@code null}
* @since 2.4.6
*/
public String getProfile() {
public @Nullable String getProfile() {
return this.reference.getProfile();
}
@ -105,7 +107,7 @@ public class StandardConfigDataResource extends ConfigDataResource { @@ -105,7 +107,7 @@ public class StandardConfigDataResource extends ConfigDataResource {
return ours.equals(other) || isSameFile(getUnderlyingFile(ours), getUnderlyingFile(other));
}
private boolean isSameFile(File ours, File other) {
private boolean isSameFile(@Nullable File ours, @Nullable File other) {
return (ours != null) && ours.equals(other);
}
@ -128,7 +130,7 @@ public class StandardConfigDataResource extends ConfigDataResource { @@ -128,7 +130,7 @@ public class StandardConfigDataResource extends ConfigDataResource {
return this.resource.toString();
}
private File getUnderlyingFile(Resource resource) {
private @Nullable File getUnderlyingFile(Resource resource) {
try {
if (resource instanceof ClassPathResource || resource instanceof FileSystemResource
|| resource instanceof FileUrlResource) {

6
core/spring-boot/src/main/java/org/springframework/boot/context/config/SystemEnvironmentConfigDataLocationResolver.java

@ -20,6 +20,8 @@ import java.util.Collections; @@ -20,6 +20,8 @@ import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.io.support.SpringFactoriesLoader;
@ -38,7 +40,7 @@ class SystemEnvironmentConfigDataLocationResolver @@ -38,7 +40,7 @@ class SystemEnvironmentConfigDataLocationResolver
private final List<PropertySourceLoader> loaders;
private final Function<String, String> environment;
private final Function<String, @Nullable String> environment;
SystemEnvironmentConfigDataLocationResolver() {
this.loaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());
@ -46,7 +48,7 @@ class SystemEnvironmentConfigDataLocationResolver @@ -46,7 +48,7 @@ class SystemEnvironmentConfigDataLocationResolver
}
SystemEnvironmentConfigDataLocationResolver(List<PropertySourceLoader> loaders,
Function<String, String> environment) {
Function<String, @Nullable String> environment) {
this.loaders = loaders;
this.environment = environment;
}

8
core/spring-boot/src/main/java/org/springframework/boot/context/config/SystemEnvironmentConfigDataResource.java

@ -22,6 +22,8 @@ import java.util.List; @@ -22,6 +22,8 @@ import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ByteArrayResource;
@ -39,10 +41,10 @@ class SystemEnvironmentConfigDataResource extends ConfigDataResource { @@ -39,10 +41,10 @@ class SystemEnvironmentConfigDataResource extends ConfigDataResource {
private final PropertySourceLoader loader;
private final Function<String, String> environment;
private final Function<String, @Nullable String> environment;
SystemEnvironmentConfigDataResource(String variableName, PropertySourceLoader loader,
Function<String, String> environment) {
Function<String, @Nullable String> environment) {
this.variableName = variableName;
this.loader = loader;
this.environment = environment;
@ -56,7 +58,7 @@ class SystemEnvironmentConfigDataResource extends ConfigDataResource { @@ -56,7 +58,7 @@ class SystemEnvironmentConfigDataResource extends ConfigDataResource {
return this.loader;
}
List<PropertySource<?>> load() throws IOException {
@Nullable List<PropertySource<?>> load() throws IOException {
String content = this.environment.apply(this.variableName);
return (content != null) ? this.loader.load(StringUtils.capitalize(toString()), asResource(content)) : null;
}

3
core/spring-boot/src/main/java/org/springframework/boot/context/config/package-info.java

@ -20,4 +20,7 @@ @@ -20,4 +20,7 @@
*
* @see org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor
*/
@NullMarked
package org.springframework.boot.context.config;
import org.jspecify.annotations.NullMarked;

12
core/spring-boot/src/main/java/org/springframework/boot/context/event/ApplicationFailedEvent.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.event;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
@ -29,7 +31,7 @@ import org.springframework.context.ConfigurableApplicationContext; @@ -29,7 +31,7 @@ import org.springframework.context.ConfigurableApplicationContext;
@SuppressWarnings("serial")
public class ApplicationFailedEvent extends SpringApplicationEvent {
private final ConfigurableApplicationContext context;
private final @Nullable ConfigurableApplicationContext context;
private final Throwable exception;
@ -40,8 +42,8 @@ public class ApplicationFailedEvent extends SpringApplicationEvent { @@ -40,8 +42,8 @@ public class ApplicationFailedEvent extends SpringApplicationEvent {
* @param context the context that was being created (maybe null)
* @param exception the exception that caused the error
*/
public ApplicationFailedEvent(SpringApplication application, String[] args, ConfigurableApplicationContext context,
Throwable exception) {
public ApplicationFailedEvent(SpringApplication application, String[] args,
@Nullable ConfigurableApplicationContext context, Throwable exception) {
super(application, args);
this.context = context;
this.exception = exception;
@ -49,9 +51,9 @@ public class ApplicationFailedEvent extends SpringApplicationEvent { @@ -49,9 +51,9 @@ public class ApplicationFailedEvent extends SpringApplicationEvent {
/**
* Return the application context.
* @return the context
* @return the context or {@code null}
*/
public ConfigurableApplicationContext getApplicationContext() {
public @Nullable ConfigurableApplicationContext getApplicationContext() {
return this.context;
}

8
core/spring-boot/src/main/java/org/springframework/boot/context/event/ApplicationReadyEvent.java

@ -18,6 +18,8 @@ package org.springframework.boot.context.event; @@ -18,6 +18,8 @@ package org.springframework.boot.context.event;
import java.time.Duration;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
@ -37,7 +39,7 @@ public class ApplicationReadyEvent extends SpringApplicationEvent { @@ -37,7 +39,7 @@ public class ApplicationReadyEvent extends SpringApplicationEvent {
private final ConfigurableApplicationContext context;
private final Duration timeTaken;
private final @Nullable Duration timeTaken;
/**
* Create a new {@link ApplicationReadyEvent} instance.
@ -48,7 +50,7 @@ public class ApplicationReadyEvent extends SpringApplicationEvent { @@ -48,7 +50,7 @@ public class ApplicationReadyEvent extends SpringApplicationEvent {
* @since 2.6.0
*/
public ApplicationReadyEvent(SpringApplication application, String[] args, ConfigurableApplicationContext context,
Duration timeTaken) {
@Nullable Duration timeTaken) {
super(application, args);
this.context = context;
this.timeTaken = timeTaken;
@ -68,7 +70,7 @@ public class ApplicationReadyEvent extends SpringApplicationEvent { @@ -68,7 +70,7 @@ public class ApplicationReadyEvent extends SpringApplicationEvent {
* @return the time taken to be ready to service requests
* @since 2.6.0
*/
public Duration getTimeTaken() {
public @Nullable Duration getTimeTaken() {
return this.timeTaken;
}

8
core/spring-boot/src/main/java/org/springframework/boot/context/event/ApplicationStartedEvent.java

@ -18,6 +18,8 @@ package org.springframework.boot.context.event; @@ -18,6 +18,8 @@ package org.springframework.boot.context.event;
import java.time.Duration;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
@ -36,7 +38,7 @@ public class ApplicationStartedEvent extends SpringApplicationEvent { @@ -36,7 +38,7 @@ public class ApplicationStartedEvent extends SpringApplicationEvent {
private final ConfigurableApplicationContext context;
private final Duration timeTaken;
private final @Nullable Duration timeTaken;
/**
* Create a new {@link ApplicationStartedEvent} instance.
@ -47,7 +49,7 @@ public class ApplicationStartedEvent extends SpringApplicationEvent { @@ -47,7 +49,7 @@ public class ApplicationStartedEvent extends SpringApplicationEvent {
* @since 2.6.0
*/
public ApplicationStartedEvent(SpringApplication application, String[] args, ConfigurableApplicationContext context,
Duration timeTaken) {
@Nullable Duration timeTaken) {
super(application, args);
this.context = context;
this.timeTaken = timeTaken;
@ -66,7 +68,7 @@ public class ApplicationStartedEvent extends SpringApplicationEvent { @@ -66,7 +68,7 @@ public class ApplicationStartedEvent extends SpringApplicationEvent {
* @return the startup time
* @since 2.6.0
*/
public Duration getTimeTaken() {
public @Nullable Duration getTimeTaken() {
return this.timeTaken;
}

7
core/spring-boot/src/main/java/org/springframework/boot/context/event/EventPublishingRunListener.java

@ -20,6 +20,7 @@ import java.time.Duration; @@ -20,6 +20,7 @@ import java.time.Duration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
@ -99,19 +100,19 @@ class EventPublishingRunListener implements SpringApplicationRunListener, Ordere @@ -99,19 +100,19 @@ class EventPublishingRunListener implements SpringApplicationRunListener, Ordere
}
@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
public void started(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context, timeTaken));
AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
}
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
public void ready(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context, timeTaken));
AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
public void failed(@Nullable ConfigurableApplicationContext context, Throwable exception) {
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
if (context != null && context.isActive()) {
// Listeners have been registered to the application context so we should

3
core/spring-boot/src/main/java/org/springframework/boot/context/event/package-info.java

@ -18,4 +18,7 @@ @@ -18,4 +18,7 @@
* {@link org.springframework.context.ApplicationEvent ApplicationEvents} triggered by
* Spring Boot.
*/
@NullMarked
package org.springframework.boot.context.event;
import org.jspecify.annotations.NullMarked;

21
core/spring-boot/src/main/java/org/springframework/boot/context/logging/LoggingApplicationListener.java

@ -25,6 +25,7 @@ import java.util.function.BiConsumer; @@ -25,6 +25,7 @@ import java.util.function.BiConsumer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.SpringApplication;
@ -54,6 +55,7 @@ import org.springframework.core.ResolvableType; @@ -54,6 +55,7 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.log.LogMessage;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
@ -181,17 +183,17 @@ public class LoggingApplicationListener implements GenericApplicationListener { @@ -181,17 +183,17 @@ public class LoggingApplicationListener implements GenericApplicationListener {
private final Log logger = LogFactory.getLog(getClass());
private LoggingSystem loggingSystem;
private @Nullable LoggingSystem loggingSystem;
private LogFile logFile;
private @Nullable LogFile logFile;
private LoggerGroups loggerGroups;
private @Nullable LoggerGroups loggerGroups;
private int order = DEFAULT_ORDER;
private boolean parseArgs = true;
private LogLevel springBootLogging = null;
private @Nullable LogLevel springBootLogging = null;
@Override
public boolean supportsEventType(ResolvableType resolvableType) {
@ -199,11 +201,11 @@ public class LoggingApplicationListener implements GenericApplicationListener { @@ -199,11 +201,11 @@ public class LoggingApplicationListener implements GenericApplicationListener {
}
@Override
public boolean supportsSourceType(Class<?> sourceType) {
public boolean supportsSourceType(@Nullable Class<?> sourceType) {
return isAssignableFrom(sourceType, SOURCE_TYPES);
}
private boolean isAssignableFrom(Class<?> type, Class<?>... supportedTypes) {
private boolean isAssignableFrom(@Nullable Class<?> type, Class<?>... supportedTypes) {
if (type != null) {
for (Class<?> supportedType : supportedTypes) {
if (supportedType.isAssignableFrom(type)) {
@ -250,6 +252,7 @@ public class LoggingApplicationListener implements GenericApplicationListener { @@ -250,6 +252,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
if (!beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) {
Assert.state(this.loggingSystem != null, "loggingSystem is not set");
beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME, this.loggingSystem);
}
if (this.logFile != null && !beanFactory.containsBean(LOG_FILE_BEAN_NAME)) {
@ -295,6 +298,7 @@ public class LoggingApplicationListener implements GenericApplicationListener { @@ -295,6 +298,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
}
this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);
initializeEarlyLoggingLevel(environment);
Assert.state(this.loggingSystem != null, "loggingSystem is not set");
initializeSystem(environment, this.loggingSystem, this.logFile);
initializeFinalLoggingLevels(environment, this.loggingSystem);
registerShutdownHookIfNecessary(environment, this.loggingSystem);
@ -321,7 +325,8 @@ public class LoggingApplicationListener implements GenericApplicationListener { @@ -321,7 +325,8 @@ public class LoggingApplicationListener implements GenericApplicationListener {
return (value != null && !value.equals("false"));
}
private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system, LogFile logFile) {
private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system,
@Nullable LogFile logFile) {
String logConfig = environment.getProperty(CONFIG_PROPERTY);
if (StringUtils.hasLength(logConfig)) {
logConfig = logConfig.strip();
@ -348,7 +353,7 @@ public class LoggingApplicationListener implements GenericApplicationListener { @@ -348,7 +353,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
}
}
private boolean ignoreLogConfig(String logConfig) {
private boolean ignoreLogConfig(@Nullable String logConfig) {
return !StringUtils.hasLength(logConfig) || logConfig.startsWith("-D");
}

3
core/spring-boot/src/main/java/org/springframework/boot/context/logging/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Logging integration with Spring's Application Context.
*/
@NullMarked
package org.springframework.boot.context.logging;
import org.jspecify.annotations.NullMarked;

10
core/spring-boot/src/main/java/org/springframework/boot/context/metrics/buffering/BufferedStartupStep.java

@ -24,6 +24,8 @@ import java.util.concurrent.atomic.AtomicBoolean; @@ -24,6 +24,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.core.metrics.StartupStep;
import org.springframework.util.Assert;
@ -41,7 +43,7 @@ class BufferedStartupStep implements StartupStep { @@ -41,7 +43,7 @@ class BufferedStartupStep implements StartupStep {
private final long id;
private final BufferedStartupStep parent;
private final @Nullable BufferedStartupStep parent;
private final List<Tag> tags = new ArrayList<>();
@ -51,7 +53,7 @@ class BufferedStartupStep implements StartupStep { @@ -51,7 +53,7 @@ class BufferedStartupStep implements StartupStep {
private final AtomicBoolean ended = new AtomicBoolean();
BufferedStartupStep(BufferedStartupStep parent, String name, long id, Instant startTime,
BufferedStartupStep(@Nullable BufferedStartupStep parent, String name, long id, Instant startTime,
Consumer<BufferedStartupStep> recorder) {
this.parent = parent;
this.name = name;
@ -60,7 +62,7 @@ class BufferedStartupStep implements StartupStep { @@ -60,7 +62,7 @@ class BufferedStartupStep implements StartupStep {
this.recorder = recorder;
}
BufferedStartupStep getParent() {
@Nullable BufferedStartupStep getParent() {
return this.parent;
}
@ -79,7 +81,7 @@ class BufferedStartupStep implements StartupStep { @@ -79,7 +81,7 @@ class BufferedStartupStep implements StartupStep {
}
@Override
public Long getParentId() {
public @Nullable Long getParentId() {
return (this.parent != null) ? this.parent.getId() : null;
}

4
core/spring-boot/src/main/java/org/springframework/boot/context/metrics/buffering/BufferingApplicationStartup.java

@ -26,6 +26,8 @@ import java.util.concurrent.atomic.AtomicInteger; @@ -26,6 +26,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.metrics.buffering.StartupTimeline.TimelineEvent;
import org.springframework.core.metrics.ApplicationStartup;
import org.springframework.core.metrics.StartupStep;
@ -133,7 +135,7 @@ public class BufferingApplicationStartup implements ApplicationStartup { @@ -133,7 +135,7 @@ public class BufferingApplicationStartup implements ApplicationStartup {
}
}
private BufferedStartupStep getLatestActive(BufferedStartupStep step) {
private @Nullable BufferedStartupStep getLatestActive(@Nullable BufferedStartupStep step) {
while (step != null && step.isEnded()) {
step = step.getParent();
}

3
core/spring-boot/src/main/java/org/springframework/boot/context/metrics/buffering/package-info.java

@ -18,4 +18,7 @@ @@ -18,4 +18,7 @@
* {@link org.springframework.core.metrics.ApplicationStartup} implementation for
* buffering steps and measuring their processing time.
*/
@NullMarked
package org.springframework.boot.context.metrics.buffering;
import org.jspecify.annotations.NullMarked;

3
core/spring-boot/src/main/java/org/springframework/boot/context/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Classes related to Spring's {@link org.springframework.context.ApplicationContext}.
*/
@NullMarked
package org.springframework.boot.context;
import org.jspecify.annotations.NullMarked;

10
core/spring-boot/src/main/java/org/springframework/boot/context/properties/BindMethodAttribute.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.properties;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.context.properties.bind.BindMethod;
@ -36,21 +38,21 @@ final class BindMethodAttribute { @@ -36,21 +38,21 @@ final class BindMethodAttribute {
private BindMethodAttribute() {
}
static BindMethod get(ApplicationContext applicationContext, String beanName) {
static @Nullable BindMethod get(ApplicationContext applicationContext, String beanName) {
return (applicationContext instanceof ConfigurableApplicationContext configurableApplicationContext)
? get(configurableApplicationContext.getBeanFactory(), beanName) : null;
}
static BindMethod get(ConfigurableListableBeanFactory beanFactory, String beanName) {
static @Nullable BindMethod get(ConfigurableListableBeanFactory beanFactory, String beanName) {
return (!beanFactory.containsBeanDefinition(beanName)) ? null : get(beanFactory.getBeanDefinition(beanName));
}
static BindMethod get(BeanDefinitionRegistry beanDefinitionRegistry, String beanName) {
static @Nullable BindMethod get(BeanDefinitionRegistry beanDefinitionRegistry, String beanName) {
return (!beanDefinitionRegistry.containsBeanDefinition(beanName)) ? null
: get(beanDefinitionRegistry.getBeanDefinition(beanName));
}
static BindMethod get(AttributeAccessor attributes) {
static @Nullable BindMethod get(AttributeAccessor attributes) {
return (BindMethod) attributes.getAttribute(NAME);
}

6
core/spring-boot/src/main/java/org/springframework/boot/context/properties/BoundConfigurationProperties.java

@ -20,6 +20,8 @@ import java.util.Collections; @@ -20,6 +20,8 @@ import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@ -53,7 +55,7 @@ public class BoundConfigurationProperties { @@ -53,7 +55,7 @@ public class BoundConfigurationProperties {
* @param name the property name
* @return the bound property or {@code null}
*/
public ConfigurationProperty get(ConfigurationPropertyName name) {
public @Nullable ConfigurationProperty get(ConfigurationPropertyName name) {
return this.properties.get(name);
}
@ -71,7 +73,7 @@ public class BoundConfigurationProperties { @@ -71,7 +73,7 @@ public class BoundConfigurationProperties {
* @param context the context to search
* @return a {@link BoundConfigurationProperties} or {@code null}
*/
public static BoundConfigurationProperties get(ApplicationContext context) {
public static @Nullable BoundConfigurationProperties get(ApplicationContext context) {
return (!context.containsBeanDefinition(BEAN_NAME)) ? null
: context.getBean(BEAN_NAME, BoundConfigurationProperties.class);
}

45
core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java

@ -24,6 +24,8 @@ import java.util.Iterator; @@ -24,6 +24,8 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
@ -40,6 +42,7 @@ import org.springframework.core.ResolvableType; @@ -40,6 +42,7 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
@ -66,11 +69,11 @@ public final class ConfigurationPropertiesBean { @@ -66,11 +69,11 @@ public final class ConfigurationPropertiesBean {
private final String name;
private final Object instance;
private final @Nullable Object instance;
private final Bindable<?> bindTarget;
private ConfigurationPropertiesBean(String name, Object instance, Bindable<?> bindTarget) {
private ConfigurationPropertiesBean(String name, @Nullable Object instance, Bindable<?> bindTarget) {
this.name = name;
this.instance = instance;
this.bindTarget = bindTarget;
@ -88,7 +91,7 @@ public final class ConfigurationPropertiesBean { @@ -88,7 +91,7 @@ public final class ConfigurationPropertiesBean {
* Return the actual Spring bean instance.
* @return the bean instance
*/
public Object getInstance() {
public @Nullable Object getInstance() {
return this.instance;
}
@ -97,7 +100,9 @@ public final class ConfigurationPropertiesBean { @@ -97,7 +100,9 @@ public final class ConfigurationPropertiesBean {
* @return the bean type
*/
Class<?> getType() {
return this.bindTarget.getType().resolve();
Class<?> resolved = this.bindTarget.getType().resolve();
Assert.state(resolved != null, "'resolved' must not be null");
return resolved;
}
/**
@ -107,7 +112,9 @@ public final class ConfigurationPropertiesBean { @@ -107,7 +112,9 @@ public final class ConfigurationPropertiesBean {
* @return the configuration properties annotation
*/
public ConfigurationProperties getAnnotation() {
return this.bindTarget.getAnnotation(ConfigurationProperties.class);
ConfigurationProperties annotation = this.bindTarget.getAnnotation(ConfigurationProperties.class);
Assert.state(annotation != null, "'annotation' must not be null");
return annotation;
}
/**
@ -193,7 +200,8 @@ public final class ConfigurationPropertiesBean { @@ -193,7 +200,8 @@ public final class ConfigurationPropertiesBean {
* factory method are annotated with
* {@link ConfigurationProperties @ConfigurationProperties}
*/
public static ConfigurationPropertiesBean get(ApplicationContext applicationContext, Object bean, String beanName) {
public static @Nullable ConfigurationPropertiesBean get(ApplicationContext applicationContext, Object bean,
String beanName) {
Method factoryMethod = findFactoryMethod(applicationContext, beanName);
Bindable<Object> bindTarget = createBindTarget(bean, bean.getClass(), factoryMethod);
if (bindTarget == null) {
@ -209,18 +217,19 @@ public final class ConfigurationPropertiesBean { @@ -209,18 +217,19 @@ public final class ConfigurationPropertiesBean {
return create(beanName, bean, bindTarget);
}
private static Method findFactoryMethod(ApplicationContext applicationContext, String beanName) {
private static @Nullable Method findFactoryMethod(ApplicationContext applicationContext, String beanName) {
if (applicationContext instanceof ConfigurableApplicationContext configurableContext) {
return findFactoryMethod(configurableContext, beanName);
}
return null;
}
private static Method findFactoryMethod(ConfigurableApplicationContext applicationContext, String beanName) {
private static @Nullable Method findFactoryMethod(ConfigurableApplicationContext applicationContext,
String beanName) {
return findFactoryMethod(applicationContext.getBeanFactory(), beanName);
}
private static Method findFactoryMethod(ConfigurableListableBeanFactory beanFactory, String beanName) {
private static @Nullable Method findFactoryMethod(ConfigurableListableBeanFactory beanFactory, String beanName) {
if (beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
if (beanDefinition instanceof RootBeanDefinition rootBeanDefinition) {
@ -237,14 +246,16 @@ public final class ConfigurationPropertiesBean { @@ -237,14 +246,16 @@ public final class ConfigurationPropertiesBean {
return create(beanName, null, bindTarget.withBindMethod(VALUE_OBJECT_BIND_METHOD));
}
private static Bindable<Object> createBindTarget(Object bean, Class<?> beanType, Method factoryMethod) {
private static @Nullable Bindable<Object> createBindTarget(@Nullable Object bean, Class<?> beanType,
@Nullable Method factoryMethod) {
ResolvableType type = (factoryMethod != null) ? ResolvableType.forMethodReturnType(factoryMethod)
: ResolvableType.forClass(beanType);
Annotation[] annotations = findAnnotations(bean, beanType, factoryMethod);
return (annotations != null) ? Bindable.of(type).withAnnotations(annotations) : null;
}
private static Annotation[] findAnnotations(Object instance, Class<?> type, Method factory) {
private static Annotation @Nullable [] findAnnotations(@Nullable Object instance, Class<?> type,
@Nullable Method factory) {
ConfigurationProperties annotation = findAnnotation(instance, type, factory, ConfigurationProperties.class);
if (annotation == null) {
return null;
@ -253,8 +264,8 @@ public final class ConfigurationPropertiesBean { @@ -253,8 +264,8 @@ public final class ConfigurationPropertiesBean {
return (validated != null) ? new Annotation[] { annotation, validated } : new Annotation[] { annotation };
}
private static <A extends Annotation> A findAnnotation(Object instance, Class<?> type, Method factory,
Class<A> annotationType) {
private static <A extends Annotation> @Nullable A findAnnotation(@Nullable Object instance, Class<?> type,
@Nullable Method factory, Class<A> annotationType) {
MergedAnnotation<A> annotation = MergedAnnotation.missing();
if (factory != null) {
annotation = findMergedAnnotation(factory, annotationType);
@ -269,13 +280,15 @@ public final class ConfigurationPropertiesBean { @@ -269,13 +280,15 @@ public final class ConfigurationPropertiesBean {
return annotation.isPresent() ? annotation.synthesize() : null;
}
private static <A extends Annotation> MergedAnnotation<A> findMergedAnnotation(AnnotatedElement element,
private static <A extends Annotation> MergedAnnotation<A> findMergedAnnotation(@Nullable AnnotatedElement element,
Class<A> annotationType) {
return (element != null) ? MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY).get(annotationType)
: MergedAnnotation.missing();
}
private static ConfigurationPropertiesBean create(String name, Object instance, Bindable<Object> bindTarget) {
@Contract("_, _, !null -> !null")
private static @Nullable ConfigurationPropertiesBean create(String name, @Nullable Object instance,
@Nullable Bindable<Object> bindTarget) {
return (bindTarget != null) ? new ConfigurationPropertiesBean(name, instance, bindTarget) : null;
}
@ -298,7 +311,7 @@ public final class ConfigurationPropertiesBean { @@ -298,7 +311,7 @@ public final class ConfigurationPropertiesBean {
}
private static org.springframework.boot.context.properties.bind.BindMethod deduceBindMethod(
Constructor<?> bindConstructor) {
@Nullable Constructor<?> bindConstructor) {
return (bindConstructor != null) ? VALUE_OBJECT_BIND_METHOD : JAVA_BEAN_BIND_METHOD;
}

4
core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanFactoryInitializationAotProcessor.java

@ -19,6 +19,8 @@ package org.springframework.boot.context.properties; @@ -19,6 +19,8 @@ package org.springframework.boot.context.properties;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
@ -41,7 +43,7 @@ import org.springframework.util.ClassUtils; @@ -41,7 +43,7 @@ import org.springframework.util.ClassUtils;
class ConfigurationPropertiesBeanFactoryInitializationAotProcessor implements BeanFactoryInitializationAotProcessor {
@Override
public ConfigurationPropertiesReflectionHintsContribution processAheadOfTime(
public @Nullable ConfigurationPropertiesReflectionHintsContribution processAheadOfTime(
ConfigurableListableBeanFactory beanFactory) {
String[] beanNames = beanFactory.getBeanNamesForAnnotation(ConfigurationProperties.class);
List<Bindable<?>> bindables = new ArrayList<>();

4
core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrationAotProcessor.java

@ -20,6 +20,8 @@ import java.util.function.Predicate; @@ -20,6 +20,8 @@ import java.util.function.Predicate;
import javax.lang.model.element.Modifier;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.generate.GeneratedMethod;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.beans.factory.BeanFactory;
@ -45,7 +47,7 @@ import org.springframework.javapoet.CodeBlock; @@ -45,7 +47,7 @@ import org.springframework.javapoet.CodeBlock;
class ConfigurationPropertiesBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
@Override
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
public @Nullable BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
if (!isImmutableConfigurationPropertiesBeanDefinition(registeredBean.getMergedBeanDefinition())) {
return null;
}

24
core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java

@ -20,6 +20,8 @@ import java.util.ArrayList; @@ -20,6 +20,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.factory.BeanFactory;
@ -72,13 +74,13 @@ class ConfigurationPropertiesBinder { @@ -72,13 +74,13 @@ class ConfigurationPropertiesBinder {
private final PropertySources propertySources;
private final Validator configurationPropertiesValidator;
private final @Nullable Validator configurationPropertiesValidator;
private final boolean jsr303Present;
private volatile List<ConfigurationPropertiesBindHandlerAdvisor> bindHandlerAdvisors;
private volatile @Nullable List<ConfigurationPropertiesBindHandlerAdvisor> bindHandlerAdvisors;
private volatile Binder binder;
private volatile @Nullable Binder binder;
ConfigurationPropertiesBinder(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
@ -101,7 +103,7 @@ class ConfigurationPropertiesBinder { @@ -101,7 +103,7 @@ class ConfigurationPropertiesBinder {
return getBinder().bindOrCreate(annotation.prefix(), target, bindHandler);
}
private Validator getConfigurationPropertiesValidator(ApplicationContext applicationContext) {
private @Nullable Validator getConfigurationPropertiesValidator(ApplicationContext applicationContext) {
if (applicationContext.containsBean(VALIDATOR_BEAN_NAME)) {
return applicationContext.getBean(VALIDATOR_BEAN_NAME, Validator.class);
}
@ -153,7 +155,9 @@ class ConfigurationPropertiesBinder { @@ -153,7 +155,9 @@ class ConfigurationPropertiesBinder {
validators.add(this.configurationPropertiesValidator);
}
if (this.jsr303Present && target.getAnnotation(Validated.class) != null) {
validators.add(getJsr303Validator(target.getType().resolve()));
Class<?> resolved = target.getType().resolve();
Assert.state(resolved != null, "'resolved' must not be null");
validators.add(getJsr303Validator(resolved));
}
Validator selfValidator = getSelfValidator(target);
if (selfValidator != null) {
@ -162,7 +166,7 @@ class ConfigurationPropertiesBinder { @@ -162,7 +166,7 @@ class ConfigurationPropertiesBinder {
return validators;
}
private Validator getSelfValidator(Bindable<?> target) {
private @Nullable Validator getSelfValidator(Bindable<?> target) {
if (target.getValue() != null) {
Object value = target.getValue().get();
return (value instanceof Validator validator) ? validator : null;
@ -194,11 +198,11 @@ class ConfigurationPropertiesBinder { @@ -194,11 +198,11 @@ class ConfigurationPropertiesBinder {
return new PropertySourcesPlaceholdersResolver(this.propertySources);
}
private List<ConversionService> getConversionServices() {
private @Nullable List<ConversionService> getConversionServices() {
return new ConversionServiceDeducer(this.applicationContext).getConversionServices();
}
private Consumer<PropertyEditorRegistry> getPropertyEditorInitializer() {
private @Nullable Consumer<PropertyEditorRegistry> getPropertyEditorInitializer() {
if (this.applicationContext instanceof ConfigurableApplicationContext configurableContext) {
return configurableContext.getBeanFactory()::copyRegisteredEditorsTo;
}
@ -235,7 +239,7 @@ class ConfigurationPropertiesBinder { @@ -235,7 +239,7 @@ class ConfigurationPropertiesBinder {
? target.withBindRestrictions(BindRestriction.NO_DIRECT_PROPERTY) : target;
}
private boolean isConfigurationProperties(Class<?> target) {
private boolean isConfigurationProperties(@Nullable Class<?> target) {
return target != null && MergedAnnotations.from(target).isPresent(ConfigurationProperties.class);
}
@ -247,7 +251,7 @@ class ConfigurationPropertiesBinder { @@ -247,7 +251,7 @@ class ConfigurationPropertiesBinder {
static class ConfigurationPropertiesBinderFactory
implements FactoryBean<ConfigurationPropertiesBinder>, ApplicationContextAware {
private ConfigurationPropertiesBinder binder;
private @Nullable ConfigurationPropertiesBinder binder;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

7
core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.context.properties;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
@ -49,10 +51,13 @@ public class ConfigurationPropertiesBindingPostProcessor @@ -49,10 +51,13 @@ public class ConfigurationPropertiesBindingPostProcessor
*/
public static final String BEAN_NAME = ConfigurationPropertiesBindingPostProcessor.class.getName();
@SuppressWarnings("NullAway.Init")
private ApplicationContext applicationContext;
@SuppressWarnings("NullAway.Init")
private BeanDefinitionRegistry registry;
@SuppressWarnings("NullAway.Init")
private ConfigurationPropertiesBinder binder;
@Override
@ -85,7 +90,7 @@ public class ConfigurationPropertiesBindingPostProcessor @@ -85,7 +90,7 @@ public class ConfigurationPropertiesBindingPostProcessor
return BindMethod.VALUE_OBJECT.equals(BindMethodAttribute.get(this.registry, beanName));
}
private void bind(ConfigurationPropertiesBean bean) {
private void bind(@Nullable ConfigurationPropertiesBean bean) {
if (bean == null) {
return;
}

7
core/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesCharSequenceToObjectConverter.java

@ -19,6 +19,8 @@ package org.springframework.boot.context.properties; @@ -19,6 +19,8 @@ package org.springframework.boot.context.properties;
import java.util.Collections;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
@ -96,7 +98,10 @@ final class ConfigurationPropertiesCharSequenceToObjectConverter implements Cond @@ -96,7 +98,10 @@ final class ConfigurationPropertiesCharSequenceToObjectConverter implements Cond
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
return null;
}
return this.conversionService.convert(source.toString(), STRING, targetType);
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save