Browse Source

Add nullability annotations to core/spring-boot-autoconfigure

See gh-46587
pull/46595/head
Moritz Halbritter 8 months ago
parent
commit
b6e4533296
  1. 1
      config/checkstyle/checkstyle-suppressions.xml
  2. 8
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AbstractDependsOnBeanFactoryPostProcessor.java
  3. 7
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java
  4. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportFilter.java
  5. 43
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java
  6. 19
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationMetadata.java
  7. 16
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationMetadataLoader.java
  8. 8
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationPackages.java
  9. 6
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationReplacements.java
  10. 46
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationSorter.java
  11. 15
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java
  12. 1
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java
  13. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/admin/package-info.java
  14. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/aop/package-info.java
  15. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/availability/package-info.java
  16. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/package-info.java
  17. 6
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/AbstractNestedCondition.java
  18. 10
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReport.java
  19. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportAutoConfigurationImportListener.java
  20. 33
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionMessage.java
  21. 8
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionOutcome.java
  22. 33
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/FilteringSpringBootCondition.java
  23. 66
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java
  24. 47
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnClassCondition.java
  25. 8
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnCloudPlatformCondition.java
  26. 12
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java
  27. 8
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnJavaCondition.java
  28. 10
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnJndiCondition.java
  29. 14
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnPropertyCondition.java
  30. 20
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnResourceCondition.java
  31. 8
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnThreadingCondition.java
  32. 16
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWebApplicationCondition.java
  33. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/package-info.java
  34. 10
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/container/ContainerImageMetadata.java
  35. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/container/package-info.java
  36. 8
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java
  37. 14
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java
  38. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/package-info.java
  39. 11
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/AbstractRepositoryConfigurationSourceSupport.java
  40. 13
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/OnRepositoryTypeCondition.java
  41. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/package-info.java
  42. 23
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/diagnostics/analyzer/NoSuchBeanDefinitionFailureAnalyzer.java
  43. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/diagnostics/analyzer/package-info.java
  44. 1
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java
  45. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanner.java
  46. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/package-info.java
  47. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.java
  48. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/package-info.java
  49. 5
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java
  50. 8
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxProperties.java
  51. 13
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategy.java
  52. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/package-info.java
  53. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListener.java
  54. 5
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingProcessor.java
  55. 2
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportMessage.java
  56. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/package-info.java
  57. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/package-info.java
  58. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/preinitialize/package-info.java
  59. 8
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/service/connection/ConnectionDetailsFactories.java
  60. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/service/connection/ConnectionDetailsFactory.java
  61. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/service/connection/package-info.java
  62. 5
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/BundleContentProperty.java
  63. 17
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/CertificateMatcher.java
  64. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/FileWatcher.java
  65. 26
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/JksSslBundleProperties.java
  66. 26
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PemSslBundleProperties.java
  67. 21
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java
  68. 26
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/SslBundleProperties.java
  69. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/package-info.java
  70. 14
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java
  71. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java
  72. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations.java
  73. 14
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingProperties.java
  74. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/package-info.java
  75. 26
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProviders.java
  76. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateRuntimeHints.java
  77. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/package-info.java
  78. 10
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java
  79. 95
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebProperties.java
  80. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebResourcesRuntimeHints.java
  81. 20
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/DateTimeFormatters.java
  82. 4
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java
  83. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/package-info.java
  84. 3
      core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/package-info.java
  85. 2
      core/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProvidersTests.java

1
config/checkstyle/checkstyle-suppressions.xml

@ -90,4 +90,5 @@ @@ -90,4 +90,5 @@
<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"/>
<suppress files="ConditionMessage\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
</suppressions>

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

@ -22,6 +22,8 @@ import java.util.Set; @@ -22,6 +22,8 @@ import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.FactoryBean;
@ -50,7 +52,7 @@ public abstract class AbstractDependsOnBeanFactoryPostProcessor implements BeanF @@ -50,7 +52,7 @@ public abstract class AbstractDependsOnBeanFactoryPostProcessor implements BeanF
private final Class<?> beanClass;
private final Class<? extends FactoryBean<?>> factoryBeanClass;
private final @Nullable Class<? extends FactoryBean<?>> factoryBeanClass;
private final Function<ListableBeanFactory, Set<String>> dependsOn;
@ -61,7 +63,7 @@ public abstract class AbstractDependsOnBeanFactoryPostProcessor implements BeanF @@ -61,7 +63,7 @@ public abstract class AbstractDependsOnBeanFactoryPostProcessor implements BeanF
* @param dependsOn dependency names
*/
protected AbstractDependsOnBeanFactoryPostProcessor(Class<?> beanClass,
Class<? extends FactoryBean<?>> factoryBeanClass, String... dependsOn) {
@Nullable Class<? extends FactoryBean<?>> factoryBeanClass, String... dependsOn) {
this.beanClass = beanClass;
this.factoryBeanClass = factoryBeanClass;
this.dependsOn = (beanFactory) -> new HashSet<>(Arrays.asList(dependsOn));
@ -75,7 +77,7 @@ public abstract class AbstractDependsOnBeanFactoryPostProcessor implements BeanF @@ -75,7 +77,7 @@ public abstract class AbstractDependsOnBeanFactoryPostProcessor implements BeanF
* @since 2.1.7
*/
protected AbstractDependsOnBeanFactoryPostProcessor(Class<?> beanClass,
Class<? extends FactoryBean<?>> factoryBeanClass, Class<?>... dependencyTypes) {
@Nullable Class<? extends FactoryBean<?>> factoryBeanClass, Class<?>... dependencyTypes) {
this.beanClass = beanClass;
this.factoryBeanClass = factoryBeanClass;
this.dependsOn = (beanFactory) -> Arrays.stream(dependencyTypes)

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

@ -19,12 +19,15 @@ package org.springframework.boot.autoconfigure; @@ -19,12 +19,15 @@ package org.springframework.boot.autoconfigure;
import java.io.IOException;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.boot.context.annotation.ImportCandidates;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.Assert;
/**
* A {@link TypeFilter} implementation that matches registered auto-configuration classes.
@ -35,9 +38,10 @@ import org.springframework.core.type.filter.TypeFilter; @@ -35,9 +38,10 @@ import org.springframework.core.type.filter.TypeFilter;
*/
public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware {
@SuppressWarnings("NullAway.Init")
private ClassLoader beanClassLoader;
private volatile List<String> autoConfigurations;
private volatile @Nullable List<String> autoConfigurations;
@Override
public void setBeanClassLoader(ClassLoader beanClassLoader) {
@ -66,6 +70,7 @@ public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoad @@ -66,6 +70,7 @@ public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoad
ImportCandidates importCandidates = ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader);
this.autoConfigurations = importCandidates.getCandidates();
}
Assert.state(this.autoConfigurations != null, "'autoConfigurations' must not be null");
return this.autoConfigurations;
}

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

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.EnvironmentAware;
@ -54,6 +56,6 @@ public interface AutoConfigurationImportFilter { @@ -54,6 +56,6 @@ public interface AutoConfigurationImportFilter {
* {@code autoConfigurationClasses} parameter. Entries containing {@code false} will
* not be imported.
*/
boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata);
boolean[] match(@Nullable String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata);
}

43
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java

@ -32,6 +32,7 @@ import java.util.stream.Collectors; @@ -32,6 +32,7 @@ import java.util.stream.Collectors;
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.Aware;
@ -89,23 +90,27 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, @@ -89,23 +90,27 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
private final Class<?> autoConfigurationAnnotation;
@SuppressWarnings("NullAway.Init")
private ConfigurableListableBeanFactory beanFactory;
@SuppressWarnings("NullAway.Init")
private Environment environment;
@SuppressWarnings("NullAway.Init")
private ClassLoader beanClassLoader;
@SuppressWarnings("NullAway.Init")
private ResourceLoader resourceLoader;
private volatile ConfigurationClassFilter configurationClassFilter;
private volatile @Nullable ConfigurationClassFilter configurationClassFilter;
private volatile AutoConfigurationReplacements autoConfigurationReplacements;
private volatile @Nullable AutoConfigurationReplacements autoConfigurationReplacements;
public AutoConfigurationImportSelector() {
this(null);
}
AutoConfigurationImportSelector(Class<?> autoConfigurationAnnotation) {
AutoConfigurationImportSelector(@Nullable Class<?> autoConfigurationAnnotation) {
this.autoConfigurationAnnotation = (autoConfigurationAnnotation != null) ? autoConfigurationAnnotation
: AutoConfiguration.class;
}
@ -168,7 +173,7 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, @@ -168,7 +173,7 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
* @param metadata the annotation metadata
* @return annotation attributes
*/
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
protected @Nullable AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
String name = getAnnotationClass().getName();
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
Assert.state(attributes != null, () -> "No auto-configuration attributes found. Is " + metadata.getClassName()
@ -192,7 +197,8 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, @@ -192,7 +197,8 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
* attributes}
* @return a list of candidate configurations
*/
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
@Nullable AnnotationAttributes attributes) {
ImportCandidates importCandidates = ImportCandidates.load(this.autoConfigurationAnnotation,
getBeanClassLoader());
List<String> configurations = importCandidates.getCandidates();
@ -237,10 +243,12 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, @@ -237,10 +243,12 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
* attributes}
* @return exclusions or an empty set
*/
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
protected Set<String> getExclusions(AnnotationMetadata metadata, @Nullable AnnotationAttributes attributes) {
Set<String> excluded = new LinkedHashSet<>();
excluded.addAll(asList(attributes, "exclude"));
excluded.addAll(asList(attributes, "excludeName"));
if (attributes != null) {
excluded.addAll(asList(attributes, "exclude"));
excluded.addAll(asList(attributes, "excludeName"));
}
excluded.addAll(getExcludeAutoConfigurationsProperty());
return getAutoConfigurationReplacements().replaceAll(excluded);
}
@ -389,7 +397,7 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, @@ -389,7 +397,7 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
List<String> filter(List<String> configurations) {
long startTime = System.nanoTime();
String[] candidates = StringUtils.toStringArray(configurations);
@Nullable String[] candidates = StringUtils.toStringArray(configurations);
boolean skipped = false;
for (AutoConfigurationImportFilter filter : this.filters) {
boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
@ -426,15 +434,18 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, @@ -426,15 +434,18 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();
@SuppressWarnings("NullAway.Init")
private ClassLoader beanClassLoader;
@SuppressWarnings("NullAway.Init")
private BeanFactory beanFactory;
@SuppressWarnings("NullAway.Init")
private ResourceLoader resourceLoader;
private AutoConfigurationMetadata autoConfigurationMetadata;
private @Nullable AutoConfigurationMetadata autoConfigurationMetadata;
private AutoConfigurationReplacements autoConfigurationReplacements;
private @Nullable AutoConfigurationReplacements autoConfigurationReplacements;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
@ -488,10 +499,16 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, @@ -488,10 +499,16 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
.collect(Collectors.toCollection(LinkedHashSet::new));
processedConfigurations.removeAll(allExclusions);
return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
.map(this::getEntry)
.toList();
}
private Entry getEntry(String importClassName) {
AnnotationMetadata metadata = this.entries.get(importClassName);
Assert.state(metadata != null, "'metadata' must not be null");
return new Entry(metadata, importClassName);
}
private AutoConfigurationMetadata getAutoConfigurationMetadata() {
if (this.autoConfigurationMetadata == null) {
this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
@ -501,6 +518,8 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, @@ -501,6 +518,8 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
private List<String> sortAutoConfigurations(Set<String> configurations,
AutoConfigurationMetadata autoConfigurationMetadata) {
Assert.state(this.autoConfigurationReplacements != null,
"'autoConfigurationReplacements' must not be null");
return new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata,
this.autoConfigurationReplacements::replace)
.getInPriorityOrder(configurations);

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

@ -18,6 +18,10 @@ package org.springframework.boot.autoconfigure; @@ -18,6 +18,10 @@ package org.springframework.boot.autoconfigure;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.lang.Contract;
/**
* Provides access to meta-data written by the auto-configure annotation processor.
*
@ -40,7 +44,7 @@ public interface AutoConfigurationMetadata { @@ -40,7 +44,7 @@ public interface AutoConfigurationMetadata {
* @param key the meta-data key
* @return the meta-data value or {@code null}
*/
Integer getInteger(String className, String key);
@Nullable Integer getInteger(String className, String key);
/**
* Get an {@link Integer} value from the meta-data.
@ -49,7 +53,8 @@ public interface AutoConfigurationMetadata { @@ -49,7 +53,8 @@ public interface AutoConfigurationMetadata {
* @param defaultValue the default value
* @return the meta-data value or {@code defaultValue}
*/
Integer getInteger(String className, String key, Integer defaultValue);
@Contract("_, _, !null -> !null")
@Nullable Integer getInteger(String className, String key, @Nullable Integer defaultValue);
/**
* Get a {@link Set} value from the meta-data.
@ -57,7 +62,7 @@ public interface AutoConfigurationMetadata { @@ -57,7 +62,7 @@ public interface AutoConfigurationMetadata {
* @param key the meta-data key
* @return the meta-data value or {@code null}
*/
Set<String> getSet(String className, String key);
@Nullable Set<String> getSet(String className, String key);
/**
* Get a {@link Set} value from the meta-data.
@ -66,7 +71,8 @@ public interface AutoConfigurationMetadata { @@ -66,7 +71,8 @@ public interface AutoConfigurationMetadata {
* @param defaultValue the default value
* @return the meta-data value or {@code defaultValue}
*/
Set<String> getSet(String className, String key, Set<String> defaultValue);
@Contract("_, _, !null -> !null")
@Nullable Set<String> getSet(String className, String key, @Nullable Set<String> defaultValue);
/**
* Get an {@link String} value from the meta-data.
@ -74,7 +80,7 @@ public interface AutoConfigurationMetadata { @@ -74,7 +80,7 @@ public interface AutoConfigurationMetadata {
* @param key the meta-data key
* @return the meta-data value or {@code null}
*/
String get(String className, String key);
@Nullable String get(String className, String key);
/**
* Get an {@link String} value from the meta-data.
@ -83,6 +89,7 @@ public interface AutoConfigurationMetadata { @@ -83,6 +89,7 @@ public interface AutoConfigurationMetadata {
* @param defaultValue the default value
* @return the meta-data value or {@code defaultValue}
*/
String get(String className, String key, String defaultValue);
@Contract("_, _, !null -> !null")
@Nullable String get(String className, String key, @Nullable String defaultValue);
}

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

@ -22,6 +22,8 @@ import java.util.Enumeration; @@ -22,6 +22,8 @@ import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.StringUtils;
@ -42,7 +44,7 @@ final class AutoConfigurationMetadataLoader { @@ -42,7 +44,7 @@ final class AutoConfigurationMetadataLoader {
return loadMetadata(classLoader, PATH);
}
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
static AutoConfigurationMetadata loadMetadata(@Nullable ClassLoader classLoader, String path) {
try {
Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
: ClassLoader.getSystemResources(path);
@ -78,34 +80,34 @@ final class AutoConfigurationMetadataLoader { @@ -78,34 +80,34 @@ final class AutoConfigurationMetadataLoader {
}
@Override
public Integer getInteger(String className, String key) {
public @Nullable Integer getInteger(String className, String key) {
return getInteger(className, key, null);
}
@Override
public Integer getInteger(String className, String key, Integer defaultValue) {
public @Nullable Integer getInteger(String className, String key, @Nullable Integer defaultValue) {
String value = get(className, key);
return (value != null) ? Integer.valueOf(value) : defaultValue;
}
@Override
public Set<String> getSet(String className, String key) {
public @Nullable Set<String> getSet(String className, String key) {
return getSet(className, key, null);
}
@Override
public Set<String> getSet(String className, String key, Set<String> defaultValue) {
public @Nullable Set<String> getSet(String className, String key, @Nullable Set<String> defaultValue) {
String value = get(className, key);
return (value != null) ? StringUtils.commaDelimitedListToSet(value) : defaultValue;
}
@Override
public String get(String className, String key) {
public @Nullable String get(String className, String key) {
return get(className, key, null);
}
@Override
public String get(String className, String key, String defaultValue) {
public @Nullable String get(String className, String key, @Nullable String defaultValue) {
String value = this.properties.getProperty(className + "." + key);
return (value != null) ? value : defaultValue;
}

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

@ -30,12 +30,14 @@ import org.springframework.beans.factory.BeanFactory; @@ -30,12 +30,14 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.context.annotation.DeterminableImports;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@ -105,8 +107,9 @@ public abstract class AutoConfigurationPackages { @@ -105,8 +107,9 @@ public abstract class AutoConfigurationPackages {
private static void addBasePackages(BeanDefinition beanDefinition, String[] additionalBasePackages) {
ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
if (constructorArgumentValues.hasIndexedArgumentValue(0)) {
String[] existingPackages = (String[]) constructorArgumentValues.getIndexedArgumentValue(0, String[].class)
.getValue();
ValueHolder indexedArgumentValue = constructorArgumentValues.getIndexedArgumentValue(0, String[].class);
Assert.state(indexedArgumentValue != null, "'indexedArgumentValue' must not be null");
String[] existingPackages = (String[]) indexedArgumentValue.getValue();
constructorArgumentValues.addIndexedArgumentValue(0,
Stream.concat(Stream.of(existingPackages), Stream.of(additionalBasePackages))
.distinct()
@ -145,6 +148,7 @@ public abstract class AutoConfigurationPackages { @@ -145,6 +148,7 @@ public abstract class AutoConfigurationPackages {
PackageImports(AnnotationMetadata metadata) {
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(metadata.getAnnotationAttributes(AutoConfigurationPackage.class.getName(), false));
Assert.state(attributes != null, "'attributes' must not be null");
List<String> packageNames = new ArrayList<>(Arrays.asList(attributes.getStringArray("basePackages")));
for (Class<?> basePackageClass : attributes.getClassArray("basePackageClasses")) {
packageNames.add(basePackageClass.getPackage().getName());

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

@ -28,6 +28,8 @@ import java.util.Map; @@ -28,6 +28,8 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.annotation.ImportCandidates;
import org.springframework.core.io.UrlResource;
import org.springframework.util.Assert;
@ -88,7 +90,7 @@ final class AutoConfigurationReplacements { @@ -88,7 +90,7 @@ final class AutoConfigurationReplacements {
* @param classLoader class loader to use for loading
* @return list of names of annotated classes
*/
static AutoConfigurationReplacements load(Class<?> annotation, ClassLoader classLoader) {
static AutoConfigurationReplacements 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());
@ -101,7 +103,7 @@ final class AutoConfigurationReplacements { @@ -101,7 +103,7 @@ final class AutoConfigurationReplacements {
return new AutoConfigurationReplacements(replacements);
}
private static ClassLoader decideClassloader(ClassLoader classLoader) {
private static ClassLoader decideClassloader(@Nullable ClassLoader classLoader) {
if (classLoader == null) {
return ImportCandidates.class.getClassLoader();
}

46
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationSorter.java

@ -30,6 +30,8 @@ import java.util.Set; @@ -30,6 +30,8 @@ import java.util.Set;
import java.util.TreeSet;
import java.util.function.UnaryOperator;
import org.jspecify.annotations.Nullable;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
@ -47,12 +49,13 @@ class AutoConfigurationSorter { @@ -47,12 +49,13 @@ class AutoConfigurationSorter {
private final MetadataReaderFactory metadataReaderFactory;
private final AutoConfigurationMetadata autoConfigurationMetadata;
private final @Nullable AutoConfigurationMetadata autoConfigurationMetadata;
private final UnaryOperator<String> replacementMapper;
private final @Nullable UnaryOperator<String> replacementMapper;
AutoConfigurationSorter(MetadataReaderFactory metadataReaderFactory,
AutoConfigurationMetadata autoConfigurationMetadata, UnaryOperator<String> replacementMapper) {
@Nullable AutoConfigurationMetadata autoConfigurationMetadata,
@Nullable UnaryOperator<String> replacementMapper) {
Assert.notNull(metadataReaderFactory, "'metadataReaderFactory' must not be null");
this.metadataReaderFactory = metadataReaderFactory;
this.autoConfigurationMetadata = autoConfigurationMetadata;
@ -91,7 +94,7 @@ class AutoConfigurationSorter { @@ -91,7 +94,7 @@ class AutoConfigurationSorter {
}
private void doSortByAfterAnnotation(AutoConfigurationClasses classes, List<String> toSort, Set<String> sorted,
Set<String> processing, String current) {
Set<String> processing, @Nullable String current) {
if (current == null) {
current = toSort.remove(0);
}
@ -118,7 +121,7 @@ class AutoConfigurationSorter { @@ -118,7 +121,7 @@ class AutoConfigurationSorter {
private final Map<String, AutoConfigurationClass> classes = new LinkedHashMap<>();
AutoConfigurationClasses(MetadataReaderFactory metadataReaderFactory,
AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames) {
@Nullable AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames) {
addToClasses(metadataReaderFactory, autoConfigurationMetadata, classNames, true);
}
@ -127,7 +130,8 @@ class AutoConfigurationSorter { @@ -127,7 +130,8 @@ class AutoConfigurationSorter {
}
private void addToClasses(MetadataReaderFactory metadataReaderFactory,
AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames, boolean required) {
@Nullable AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames,
boolean required) {
for (String className : classNames) {
if (!this.classes.containsKey(className)) {
AutoConfigurationClass autoConfigurationClass = new AutoConfigurationClass(className,
@ -147,7 +151,9 @@ class AutoConfigurationSorter { @@ -147,7 +151,9 @@ class AutoConfigurationSorter {
}
AutoConfigurationClass get(String className) {
return this.classes.get(className);
AutoConfigurationClass autoConfigurationClass = this.classes.get(className);
Assert.state(autoConfigurationClass != null, "'autoConfigurationClass' must not be null");
return autoConfigurationClass;
}
Set<String> getClassesRequestedAfter(String className) {
@ -168,16 +174,16 @@ class AutoConfigurationSorter { @@ -168,16 +174,16 @@ class AutoConfigurationSorter {
private final MetadataReaderFactory metadataReaderFactory;
private final AutoConfigurationMetadata autoConfigurationMetadata;
private final @Nullable AutoConfigurationMetadata autoConfigurationMetadata;
private volatile AnnotationMetadata annotationMetadata;
private volatile @Nullable AnnotationMetadata annotationMetadata;
private volatile Set<String> before;
private volatile @Nullable Set<String> before;
private volatile Set<String> after;
private volatile @Nullable Set<String> after;
AutoConfigurationClass(String className, MetadataReaderFactory metadataReaderFactory,
AutoConfigurationMetadata autoConfigurationMetadata) {
@Nullable AutoConfigurationMetadata autoConfigurationMetadata) {
this.className = className;
this.metadataReaderFactory = metadataReaderFactory;
this.autoConfigurationMetadata = autoConfigurationMetadata;
@ -210,12 +216,15 @@ class AutoConfigurationSorter { @@ -210,12 +216,15 @@ class AutoConfigurationSorter {
}
private Set<String> getClassNames(String metadataKey, Class<? extends Annotation> annotation) {
Set<String> annotationValue = wasProcessed()
? this.autoConfigurationMetadata.getSet(this.className, metadataKey, Collections.emptySet())
: getAnnotationValue(annotation);
Set<String> annotationValue = wasProcessed() ? getSet(metadataKey) : getAnnotationValue(annotation);
return applyReplacements(annotationValue);
}
private Set<String> getSet(String metadataKey) {
Assert.state(this.autoConfigurationMetadata != null, "'autoConfigurationMetadata' must not be null");
return this.autoConfigurationMetadata.getSet(this.className, metadataKey, Collections.emptySet());
}
private Set<String> applyReplacements(Set<String> values) {
if (AutoConfigurationSorter.this.replacementMapper == null) {
return values;
@ -229,10 +238,11 @@ class AutoConfigurationSorter { @@ -229,10 +238,11 @@ class AutoConfigurationSorter {
private int getOrder() {
if (wasProcessed()) {
Assert.state(this.autoConfigurationMetadata != null, "'autoConfigurationMetadata' must not be null");
return this.autoConfigurationMetadata.getInteger(this.className, "AutoConfigureOrder",
AutoConfigureOrder.DEFAULT_ORDER);
}
Map<String, Object> attributes = getAnnotationMetadata()
Map<String, @Nullable Object> attributes = getAnnotationMetadata()
.getAnnotationAttributes(AutoConfigureOrder.class.getName());
return (attributes != null) ? (Integer) attributes.get("value") : AutoConfigureOrder.DEFAULT_ORDER;
}
@ -243,8 +253,8 @@ class AutoConfigurationSorter { @@ -243,8 +253,8 @@ class AutoConfigurationSorter {
}
private Set<String> getAnnotationValue(Class<?> annotation) {
Map<String, Object> attributes = getAnnotationMetadata().getAnnotationAttributes(annotation.getName(),
true);
Map<String, @Nullable Object> attributes = getAnnotationMetadata()
.getAnnotationAttributes(annotation.getName(), true);
if (attributes == null) {
return Collections.emptySet();
}

15
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java

@ -28,6 +28,8 @@ import java.util.Map; @@ -28,6 +28,8 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.annotation.DeterminableImports;
import org.springframework.boot.context.annotation.ImportCandidates;
import org.springframework.core.annotation.AnnotatedElementUtils;
@ -71,12 +73,13 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec @@ -71,12 +73,13 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec
}
@Override
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
protected @Nullable AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
return null;
}
@Override
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
@Nullable AnnotationAttributes attributes) {
List<String> candidates = new ArrayList<>();
Map<Class<?>, List<Annotation>> annotations = getAnnotations(metadata);
annotations.forEach(
@ -93,13 +96,13 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec @@ -93,13 +96,13 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec
private Collection<String> getConfigurationsForAnnotation(Class<?> source, Annotation annotation) {
String[] classes = (String[]) AnnotationUtils.getAnnotationAttributes(annotation, true).get("classes");
if (classes.length > 0) {
if (classes != null && classes.length > 0) {
return Arrays.asList(classes);
}
return loadFactoryNames(source).stream().map(this::mapFactoryName).filter(Objects::nonNull).toList();
}
private String mapFactoryName(String name) {
private @Nullable String mapFactoryName(String name) {
if (!name.startsWith(OPTIONAL_PREFIX)) {
return name;
}
@ -117,7 +120,7 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec @@ -117,7 +120,7 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec
}
@Override
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
protected Set<String> getExclusions(AnnotationMetadata metadata, @Nullable AnnotationAttributes attributes) {
Set<String> exclusions = new LinkedHashSet<>();
Class<?> source = ClassUtils.resolveClassName(metadata.getClassName(), getBeanClassLoader());
for (String annotationName : ANNOTATION_NAMES) {
@ -148,7 +151,7 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec @@ -148,7 +151,7 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec
return Collections.unmodifiableMap(annotations);
}
private void collectAnnotations(Class<?> source, MultiValueMap<Class<?>, Annotation> annotations,
private void collectAnnotations(@Nullable Class<?> source, MultiValueMap<Class<?>, Annotation> annotations,
HashSet<Class<?>> seen) {
if (source != null && seen.add(source)) {
for (Annotation annotation : source.getDeclaredAnnotations()) {

1
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java

@ -191,6 +191,7 @@ class SharedMetadataReaderFactoryContextInitializer implements @@ -191,6 +191,7 @@ class SharedMetadataReaderFactoryContextInitializer implements
implements FactoryBean<ConcurrentReferenceCachingMetadataReaderFactory>, ResourceLoaderAware,
ApplicationListener<ContextRefreshedEvent> {
@SuppressWarnings("NullAway.Init")
private ConcurrentReferenceCachingMetadataReaderFactory metadataReaderFactory;
@Override

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for admin-related features.
*/
@NullMarked
package org.springframework.boot.autoconfigure.admin;
import org.jspecify.annotations.NullMarked;

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for Spring AOP.
*/
@NullMarked
package org.springframework.boot.autoconfigure.aop;
import org.jspecify.annotations.NullMarked;

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for application availability features.
*/
@NullMarked
package org.springframework.boot.autoconfigure.availability;
import org.jspecify.annotations.NullMarked;

3
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/package-info.java vendored

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration base classes for Caching support.
*/
@NullMarked
package org.springframework.boot.autoconfigure.cache;
import org.jspecify.annotations.NullMarked;

6
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/AbstractNestedCondition.java

@ -22,6 +22,8 @@ import java.util.Collections; @@ -22,6 +22,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
@ -153,8 +155,8 @@ public abstract class AbstractNestedCondition extends SpringBootCondition implem @@ -153,8 +155,8 @@ public abstract class AbstractNestedCondition extends SpringBootCondition implem
@SuppressWarnings("unchecked")
private List<String[]> getConditionClasses(AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(Conditional.class.getName(),
true);
MultiValueMap<String, @Nullable Object> attributes = metadata
.getAllAnnotationAttributes(Conditional.class.getName(), true);
Object values = (attributes != null) ? attributes.get("value") : null;
return (List<String[]>) ((values != null) ? values : Collections.emptyList());
}

10
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReport.java

@ -30,6 +30,8 @@ import java.util.TreeMap; @@ -30,6 +30,8 @@ import java.util.TreeMap;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Condition;
@ -58,7 +60,7 @@ public final class ConditionEvaluationReport { @@ -58,7 +60,7 @@ public final class ConditionEvaluationReport {
private boolean addedAncestorOutcomes;
private ConditionEvaluationReport parent;
private @Nullable ConditionEvaluationReport parent;
private final List<String> exclusions = new ArrayList<>();
@ -154,7 +156,7 @@ public final class ConditionEvaluationReport { @@ -154,7 +156,7 @@ public final class ConditionEvaluationReport {
* The parent report (from a parent BeanFactory if there is one).
* @return the parent report (or null if there isn't one)
*/
public ConditionEvaluationReport getParent() {
public @Nullable ConditionEvaluationReport getParent() {
return this.parent;
}
@ -164,7 +166,7 @@ public final class ConditionEvaluationReport { @@ -164,7 +166,7 @@ public final class ConditionEvaluationReport {
* @param beanFactory the bean factory (may be {@code null})
* @return the {@link ConditionEvaluationReport} or {@code null}
*/
public static ConditionEvaluationReport find(BeanFactory beanFactory) {
public static @Nullable ConditionEvaluationReport find(BeanFactory beanFactory) {
if (beanFactory instanceof ConfigurableListableBeanFactory) {
return ConditionEvaluationReport.get((ConfigurableListableBeanFactory) beanFactory);
}
@ -191,7 +193,7 @@ public final class ConditionEvaluationReport { @@ -191,7 +193,7 @@ public final class ConditionEvaluationReport {
}
}
private static void locateParent(BeanFactory beanFactory, ConditionEvaluationReport report) {
private static void locateParent(@Nullable BeanFactory beanFactory, ConditionEvaluationReport report) {
if (beanFactory != null && report.parent == null && beanFactory.containsBean(BEAN_NAME)) {
report.parent = beanFactory.getBean(BEAN_NAME, ConditionEvaluationReport.class);
}

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportAutoConfigurationImportListener.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.condition;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@ -32,7 +34,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurationImportListener; @@ -32,7 +34,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurationImportListener;
class ConditionEvaluationReportAutoConfigurationImportListener
implements AutoConfigurationImportListener, BeanFactoryAware {
private ConfigurableListableBeanFactory beanFactory;
private @Nullable ConfigurableListableBeanFactory beanFactory;
@Override
public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) {

33
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionMessage.java

@ -23,6 +23,8 @@ import java.util.Collection; @@ -23,6 +23,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
@ -38,13 +40,13 @@ import org.springframework.util.StringUtils; @@ -38,13 +40,13 @@ import org.springframework.util.StringUtils;
*/
public final class ConditionMessage {
private final String message;
private final @Nullable String message;
private ConditionMessage() {
this(null);
}
private ConditionMessage(String message) {
private ConditionMessage(@Nullable String message) {
this.message = message;
}
@ -87,7 +89,7 @@ public final class ConditionMessage { @@ -87,7 +89,7 @@ public final class ConditionMessage {
* @param message the message to append
* @return a new {@link ConditionMessage} instance
*/
public ConditionMessage append(String message) {
public ConditionMessage append(@Nullable String message) {
if (!StringUtils.hasLength(message)) {
return this;
}
@ -158,7 +160,7 @@ public final class ConditionMessage { @@ -158,7 +160,7 @@ public final class ConditionMessage {
* @param messages the source messages (may be {@code null})
* @return a new {@link ConditionMessage} instance
*/
public static ConditionMessage of(Collection<? extends ConditionMessage> messages) {
public static ConditionMessage of(@Nullable Collection<? extends ConditionMessage> messages) {
ConditionMessage result = new ConditionMessage();
if (messages != null) {
for (ConditionMessage message : messages) {
@ -296,7 +298,7 @@ public final class ConditionMessage { @@ -296,7 +298,7 @@ public final class ConditionMessage {
* @param reason the reason for the message
* @return a built {@link ConditionMessage}
*/
public ConditionMessage because(String reason) {
public ConditionMessage because(@Nullable String reason) {
if (StringUtils.hasLength(reason)) {
return new ConditionMessage(ConditionMessage.this,
StringUtils.hasLength(this.condition) ? this.condition + " " + reason : reason);
@ -343,7 +345,7 @@ public final class ConditionMessage { @@ -343,7 +345,7 @@ public final class ConditionMessage {
* @param items the items (may be {@code null})
* @return a built {@link ConditionMessage}
*/
public ConditionMessage items(Object... items) {
public ConditionMessage items(Object @Nullable ... items) {
return items(Style.NORMAL, items);
}
@ -355,7 +357,7 @@ public final class ConditionMessage { @@ -355,7 +357,7 @@ public final class ConditionMessage {
* @param items the items (may be {@code null})
* @return a built {@link ConditionMessage}
*/
public ConditionMessage items(Style style, Object... items) {
public ConditionMessage items(Style style, Object @Nullable ... items) {
return items(style, (items != null) ? Arrays.asList(items) : null);
}
@ -366,7 +368,7 @@ public final class ConditionMessage { @@ -366,7 +368,7 @@ public final class ConditionMessage {
* @param items the source of the items (may be {@code null})
* @return a built {@link ConditionMessage}
*/
public ConditionMessage items(Collection<?> items) {
public ConditionMessage items(@Nullable Collection<?> items) {
return items(Style.NORMAL, items);
}
@ -378,7 +380,7 @@ public final class ConditionMessage { @@ -378,7 +380,7 @@ public final class ConditionMessage {
* @param items the source of the items (may be {@code null})
* @return a built {@link ConditionMessage}
*/
public ConditionMessage items(Style style, Collection<?> items) {
public ConditionMessage items(Style style, @Nullable Collection<?> items) {
Assert.notNull(style, "'style' must not be null");
StringBuilder message = new StringBuilder(this.reason);
items = style.applyTo(items);
@ -408,7 +410,7 @@ public final class ConditionMessage { @@ -408,7 +410,7 @@ public final class ConditionMessage {
NORMAL {
@Override
protected Object applyToItem(Object item) {
protected @Nullable Object applyToItem(@Nullable Object item) {
return item;
}
@ -420,24 +422,27 @@ public final class ConditionMessage { @@ -420,24 +422,27 @@ public final class ConditionMessage {
QUOTE {
@Override
protected String applyToItem(Object item) {
protected @Nullable String applyToItem(@Nullable Object item) {
return (item != null) ? "'" + item + "'" : null;
}
};
public Collection<?> applyTo(Collection<?> items) {
public @Nullable Collection<?> applyTo(@Nullable Collection<?> items) {
if (items == null) {
return null;
}
List<Object> result = new ArrayList<>(items.size());
for (Object item : items) {
result.add(applyToItem(item));
Object applied = applyToItem(item);
if (applied != null) {
result.add(applied);
}
}
return result;
}
protected abstract Object applyToItem(Object item);
protected abstract @Nullable Object applyToItem(@Nullable Object item);
}

8
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionOutcome.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.condition;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@ -111,13 +113,13 @@ public class ConditionOutcome { @@ -111,13 +113,13 @@ public class ConditionOutcome {
* Return an outcome message or {@code null}.
* @return the message or {@code null}
*/
public String getMessage() {
public @Nullable String getMessage() {
return this.message.isEmpty() ? null : this.message.toString();
}
/**
* Return an outcome message or {@code null}.
* @return the message or {@code null}
* Return an outcome message.
* @return the message
*/
public ConditionMessage getConditionMessage() {
return this.message;

33
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/FilteringSpringBootCondition.java

@ -21,12 +21,15 @@ import java.util.Collection; @@ -21,12 +21,15 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
@ -39,28 +42,33 @@ import org.springframework.util.CollectionUtils; @@ -39,28 +42,33 @@ import org.springframework.util.CollectionUtils;
abstract class FilteringSpringBootCondition extends SpringBootCondition
implements AutoConfigurationImportFilter, BeanFactoryAware, BeanClassLoaderAware {
@SuppressWarnings("NullAway.Init")
private BeanFactory beanFactory;
@SuppressWarnings("NullAway.Init")
private ClassLoader beanClassLoader;
@Override
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
public boolean[] match(@Nullable String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionEvaluationReport report = ConditionEvaluationReport.find(this.beanFactory);
ConditionOutcome[] outcomes = getOutcomes(autoConfigurationClasses, autoConfigurationMetadata);
@Nullable ConditionOutcome[] outcomes = getOutcomes(autoConfigurationClasses, autoConfigurationMetadata);
boolean[] match = new boolean[outcomes.length];
for (int i = 0; i < outcomes.length; i++) {
match[i] = (outcomes[i] == null || outcomes[i].isMatch());
if (!match[i] && outcomes[i] != null) {
logOutcome(autoConfigurationClasses[i], outcomes[i]);
String autoConfigurationClass = autoConfigurationClasses[i];
Assert.state(autoConfigurationClass != null, "'autoConfigurationClass' must not be null");
logOutcome(autoConfigurationClass, outcomes[i]);
if (report != null) {
report.recordConditionEvaluation(autoConfigurationClasses[i], this, outcomes[i]);
report.recordConditionEvaluation(autoConfigurationClass, this, outcomes[i]);
}
}
}
return match;
}
protected abstract ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
protected abstract @Nullable ConditionOutcome[] getOutcomes(@Nullable String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata);
@Override
@ -81,8 +89,8 @@ abstract class FilteringSpringBootCondition extends SpringBootCondition @@ -81,8 +89,8 @@ abstract class FilteringSpringBootCondition extends SpringBootCondition
this.beanClassLoader = classLoader;
}
protected final List<String> filter(Collection<String> classNames, ClassNameFilter classNameFilter,
ClassLoader classLoader) {
protected final List<String> filter(@Nullable Collection<String> classNames, ClassNameFilter classNameFilter,
@Nullable ClassLoader classLoader) {
if (CollectionUtils.isEmpty(classNames)) {
return Collections.emptyList();
}
@ -103,7 +111,8 @@ abstract class FilteringSpringBootCondition extends SpringBootCondition @@ -103,7 +111,8 @@ abstract class FilteringSpringBootCondition extends SpringBootCondition
* @return a resolved class
* @throws ClassNotFoundException if the class cannot be found
*/
protected static Class<?> resolve(String className, ClassLoader classLoader) throws ClassNotFoundException {
protected static Class<?> resolve(String className, @Nullable ClassLoader classLoader)
throws ClassNotFoundException {
if (classLoader != null) {
return Class.forName(className, false, classLoader);
}
@ -115,7 +124,7 @@ abstract class FilteringSpringBootCondition extends SpringBootCondition @@ -115,7 +124,7 @@ abstract class FilteringSpringBootCondition extends SpringBootCondition
PRESENT {
@Override
public boolean matches(String className, ClassLoader classLoader) {
public boolean matches(String className, @Nullable ClassLoader classLoader) {
return isPresent(className, classLoader);
}
@ -124,15 +133,15 @@ abstract class FilteringSpringBootCondition extends SpringBootCondition @@ -124,15 +133,15 @@ abstract class FilteringSpringBootCondition extends SpringBootCondition
MISSING {
@Override
public boolean matches(String className, ClassLoader classLoader) {
public boolean matches(String className, @Nullable ClassLoader classLoader) {
return !isPresent(className, classLoader);
}
};
abstract boolean matches(String className, ClassLoader classLoader);
abstract boolean matches(String className, @Nullable ClassLoader classLoader);
private static boolean isPresent(String className, ClassLoader classLoader) {
private static boolean isPresent(String className, @Nullable ClassLoader classLoader) {
if (classLoader == null) {
classLoader = ClassUtils.getDefaultClassLoader();
}

66
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java

@ -34,6 +34,8 @@ import java.util.Set; @@ -34,6 +34,8 @@ import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
@ -60,6 +62,7 @@ import org.springframework.core.annotation.MergedAnnotations; @@ -60,6 +62,7 @@ import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
@ -90,9 +93,9 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -90,9 +93,9 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
}
@Override
protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
protected final @Nullable ConditionOutcome[] getOutcomes(@Nullable String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
@Nullable ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
for (int i = 0; i < outcomes.length; i++) {
String autoConfigurationClass = autoConfigurationClasses[i];
if (autoConfigurationClass != null) {
@ -108,7 +111,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -108,7 +111,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return outcomes;
}
private ConditionOutcome getOutcome(Set<String> requiredBeanTypes, Class<? extends Annotation> annotation) {
private @Nullable ConditionOutcome getOutcome(@Nullable Set<String> requiredBeanTypes,
Class<? extends Annotation> annotation) {
List<String> missing = filter(requiredBeanTypes, ClassNameFilter.MISSING, getBeanClassLoader());
if (!missing.isEmpty()) {
ConditionMessage message = ConditionMessage.forCondition(annotation)
@ -171,7 +175,9 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -171,7 +175,9 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return ConditionOutcome
.match(spec.message(matchMessage).found("a single bean").items(Style.QUOTE, allBeans));
}
Map<String, BeanDefinition> beanDefinitions = getBeanDefinitions(spec.context.getBeanFactory(), allBeans,
ConfigurableListableBeanFactory beanFactory = spec.context.getBeanFactory();
Assert.state(beanFactory != null, "'beanFactory' must not be null");
Map<String, BeanDefinition> beanDefinitions = getBeanDefinitions(beanFactory, allBeans,
spec.getStrategy() == SearchStrategy.ALL);
List<String> primaryBeans = getPrimaryBeans(beanDefinitions);
if (primaryBeans.size() == 1) {
@ -249,6 +255,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -249,6 +255,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
private ConfigurableListableBeanFactory getSearchBeanFactory(Spec<?> spec) {
ConfigurableListableBeanFactory beanFactory = spec.getContext().getBeanFactory();
Assert.state(beanFactory != null, "'beanFactory' must not be null'");
if (spec.getStrategy() == SearchStrategy.ANCESTORS) {
BeanFactory parent = beanFactory.getParentBeanFactory();
Assert.state(parent instanceof ConfigurableListableBeanFactory,
@ -269,8 +276,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -269,8 +276,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return matchedNames;
}
private boolean isCandidate(ConfigurableListableBeanFactory beanFactory, String name, BeanDefinition definition,
Set<String> ignoredBeans) {
private boolean isCandidate(ConfigurableListableBeanFactory beanFactory, String name,
@Nullable BeanDefinition definition, Set<String> ignoredBeans) {
return (!ignoredBeans.contains(name)) && (definition == null
|| isAutowireCandidate(beanFactory, name, definition) && isDefaultCandidate(definition));
}
@ -316,12 +323,14 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -316,12 +323,14 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return (result != null) ? result : Collections.emptyMap();
}
private Map<String, BeanDefinition> collectBeanDefinitionsForType(ListableBeanFactory beanFactory,
private @Nullable Map<String, BeanDefinition> collectBeanDefinitionsForType(ListableBeanFactory beanFactory,
boolean considerHierarchy, ResolvableType type, Set<ResolvableType> parameterizedContainers,
Map<String, BeanDefinition> result) {
@Nullable Map<String, BeanDefinition> result) {
result = putAll(result, beanFactory.getBeanNamesForType(type, true, false), beanFactory);
for (ResolvableType parameterizedContainer : parameterizedContainers) {
ResolvableType generic = ResolvableType.forClassWithGenerics(parameterizedContainer.resolve(), type);
Class<?> resolved = parameterizedContainer.resolve();
Assert.state(resolved != null, "'resolved' must not be null");
ResolvableType generic = ResolvableType.forClassWithGenerics(resolved, type);
result = putAll(result, beanFactory.getBeanNamesForType(generic, true, false), beanFactory);
}
if (considerHierarchy && beanFactory instanceof HierarchicalBeanFactory hierarchicalBeanFactory) {
@ -334,7 +343,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -334,7 +343,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return result;
}
private Map<String, BeanDefinition> getBeanDefinitionsForAnnotation(ClassLoader classLoader,
private Map<String, BeanDefinition> getBeanDefinitionsForAnnotation(@Nullable ClassLoader classLoader,
ConfigurableListableBeanFactory beanFactory, String type, boolean considerHierarchy) throws LinkageError {
Map<String, BeanDefinition> result = null;
try {
@ -348,13 +357,14 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -348,13 +357,14 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
}
@SuppressWarnings("unchecked")
private Class<? extends Annotation> resolveAnnotationType(ClassLoader classLoader, String type)
private Class<? extends Annotation> resolveAnnotationType(@Nullable ClassLoader classLoader, String type)
throws ClassNotFoundException {
return (Class<? extends Annotation>) resolve(type, classLoader);
}
private Map<String, BeanDefinition> collectBeanDefinitionsForAnnotation(ListableBeanFactory beanFactory,
Class<? extends Annotation> annotationType, boolean considerHierarchy, Map<String, BeanDefinition> result) {
private @Nullable Map<String, BeanDefinition> collectBeanDefinitionsForAnnotation(ListableBeanFactory beanFactory,
Class<? extends Annotation> annotationType, boolean considerHierarchy,
@Nullable Map<String, BeanDefinition> result) {
result = putAll(result, getBeanNamesForAnnotation(beanFactory, annotationType), beanFactory);
if (considerHierarchy) {
BeanFactory parent = ((HierarchicalBeanFactory) beanFactory).getParentBeanFactory();
@ -477,7 +487,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -477,7 +487,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return matches;
}
private BeanDefinition findBeanDefinition(ConfigurableListableBeanFactory beanFactory, String beanName,
private @Nullable BeanDefinition findBeanDefinition(ConfigurableListableBeanFactory beanFactory, String beanName,
boolean considerHierarchy) {
if (beanFactory.containsBeanDefinition(beanName)) {
return beanFactory.getBeanDefinition(beanName);
@ -489,7 +499,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -489,7 +499,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return null;
}
private static Set<String> addAll(Set<String> result, Collection<String> additional) {
private static @Nullable Set<String> addAll(@Nullable Set<String> result, @Nullable Collection<String> additional) {
if (CollectionUtils.isEmpty(additional)) {
return result;
}
@ -498,8 +508,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -498,8 +508,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return result;
}
private static Map<String, BeanDefinition> putAll(Map<String, BeanDefinition> result, String[] beanNames,
ListableBeanFactory beanFactory) {
private static @Nullable Map<String, BeanDefinition> putAll(@Nullable Map<String, BeanDefinition> result,
String[] beanNames, ListableBeanFactory beanFactory) {
if (ObjectUtils.isEmpty(beanNames)) {
return result;
}
@ -517,7 +527,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -517,7 +527,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return result;
}
private static BeanDefinition getBeanDefinition(String beanName, ConfigurableListableBeanFactory beanFactory) {
private static @Nullable BeanDefinition getBeanDefinition(String beanName,
ConfigurableListableBeanFactory beanFactory) {
try {
return beanFactory.getBeanDefinition(beanName);
}
@ -548,7 +559,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -548,7 +559,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
private final Set<ResolvableType> parameterizedContainers;
private final SearchStrategy strategy;
private final @Nullable SearchStrategy strategy;
Spec(ConditionContext context, AnnotatedTypeMetadata metadata, MergedAnnotations annotations,
Class<A> annotationType) {
@ -621,7 +632,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -621,7 +632,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return resolved;
}
protected void validate(BeanTypeDeductionException ex) {
protected void validate(@Nullable BeanTypeDeductionException ex) {
if (!hasAtLeastOneElement(getTypes(), getNames(), getAnnotations())) {
String message = getAnnotationName() + " did not specify a bean using type, name or annotation";
if (ex == null) {
@ -671,13 +682,13 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -671,13 +682,13 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return returnType;
}
private boolean isParameterizedContainer(Class<?> type) {
private boolean isParameterizedContainer(@Nullable Class<?> type) {
return (type != null) && this.parameterizedContainers.stream()
.map(ResolvableType::resolve)
.anyMatch((container) -> container != null && container.isAssignableFrom(type));
}
private ResolvableType getMethodReturnType(MethodMetadata metadata, ClassLoader classLoader)
private ResolvableType getMethodReturnType(MethodMetadata metadata, @Nullable ClassLoader classLoader)
throws ClassNotFoundException, LinkageError {
Class<?> declaringClass = resolve(metadata.getDeclaringClassName(), classLoader);
Method beanMethod = findBeanMethod(declaringClass, metadata.getMethodName());
@ -698,7 +709,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -698,7 +709,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
throw new IllegalStateException("Unable to find bean method " + methodName);
}
private boolean isBeanMethod(Method method) {
@Contract("null -> false")
private boolean isBeanMethod(@Nullable Method method) {
return method != null && MergedAnnotations.from(method, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY)
.isPresent(Bean.class);
}
@ -761,8 +773,10 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -761,8 +773,10 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
string.append(StringUtils.collectionToCommaDelimitedString(this.ignoredTypes));
string.append("; ");
}
string.append("SearchStrategy: ");
string.append(this.strategy.toString().toLowerCase(Locale.ENGLISH));
if (this.strategy != null) {
string.append("SearchStrategy: ");
string.append(this.strategy.toString().toLowerCase(Locale.ENGLISH));
}
string.append(")");
return string.toString();
}
@ -789,7 +803,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat @@ -789,7 +803,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
}
@Override
protected void validate(BeanTypeDeductionException ex) {
protected void validate(@Nullable BeanTypeDeductionException ex) {
Assert.isTrue(getTypes().size() == 1,
() -> getAnnotationName() + " annotations must specify only one type (got "
+ StringUtils.collectionToCommaDelimitedString(getTypes()) + ")");

47
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnClassCondition.java

@ -20,6 +20,8 @@ import java.util.ArrayList; @@ -20,6 +20,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
@ -44,7 +46,7 @@ import org.springframework.util.StringUtils; @@ -44,7 +46,7 @@ import org.springframework.util.StringUtils;
class OnClassCondition extends FilteringSpringBootCondition {
@Override
protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
protected final @Nullable ConditionOutcome[] getOutcomes(@Nullable String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// Split the work and perform half in a background thread if more than one
// processor is available. Using a single additional thread seems to offer the
@ -59,22 +61,22 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -59,22 +61,22 @@ class OnClassCondition extends FilteringSpringBootCondition {
}
}
private ConditionOutcome[] resolveOutcomesThreaded(String[] autoConfigurationClasses,
private @Nullable ConditionOutcome[] resolveOutcomesThreaded(@Nullable String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
int split = autoConfigurationClasses.length / 2;
OutcomesResolver firstHalfResolver = createOutcomesResolver(autoConfigurationClasses, 0, split,
autoConfigurationMetadata);
OutcomesResolver secondHalfResolver = new StandardOutcomesResolver(autoConfigurationClasses, split,
autoConfigurationClasses.length, autoConfigurationMetadata, getBeanClassLoader());
ConditionOutcome[] secondHalf = secondHalfResolver.resolveOutcomes();
ConditionOutcome[] firstHalf = firstHalfResolver.resolveOutcomes();
ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
@Nullable ConditionOutcome[] secondHalf = secondHalfResolver.resolveOutcomes();
@Nullable ConditionOutcome[] firstHalf = firstHalfResolver.resolveOutcomes();
@Nullable ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
System.arraycopy(firstHalf, 0, outcomes, 0, firstHalf.length);
System.arraycopy(secondHalf, 0, outcomes, split, secondHalf.length);
return outcomes;
}
private OutcomesResolver createOutcomesResolver(String[] autoConfigurationClasses, int start, int end,
private OutcomesResolver createOutcomesResolver(@Nullable String[] autoConfigurationClasses, int start, int end,
AutoConfigurationMetadata autoConfigurationMetadata) {
OutcomesResolver outcomesResolver = new StandardOutcomesResolver(autoConfigurationClasses, start, end,
autoConfigurationMetadata, getBeanClassLoader());
@ -112,8 +114,9 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -112,8 +114,9 @@ class OnClassCondition extends FilteringSpringBootCondition {
return ConditionOutcome.match(matchMessage);
}
private List<String> getCandidates(AnnotatedTypeMetadata metadata, Class<?> annotationType) {
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(annotationType.getName(), true);
private @Nullable List<String> getCandidates(AnnotatedTypeMetadata metadata, Class<?> annotationType) {
MultiValueMap<String, @Nullable Object> attributes = metadata
.getAllAnnotationAttributes(annotationType.getName(), true);
if (attributes == null) {
return null;
}
@ -123,7 +126,7 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -123,7 +126,7 @@ class OnClassCondition extends FilteringSpringBootCondition {
return candidates;
}
private void addAll(List<String> list, List<Object> itemsToAdd) {
private void addAll(List<String> list, @Nullable List<@Nullable Object> itemsToAdd) {
if (itemsToAdd != null) {
for (Object item : itemsToAdd) {
Collections.addAll(list, (String[]) item);
@ -133,7 +136,7 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -133,7 +136,7 @@ class OnClassCondition extends FilteringSpringBootCondition {
private interface OutcomesResolver {
ConditionOutcome[] resolveOutcomes();
@Nullable ConditionOutcome[] resolveOutcomes();
}
@ -141,9 +144,9 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -141,9 +144,9 @@ class OnClassCondition extends FilteringSpringBootCondition {
private final Thread thread;
private volatile ConditionOutcome[] outcomes;
private volatile @Nullable ConditionOutcome @Nullable [] outcomes;
private volatile Throwable failure;
private volatile @Nullable Throwable failure;
private ThreadedOutcomesResolver(OutcomesResolver outcomesResolver) {
this.thread = new Thread(() -> {
@ -158,7 +161,7 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -158,7 +161,7 @@ class OnClassCondition extends FilteringSpringBootCondition {
}
@Override
public ConditionOutcome[] resolveOutcomes() {
public @Nullable ConditionOutcome[] resolveOutcomes() {
try {
this.thread.join();
}
@ -169,7 +172,7 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -169,7 +172,7 @@ class OnClassCondition extends FilteringSpringBootCondition {
if (failure != null) {
ReflectionUtils.rethrowRuntimeException(failure);
}
ConditionOutcome[] outcomes = this.outcomes;
@Nullable ConditionOutcome[] outcomes = this.outcomes;
return (outcomes != null) ? outcomes : new ConditionOutcome[0];
}
@ -177,7 +180,7 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -177,7 +180,7 @@ class OnClassCondition extends FilteringSpringBootCondition {
private static final class StandardOutcomesResolver implements OutcomesResolver {
private final String[] autoConfigurationClasses;
private final @Nullable String[] autoConfigurationClasses;
private final int start;
@ -187,7 +190,7 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -187,7 +190,7 @@ class OnClassCondition extends FilteringSpringBootCondition {
private final ClassLoader beanClassLoader;
private StandardOutcomesResolver(String[] autoConfigurationClasses, int start, int end,
private StandardOutcomesResolver(@Nullable String[] autoConfigurationClasses, int start, int end,
AutoConfigurationMetadata autoConfigurationMetadata, ClassLoader beanClassLoader) {
this.autoConfigurationClasses = autoConfigurationClasses;
this.start = start;
@ -197,13 +200,13 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -197,13 +200,13 @@ class OnClassCondition extends FilteringSpringBootCondition {
}
@Override
public ConditionOutcome[] resolveOutcomes() {
public @Nullable ConditionOutcome[] resolveOutcomes() {
return getOutcomes(this.autoConfigurationClasses, this.start, this.end, this.autoConfigurationMetadata);
}
private ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses, int start, int end,
AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionOutcome[] outcomes = new ConditionOutcome[end - start];
private @Nullable ConditionOutcome[] getOutcomes(@Nullable String[] autoConfigurationClasses, int start,
int end, AutoConfigurationMetadata autoConfigurationMetadata) {
@Nullable ConditionOutcome[] outcomes = new ConditionOutcome[end - start];
for (int i = start; i < end; i++) {
String autoConfigurationClass = autoConfigurationClasses[i];
if (autoConfigurationClass != null) {
@ -216,7 +219,7 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -216,7 +219,7 @@ class OnClassCondition extends FilteringSpringBootCondition {
return outcomes;
}
private ConditionOutcome getOutcome(String candidates) {
private @Nullable ConditionOutcome getOutcome(String candidates) {
try {
if (!candidates.contains(",")) {
return getOutcome(candidates, this.beanClassLoader);
@ -234,7 +237,7 @@ class OnClassCondition extends FilteringSpringBootCondition { @@ -234,7 +237,7 @@ class OnClassCondition extends FilteringSpringBootCondition {
return null;
}
private ConditionOutcome getOutcome(String className, ClassLoader classLoader) {
private @Nullable ConditionOutcome getOutcome(String className, ClassLoader classLoader) {
if (ClassNameFilter.MISSING.matches(className, classLoader)) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class)
.didNotFind("required class")

8
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnCloudPlatformCondition.java

@ -18,11 +18,14 @@ package org.springframework.boot.autoconfigure.condition; @@ -18,11 +18,14 @@ package org.springframework.boot.autoconfigure.condition;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.Assert;
/**
* {@link Condition} that checks for a required {@link CloudPlatform}.
@ -34,8 +37,11 @@ class OnCloudPlatformCondition extends SpringBootCondition { @@ -34,8 +37,11 @@ class OnCloudPlatformCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnCloudPlatform.class.getName());
Map<String, @Nullable Object> attributes = metadata
.getAnnotationAttributes(ConditionalOnCloudPlatform.class.getName());
Assert.state(attributes != null, "'attributes' must not be null");
CloudPlatform cloudPlatform = (CloudPlatform) attributes.get("value");
Assert.state(cloudPlatform != null, "'cloudPlatform' must not be null");
return getMatchOutcome(context.getEnvironment(), cloudPlatform);
}

12
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java

@ -16,6 +16,10 @@ @@ -16,6 +16,10 @@
package org.springframework.boot.autoconfigure.condition;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@ -24,6 +28,7 @@ import org.springframework.context.expression.StandardBeanExpressionResolver; @@ -24,6 +28,7 @@ import org.springframework.context.expression.StandardBeanExpressionResolver;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.Assert;
/**
* A Condition that evaluates a SpEL expression.
@ -37,8 +42,11 @@ class OnExpressionCondition extends SpringBootCondition { @@ -37,8 +42,11 @@ class OnExpressionCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
String expression = (String) metadata.getAnnotationAttributes(ConditionalOnExpression.class.getName())
.get("value");
Map<String, @Nullable Object> attributes = metadata
.getAnnotationAttributes(ConditionalOnExpression.class.getName());
Assert.state(attributes != null, "'attributes' must not be null");
String expression = (String) attributes.get("value");
Assert.state(expression != null, "'expression' must not be null");
expression = wrapIfNecessary(expression);
ConditionMessage.Builder messageBuilder = ConditionMessage.forCondition(ConditionalOnExpression.class,
"(" + expression + ")");

8
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnJavaCondition.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.condition; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.condition;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava.Range;
import org.springframework.boot.system.JavaVersion;
import org.springframework.context.annotation.Condition;
@ -25,6 +27,7 @@ import org.springframework.context.annotation.ConditionContext; @@ -25,6 +27,7 @@ import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.Assert;
/**
* {@link Condition} that checks for a required version of Java.
@ -40,9 +43,12 @@ class OnJavaCondition extends SpringBootCondition { @@ -40,9 +43,12 @@ class OnJavaCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnJava.class.getName());
Map<String, @Nullable Object> attributes = metadata.getAnnotationAttributes(ConditionalOnJava.class.getName());
Assert.state(attributes != null, "'attributes' must not be null");
Range range = (Range) attributes.get("range");
Assert.state(range != null, "'range' must not be null");
JavaVersion version = (JavaVersion) attributes.get("value");
Assert.state(version != null, "'version' must not be null");
return getMatchOutcome(range, JVM_VERSION, version);
}

10
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnJndiCondition.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.condition; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.condition;
import javax.naming.NamingException;
import org.jspecify.annotations.Nullable;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.Ordered;
@ -26,6 +28,7 @@ import org.springframework.core.annotation.Order; @@ -26,6 +28,7 @@ import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.jndi.JndiLocatorDelegate;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -39,9 +42,10 @@ class OnJndiCondition extends SpringBootCondition { @@ -39,9 +42,10 @@ class OnJndiCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
AnnotationAttributes annotationAttributes = AnnotationAttributes
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(metadata.getAnnotationAttributes(ConditionalOnJndi.class.getName()));
String[] locations = annotationAttributes.getStringArray("value");
Assert.state(attributes != null, "'attributes' must not be null");
String[] locations = attributes.getStringArray("value");
try {
return getMatchOutcome(locations);
}
@ -88,7 +92,7 @@ class OnJndiCondition extends SpringBootCondition { @@ -88,7 +92,7 @@ class OnJndiCondition extends SpringBootCondition {
this.locations = locations;
}
public String lookupFirstLocation() {
public @Nullable String lookupFirstLocation() {
for (String location : this.locations) {
try {
lookup(location);

14
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnPropertyCondition.java

@ -22,6 +22,8 @@ import java.util.Arrays; @@ -22,6 +22,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
@ -129,10 +131,16 @@ class OnPropertyCondition extends SpringBootCondition { @@ -129,10 +131,16 @@ class OnPropertyCondition extends SpringBootCondition {
this.annotationType = annotationType;
this.prefix = (!annotationAttributes.containsKey("prefix")) ? "" : getPrefix(annotationAttributes);
this.names = getNames(annotationAttributes);
this.havingValue = annotationAttributes.get("havingValue").toString();
this.havingValue = getHavingValue(annotationAttributes);
this.matchIfMissing = annotationAttributes.getBoolean("matchIfMissing");
}
private static String getHavingValue(AnnotationAttributes annotationAttributes) {
Object havingValue = annotationAttributes.get("havingValue");
Assert.state(havingValue != null, "'havingValue' must not be null");
return havingValue.toString();
}
private String getPrefix(AnnotationAttributes annotationAttributes) {
String prefix = annotationAttributes.getString("prefix").trim();
if (StringUtils.hasText(prefix) && !prefix.endsWith(".")) {
@ -144,6 +152,8 @@ class OnPropertyCondition extends SpringBootCondition { @@ -144,6 +152,8 @@ class OnPropertyCondition extends SpringBootCondition {
private String[] getNames(AnnotationAttributes annotationAttributes) {
String[] value = (String[]) annotationAttributes.get("value");
String[] name = (String[]) annotationAttributes.get("name");
Assert.state(value != null, "'value' must not be null");
Assert.state(name != null, "'name' must not be null");
Assert.state(value.length > 0 || name.length > 0,
() -> "The name or value attribute of @%s must be specified"
.formatted(ClassUtils.getShortName(this.annotationType)));
@ -169,7 +179,7 @@ class OnPropertyCondition extends SpringBootCondition { @@ -169,7 +179,7 @@ class OnPropertyCondition extends SpringBootCondition {
}
}
private boolean isMatch(String value, String requiredValue) {
private boolean isMatch(@Nullable String value, String requiredValue) {
if (StringUtils.hasLength(requiredValue)) {
return requiredValue.equalsIgnoreCase(value);
}

20
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnResourceCondition.java

@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.condition; @@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.condition;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
@ -40,11 +42,14 @@ class OnResourceCondition extends SpringBootCondition { @@ -40,11 +42,14 @@ class OnResourceCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attributes = metadata
MultiValueMap<String, @Nullable Object> attributes = metadata
.getAllAnnotationAttributes(ConditionalOnResource.class.getName(), true);
Assert.state(attributes != null, "'attributes' must not be null");
ResourceLoader loader = context.getResourceLoader();
List<String> locations = new ArrayList<>();
collectValues(locations, attributes.get("resources"));
List<@Nullable Object> resources = attributes.get("resources");
Assert.state(resources != null, "'resources' must not be null");
collectValues(locations, resources);
Assert.state(!locations.isEmpty(),
"@ConditionalOnResource annotations must specify at least one resource location");
List<String> missing = new ArrayList<>();
@ -64,10 +69,13 @@ class OnResourceCondition extends SpringBootCondition { @@ -64,10 +69,13 @@ class OnResourceCondition extends SpringBootCondition {
.items(locations));
}
private void collectValues(List<String> names, List<Object> values) {
for (Object value : values) {
for (Object item : (Object[]) value) {
names.add((String) item);
private void collectValues(List<String> names, List<@Nullable Object> resources) {
for (Object resource : resources) {
Object[] items = (Object[]) resource;
if (items != null) {
for (Object item : items) {
names.add((String) item);
}
}
}
}

8
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnThreadingCondition.java

@ -18,11 +18,14 @@ package org.springframework.boot.autoconfigure.condition; @@ -18,11 +18,14 @@ package org.springframework.boot.autoconfigure.condition;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.thread.Threading;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.Assert;
/**
* {@link Condition} that checks for a required {@link Threading}.
@ -34,8 +37,11 @@ class OnThreadingCondition extends SpringBootCondition { @@ -34,8 +37,11 @@ class OnThreadingCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnThreading.class.getName());
Map<String, @Nullable Object> attributes = metadata
.getAnnotationAttributes(ConditionalOnThreading.class.getName());
Assert.state(attributes != null, "'attributes' must not be null");
Threading threading = (Threading) attributes.get("value");
Assert.state(threading != null, "'threading' must not be null");
return getMatchOutcome(context.getEnvironment(), threading);
}

16
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWebApplicationCondition.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.condition; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.condition;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.web.context.reactive.ConfigurableReactiveWebEnvironment;
@ -27,6 +29,7 @@ import org.springframework.context.annotation.ConditionContext; @@ -27,6 +29,7 @@ import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.ConfigurableWebEnvironment;
@ -49,9 +52,9 @@ class OnWebApplicationCondition extends FilteringSpringBootCondition { @@ -49,9 +52,9 @@ class OnWebApplicationCondition extends FilteringSpringBootCondition {
private static final String REACTIVE_WEB_APPLICATION_CLASS = "org.springframework.web.reactive.HandlerResult";
@Override
protected ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
protected @Nullable ConditionOutcome[] getOutcomes(@Nullable String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
@Nullable ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
for (int i = 0; i < outcomes.length; i++) {
String autoConfigurationClass = autoConfigurationClasses[i];
if (autoConfigurationClass != null) {
@ -62,7 +65,7 @@ class OnWebApplicationCondition extends FilteringSpringBootCondition { @@ -62,7 +65,7 @@ class OnWebApplicationCondition extends FilteringSpringBootCondition {
return outcomes;
}
private ConditionOutcome getOutcome(String type) {
private @Nullable ConditionOutcome getOutcome(@Nullable String type) {
if (type == null) {
return null;
}
@ -157,9 +160,12 @@ class OnWebApplicationCondition extends FilteringSpringBootCondition { @@ -157,9 +160,12 @@ class OnWebApplicationCondition extends FilteringSpringBootCondition {
}
private Type deduceType(AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnWebApplication.class.getName());
Map<String, @Nullable Object> attributes = metadata
.getAnnotationAttributes(ConditionalOnWebApplication.class.getName());
if (attributes != null) {
return (Type) attributes.get("type");
Object type = attributes.get("type");
Assert.state(type != null, "'type' must not be null");
return (Type) type;
}
return Type.ANY;
}

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* {@code @Condition} annotations and supporting classes.
*/
@NullMarked
package org.springframework.boot.autoconfigure.condition;
import org.jspecify.annotations.NullMarked;

10
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/container/ContainerImageMetadata.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.container;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.AttributeAccessor;
@ -29,7 +31,7 @@ import org.springframework.core.AttributeAccessor; @@ -29,7 +31,7 @@ import org.springframework.core.AttributeAccessor;
* @author Phillip Webb
* @since 3.4.0
*/
public record ContainerImageMetadata(String imageName) {
public record ContainerImageMetadata(@Nullable String imageName) {
static final String NAME = ContainerImageMetadata.class.getName();
@ -37,7 +39,7 @@ public record ContainerImageMetadata(String imageName) { @@ -37,7 +39,7 @@ public record ContainerImageMetadata(String imageName) {
* Add this container image metadata to the given attributes.
* @param attributes the attributes to add the metadata to
*/
public void addTo(AttributeAccessor attributes) {
public void addTo(@Nullable AttributeAccessor attributes) {
if (attributes != null) {
attributes.setAttribute(NAME, this);
}
@ -49,7 +51,7 @@ public record ContainerImageMetadata(String imageName) { @@ -49,7 +51,7 @@ public record ContainerImageMetadata(String imageName) {
* @param attributes the attributes to check
* @return if metadata is present
*/
public static boolean isPresent(AttributeAccessor attributes) {
public static boolean isPresent(@Nullable AttributeAccessor attributes) {
return getFrom(attributes) != null;
}
@ -59,7 +61,7 @@ public record ContainerImageMetadata(String imageName) { @@ -59,7 +61,7 @@ public record ContainerImageMetadata(String imageName) {
* @param attributes the attributes
* @return the metadata or {@code null}
*/
public static ContainerImageMetadata getFrom(AttributeAccessor attributes) {
public static @Nullable ContainerImageMetadata getFrom(@Nullable AttributeAccessor attributes) {
return (attributes != null) ? (ContainerImageMetadata) attributes.getAttribute(NAME) : null;
}

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Support classes related to auto-configuration involving containers.
*/
@NullMarked
package org.springframework.boot.autoconfigure.container;
import org.jspecify.annotations.NullMarked;

8
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java

@ -22,6 +22,8 @@ import java.time.Duration; @@ -22,6 +22,8 @@ import java.time.Duration;
import java.util.List;
import java.util.Properties;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.boot.autoconfigure.AutoConfiguration;
@ -92,7 +94,7 @@ public final class MessageSourceAutoConfiguration { @@ -92,7 +94,7 @@ public final class MessageSourceAutoConfiguration {
return messageSource;
}
private Properties loadCommonMessages(List<Resource> resources) {
private @Nullable Properties loadCommonMessages(@Nullable List<Resource> resources) {
if (CollectionUtils.isEmpty(resources)) {
return null;
}
@ -135,7 +137,7 @@ public final class MessageSourceAutoConfiguration { @@ -135,7 +137,7 @@ public final class MessageSourceAutoConfiguration {
return ConditionOutcome.noMatch(message.didNotFind("bundle with basename " + basename).atAll());
}
private Resource[] getResources(ClassLoader classLoader, String name) {
private Resource[] getResources(@Nullable ClassLoader classLoader, String name) {
String target = name.replace('.', '/');
try {
return new PathMatchingResourcePatternResolver(classLoader)
@ -151,7 +153,7 @@ public final class MessageSourceAutoConfiguration { @@ -151,7 +153,7 @@ public final class MessageSourceAutoConfiguration {
static class MessageSourceRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
hints.resources().registerPattern("messages.properties").registerPattern("messages_*.properties");
}

14
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java

@ -23,6 +23,8 @@ import java.time.temporal.ChronoUnit; @@ -23,6 +23,8 @@ import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;
import org.springframework.core.io.Resource;
@ -49,7 +51,7 @@ public class MessageSourceProperties { @@ -49,7 +51,7 @@ public class MessageSourceProperties {
/**
* List of locale-independent property file resources containing common messages.
*/
private List<Resource> commonMessages;
private @Nullable List<Resource> commonMessages;
/**
* Message bundles encoding.
@ -61,7 +63,7 @@ public class MessageSourceProperties { @@ -61,7 +63,7 @@ public class MessageSourceProperties {
* forever. If a duration suffix is not specified, seconds will be used.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration cacheDuration;
private @Nullable Duration cacheDuration;
/**
* Whether to fall back to the system Locale if no files for a specific Locale have
@ -98,11 +100,11 @@ public class MessageSourceProperties { @@ -98,11 +100,11 @@ public class MessageSourceProperties {
this.encoding = encoding;
}
public Duration getCacheDuration() {
public @Nullable Duration getCacheDuration() {
return this.cacheDuration;
}
public void setCacheDuration(Duration cacheDuration) {
public void setCacheDuration(@Nullable Duration cacheDuration) {
this.cacheDuration = cacheDuration;
}
@ -130,11 +132,11 @@ public class MessageSourceProperties { @@ -130,11 +132,11 @@ public class MessageSourceProperties {
this.useCodeAsDefaultMessage = useCodeAsDefaultMessage;
}
public List<Resource> getCommonMessages() {
public @Nullable List<Resource> getCommonMessages() {
return this.commonMessages;
}
public void setCommonMessages(List<Resource> commonMessages) {
public void setCommonMessages(@Nullable List<Resource> commonMessages) {
this.commonMessages = commonMessages;
}

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for the Spring context.
*/
@NullMarked
package org.springframework.boot.autoconfigure.context;
import org.jspecify.annotations.NullMarked;

11
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/AbstractRepositoryConfigurationSourceSupport.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.data; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.data;
import java.lang.annotation.Annotation;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@ -48,15 +50,18 @@ import org.springframework.data.util.Streamable; @@ -48,15 +50,18 @@ import org.springframework.data.util.Streamable;
public abstract class AbstractRepositoryConfigurationSourceSupport
implements ImportBeanDefinitionRegistrar, BeanFactoryAware, ResourceLoaderAware, EnvironmentAware {
@SuppressWarnings("NullAway.Init")
private ResourceLoader resourceLoader;
@SuppressWarnings("NullAway.Init")
private BeanFactory beanFactory;
@SuppressWarnings("NullAway.Init")
private Environment environment;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
@Nullable BeanNameGenerator importBeanNameGenerator) {
RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(
getConfigurationSource(registry, importBeanNameGenerator), this.resourceLoader, this.environment);
delegate.registerRepositoriesIn(registry, getRepositoryConfigurationExtension());
@ -68,7 +73,7 @@ public abstract class AbstractRepositoryConfigurationSourceSupport @@ -68,7 +73,7 @@ public abstract class AbstractRepositoryConfigurationSourceSupport
}
private AnnotationRepositoryConfigurationSource getConfigurationSource(BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
@Nullable BeanNameGenerator importBeanNameGenerator) {
AnnotationMetadata metadata = AnnotationMetadata.introspect(getConfiguration());
return new AutoConfiguredAnnotationRepositoryConfigurationSource(metadata, getAnnotation(), this.resourceLoader,
this.environment, registry, importBeanNameGenerator) {
@ -129,7 +134,7 @@ public abstract class AbstractRepositoryConfigurationSourceSupport @@ -129,7 +134,7 @@ public abstract class AbstractRepositoryConfigurationSourceSupport
AutoConfiguredAnnotationRepositoryConfigurationSource(AnnotationMetadata metadata,
Class<? extends Annotation> annotation, ResourceLoader resourceLoader, Environment environment,
BeanDefinitionRegistry registry, BeanNameGenerator generator) {
BeanDefinitionRegistry registry, @Nullable BeanNameGenerator generator) {
super(metadata, annotation, resourceLoader, environment, registry, generator);
}

13
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/OnRepositoryTypeCondition.java

@ -19,12 +19,15 @@ package org.springframework.boot.autoconfigure.data; @@ -19,12 +19,15 @@ package org.springframework.boot.autoconfigure.data;
import java.util.Locale;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.Assert;
/**
* {@link SpringBootCondition} for controlling what type of Spring Data repositories are
@ -36,10 +39,14 @@ class OnRepositoryTypeCondition extends SpringBootCondition { @@ -36,10 +39,14 @@ class OnRepositoryTypeCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnRepositoryType.class.getName(),
true);
RepositoryType configuredType = getTypeProperty(context.getEnvironment(), (String) attributes.get("store"));
Map<String, @Nullable Object> attributes = metadata
.getAnnotationAttributes(ConditionalOnRepositoryType.class.getName(), true);
Assert.state(attributes != null, "'attributes' must not be null");
String store = (String) attributes.get("store");
Assert.state(store != null, "'store' must not be null");
RepositoryType configuredType = getTypeProperty(context.getEnvironment(), store);
RepositoryType requiredType = (RepositoryType) attributes.get("type");
Assert.state(requiredType != null, "'requiredType' must not be null");
ConditionMessage.Builder message = ConditionMessage.forCondition(ConditionalOnRepositoryType.class);
if (configuredType == requiredType || configuredType == RepositoryType.AUTO) {
return ConditionOutcome

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration base classes for Spring Data.
*/
@NullMarked
package org.springframework.boot.autoconfigure.data;
import org.jspecify.annotations.NullMarked;

23
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/diagnostics/analyzer/NoSuchBeanDefinitionFailureAnalyzer.java

@ -25,6 +25,8 @@ import java.util.List; @@ -25,6 +25,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.InjectionPoint;
@ -74,7 +76,8 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz @@ -74,7 +76,8 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz
}
@Override
protected FailureAnalysis analyze(Throwable rootFailure, NoSuchBeanDefinitionException cause, String description) {
protected @Nullable FailureAnalysis analyze(Throwable rootFailure, NoSuchBeanDefinitionException cause,
@Nullable String description) {
if (cause.getNumberOfBeansFound() != 0) {
return null;
}
@ -118,7 +121,9 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz @@ -118,7 +121,9 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz
}
private Class<?> extractBeanType(ResolvableType resolvableType) {
return resolvableType.getRawClass();
Class<?> rawClass = resolvableType.getRawClass();
Assert.state(rawClass != null, "'rawClass' must not be null");
return rawClass;
}
private List<AutoConfigurationResult> getAutoConfigurationResults(NoSuchBeanDefinitionException cause) {
@ -140,7 +145,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz @@ -140,7 +145,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz
.toList();
}
private MethodMetadata getFactoryMethodMetadata(String beanName) {
private @Nullable MethodMetadata getFactoryMethodMetadata(String beanName) {
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition(beanName);
if (beanDefinition instanceof AnnotatedBeanDefinition annotatedBeanDefinition) {
return annotatedBeanDefinition.getFactoryMethodMetadata();
@ -183,7 +188,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz @@ -183,7 +188,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz
}
}
private InjectionPoint findInjectionPoint(Throwable failure) {
private @Nullable InjectionPoint findInjectionPoint(Throwable failure) {
UnsatisfiedDependencyException unsatisfiedDependencyException = findCause(failure,
UnsatisfiedDependencyException.class);
if (unsatisfiedDependencyException == null) {
@ -196,7 +201,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz @@ -196,7 +201,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz
private final String className;
private final String methodName;
private final @Nullable String methodName;
Source(String source) {
String[] tokens = source.split("#");
@ -208,7 +213,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz @@ -208,7 +213,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz
return this.className;
}
String getMethodName() {
@Nullable String getMethodName() {
return this.methodName;
}
@ -252,7 +257,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz @@ -252,7 +257,7 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz
}
private boolean hasName(MethodMetadata methodMetadata, String name) {
Map<String, Object> attributes = methodMetadata.getAnnotationAttributes(Bean.class.getName());
Map<String, @Nullable Object> attributes = methodMetadata.getAnnotationAttributes(Bean.class.getName());
String[] candidates = (attributes != null) ? (String[]) attributes.get("name") : null;
if (candidates != null) {
for (String candidate : candidates) {
@ -309,11 +314,11 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz @@ -309,11 +314,11 @@ class NoSuchBeanDefinitionFailureAnalyzer extends AbstractInjectionFailureAnalyz
private static class UserConfigurationResult {
private final MethodMetadata methodMetadata;
private final @Nullable MethodMetadata methodMetadata;
private final boolean nullBean;
UserConfigurationResult(MethodMetadata methodMetadata, boolean nullBean) {
UserConfigurationResult(@Nullable MethodMetadata methodMetadata, boolean nullBean) {
this.methodMetadata = methodMetadata;
this.nullBean = nullBean;
}

3
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/diagnostics/analyzer/package-info.java

@ -18,4 +18,7 @@ @@ -18,4 +18,7 @@
* Internal {@link org.springframework.boot.diagnostics.FailureAnalyzer} implementations
* related to auto-configuration.
*/
@NullMarked
package org.springframework.boot.autoconfigure.diagnostics.analyzer;
import org.jspecify.annotations.NullMarked;

1
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java

@ -139,6 +139,7 @@ public class EntityScanPackages { @@ -139,6 +139,7 @@ public class EntityScanPackages {
private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(metadata.getAnnotationAttributes(EntityScan.class.getName()));
Assert.state(attributes != null, "'attributes' must not be null");
Set<String> packagesToScan = new LinkedHashSet<>();
for (String basePackage : attributes.getStringArray("basePackages")) {
String[] tokenized = StringUtils.tokenizeToStringArray(

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanner.java

@ -72,7 +72,9 @@ public class EntityScanner { @@ -72,7 +72,9 @@ public class EntityScanner {
for (String basePackage : packages) {
if (StringUtils.hasText(basePackage)) {
for (BeanDefinition candidate : scanner.findCandidateComponents(basePackage)) {
entitySet.add(ClassUtils.forName(candidate.getBeanClassName(), this.context.getClassLoader()));
String beanClassName = candidate.getBeanClassName();
Assert.state(beanClassName != null, "'beanClassName' must not be null");
entitySet.add(ClassUtils.forName(beanClassName, this.context.getClassLoader()));
}
}
}

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* General purpose domain annotations and classes.
*/
@NullMarked
package org.springframework.boot.autoconfigure.domain;
import org.jspecify.annotations.NullMarked;

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.java

@ -20,6 +20,8 @@ import java.io.IOException; @@ -20,6 +20,8 @@ import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Properties;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
@ -85,7 +87,7 @@ public final class ProjectInfoAutoConfiguration { @@ -85,7 +87,7 @@ public final class ProjectInfoAutoConfiguration {
return target;
}
private Properties loadSource(Resource location, Charset encoding) throws IOException {
private Properties loadSource(Resource location, @Nullable Charset encoding) throws IOException {
if (encoding != null) {
return PropertiesLoaderUtils.loadProperties(new EncodedResource(location, encoding));
}

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for project information.
*/
@NullMarked
package org.springframework.boot.autoconfigure.info;
import org.jspecify.annotations.NullMarked;

5
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java

@ -34,6 +34,7 @@ import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; @@ -34,6 +34,7 @@ import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
import org.springframework.jmx.export.annotation.AnnotationMBeanExporter;
import org.springframework.jmx.export.naming.ObjectNamingStrategy;
import org.springframework.jmx.support.MBeanServerFactoryBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -94,7 +95,9 @@ public final class JmxAutoConfiguration { @@ -94,7 +95,9 @@ public final class JmxAutoConfiguration {
MBeanServerFactoryBean factory = new MBeanServerFactoryBean();
factory.setLocateExistingServerIfPossible(true);
factory.afterPropertiesSet();
return factory.getObject();
MBeanServer mBeanServer = factory.getObject();
Assert.state(mBeanServer != null, "'mBeanServer' must not be null");
return mBeanServer;
}
}

8
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxProperties.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.jmx;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.jmx.support.RegistrationPolicy;
@ -46,7 +48,7 @@ public class JmxProperties { @@ -46,7 +48,7 @@ public class JmxProperties {
/**
* JMX domain name.
*/
private String defaultDomain;
private @Nullable String defaultDomain;
/**
* JMX Registration policy.
@ -77,11 +79,11 @@ public class JmxProperties { @@ -77,11 +79,11 @@ public class JmxProperties {
this.server = server;
}
public String getDefaultDomain() {
public @Nullable String getDefaultDomain() {
return this.defaultDomain;
}
public void setDefaultDomain(String defaultDomain) {
public void setDefaultDomain(@Nullable String defaultDomain) {
this.defaultDomain = defaultDomain;
}

13
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategy.java

@ -21,6 +21,8 @@ import java.util.Hashtable; @@ -21,6 +21,8 @@ import java.util.Hashtable;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@ -28,6 +30,7 @@ import org.springframework.jmx.export.metadata.JmxAttributeSource; @@ -28,6 +30,7 @@ import org.springframework.jmx.export.metadata.JmxAttributeSource;
import org.springframework.jmx.export.naming.MetadataNamingStrategy;
import org.springframework.jmx.support.JmxUtils;
import org.springframework.jmx.support.ObjectNameManager;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
@ -39,6 +42,7 @@ import org.springframework.util.ObjectUtils; @@ -39,6 +42,7 @@ import org.springframework.util.ObjectUtils;
*/
public class ParentAwareNamingStrategy extends MetadataNamingStrategy implements ApplicationContextAware {
@SuppressWarnings("NullAway.Init")
private ApplicationContext applicationContext;
private boolean ensureUniqueRuntimeObjectNames;
@ -62,7 +66,7 @@ public class ParentAwareNamingStrategy extends MetadataNamingStrategy implements @@ -62,7 +66,7 @@ public class ParentAwareNamingStrategy extends MetadataNamingStrategy implements
}
@Override
public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException {
public ObjectName getObjectName(Object managedBean, @Nullable String beanKey) throws MalformedObjectNameException {
ObjectName name = super.getObjectName(managedBean, beanKey);
if (this.ensureUniqueRuntimeObjectNames) {
return JmxUtils.appendIdentityToObjectName(name, managedBean);
@ -73,12 +77,15 @@ public class ParentAwareNamingStrategy extends MetadataNamingStrategy implements @@ -73,12 +77,15 @@ public class ParentAwareNamingStrategy extends MetadataNamingStrategy implements
return name;
}
private boolean parentContextContainsSameBean(ApplicationContext context, String beanKey) {
private boolean parentContextContainsSameBean(ApplicationContext context, @Nullable String beanKey) {
if (context.getParent() == null) {
return false;
}
try {
this.applicationContext.getParent().getBean(beanKey);
ApplicationContext parent = this.applicationContext.getParent();
Assert.state(parent != null, "'parent' must not be null");
Assert.state(beanKey != null, "'beanKey' must not be null");
parent.getBean(beanKey);
return true;
}
catch (BeansException ex) {

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for JMX.
*/
@NullMarked
package org.springframework.boot.autoconfigure.jmx;
import org.jspecify.annotations.NullMarked;

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListener.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.logging; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.logging;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.logging.LogLevel;
@ -124,7 +126,7 @@ public class ConditionEvaluationReportLoggingListener @@ -124,7 +126,7 @@ public class ConditionEvaluationReportLoggingListener
}
@Override
public boolean supportsSourceType(Class<?> sourceType) {
public boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}

5
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingProcessor.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.logging;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@ -31,7 +33,8 @@ import org.springframework.boot.logging.LogLevel; @@ -31,7 +33,8 @@ import org.springframework.boot.logging.LogLevel;
class ConditionEvaluationReportLoggingProcessor implements BeanFactoryInitializationAotProcessor {
@Override
public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) {
public @Nullable BeanFactoryInitializationAotContribution processAheadOfTime(
ConfigurableListableBeanFactory beanFactory) {
logConditionEvaluationReport(beanFactory);
return null;
}

2
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportMessage.java

@ -27,6 +27,7 @@ import java.util.Set; @@ -27,6 +27,7 @@ import java.util.Set;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcomes;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@ -133,6 +134,7 @@ public class ConditionEvaluationReportMessage { @@ -133,6 +134,7 @@ public class ConditionEvaluationReportMessage {
Map<String, ConditionAndOutcomes> result = new LinkedHashMap<>();
for (String shortName : shortNames) {
List<String> fullyQualifiedNames = map.get(shortName);
Assert.state(fullyQualifiedNames != null, "'fullyQualifiedNames' must not be null");
if (fullyQualifiedNames.size() > 1) {
fullyQualifiedNames
.forEach((fullyQualifiedName) -> result.put(fullyQualifiedName, outcomes.get(fullyQualifiedName)));

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for logging.
*/
@NullMarked
package org.springframework.boot.autoconfigure.logging;
import org.jspecify.annotations.NullMarked;

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

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

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Capabilities to preinitialize code in the background to improve startup performance.
*/
@NullMarked
package org.springframework.boot.autoconfigure.preinitialize;
import org.jspecify.annotations.NullMarked;

8
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/service/connection/ConnectionDetailsFactories.java

@ -26,6 +26,7 @@ import java.util.stream.Stream; @@ -26,6 +26,7 @@ import java.util.stream.Stream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
@ -53,7 +54,7 @@ public class ConnectionDetailsFactories { @@ -53,7 +54,7 @@ public class ConnectionDetailsFactories {
* @param classLoader the class loader used to load factories
* @since 3.5.0
*/
public ConnectionDetailsFactories(ClassLoader classLoader) {
public ConnectionDetailsFactories(@Nullable ClassLoader classLoader) {
this(SpringFactoriesLoader.forDefaultResourceLocation(classLoader));
}
@ -126,9 +127,10 @@ public class ConnectionDetailsFactories { @@ -126,9 +127,10 @@ public class ConnectionDetailsFactories {
ConnectionDetailsFactory<S, D> factory) {
@SuppressWarnings("unchecked")
private static <S, D extends ConnectionDetails> Registration<S, D> get(ConnectionDetailsFactory<S, D> factory) {
private static <S, D extends ConnectionDetails> @Nullable Registration<S, D> get(
ConnectionDetailsFactory<S, D> factory) {
ResolvableType type = ResolvableType.forClass(ConnectionDetailsFactory.class, factory.getClass());
Class<?>[] generics = type.resolveGenerics();
@Nullable Class<?>[] generics = type.resolveGenerics();
Class<S> sourceType = (Class<S>) generics[0];
Class<D> connectionDetailsType = (Class<D>) generics[1];
return (sourceType != null && connectionDetailsType != null)

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/service/connection/ConnectionDetailsFactory.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.service.connection;
import org.jspecify.annotations.Nullable;
/**
* A factory to create {@link ConnectionDetails} from a given {@code source}.
* Implementations should be registered in {@code META-INF/spring.factories}.
@ -36,6 +38,6 @@ public interface ConnectionDetailsFactory<S, D extends ConnectionDetails> { @@ -36,6 +38,6 @@ public interface ConnectionDetailsFactory<S, D extends ConnectionDetails> {
* @param source the source
* @return the connection details or {@code null}
*/
D getConnectionDetails(S source);
@Nullable D getConnectionDetails(S source);
}

3
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/service/connection/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Support for service connections that affect auto-configuration.
*/
@NullMarked
package org.springframework.boot.autoconfigure.service.connection;
import org.jspecify.annotations.NullMarked;

5
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/BundleContentProperty.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.ssl; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.ssl;
import java.nio.file.Path;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ssl.pem.PemContent;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@ -33,7 +35,7 @@ import org.springframework.util.StringUtils; @@ -33,7 +35,7 @@ import org.springframework.util.StringUtils;
* @author Phillip Webb
* @author Moritz Halbritter
*/
record BundleContentProperty(String name, String value) {
record BundleContentProperty(String name, @Nullable String value) {
/**
* Return if the property value is PEM content.
@ -54,6 +56,7 @@ record BundleContentProperty(String name, String value) { @@ -54,6 +56,7 @@ record BundleContentProperty(String name, String value) {
Path toWatchPath(ResourceLoader resourceLoader) {
try {
Assert.state(!isPemContent(), "Value contains PEM content");
Assert.state(this.value != null, "Value must not be null");
Resource resource = resourceLoader.getResource(this.value);
if (!resource.isFile()) {
throw new BundleContentNotWatchableException(this);

17
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/CertificateMatcher.java

@ -26,6 +26,8 @@ import java.security.cert.Certificate; @@ -26,6 +26,8 @@ import java.security.cert.Certificate;
import java.util.List;
import java.util.Objects;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
/**
@ -47,17 +49,18 @@ class CertificateMatcher { @@ -47,17 +49,18 @@ class CertificateMatcher {
private final Signature signature;
private final byte[] generatedSignature;
private final byte @Nullable [] generatedSignature;
CertificateMatcher(PrivateKey privateKey) {
Assert.notNull(privateKey, "'privateKey' must not be null");
this.privateKey = privateKey;
this.signature = createSignature(privateKey);
Assert.state(this.signature != null, "Failed to create signature");
this.generatedSignature = sign(this.signature, privateKey);
Signature signature = createSignature(privateKey);
Assert.state(signature != null, "Failed to create signature");
this.signature = signature;
this.generatedSignature = sign(signature, privateKey);
}
private Signature createSignature(PrivateKey privateKey) {
private @Nullable Signature createSignature(PrivateKey privateKey) {
try {
String algorithm = getSignatureAlgorithm(privateKey);
return (algorithm != null) ? Signature.getInstance(algorithm) : null;
@ -67,7 +70,7 @@ class CertificateMatcher { @@ -67,7 +70,7 @@ class CertificateMatcher {
}
}
private static String getSignatureAlgorithm(PrivateKey privateKey) {
private static @Nullable String getSignatureAlgorithm(PrivateKey privateKey) {
// https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html#signature-algorithms
// https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html#keypairgenerator-algorithms
return switch (privateKey.getAlgorithm()) {
@ -103,7 +106,7 @@ class CertificateMatcher { @@ -103,7 +106,7 @@ class CertificateMatcher {
}
}
private static byte[] sign(Signature signature, PrivateKey privateKey) {
private static byte @Nullable [] sign(Signature signature, PrivateKey privateKey) {
try {
signature.initSign(privateKey);
signature.update(DATA);

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/FileWatcher.java

@ -39,6 +39,7 @@ import java.util.concurrent.TimeUnit; @@ -39,6 +39,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage;
import org.springframework.util.Assert;
@ -57,7 +58,7 @@ class FileWatcher implements Closeable { @@ -57,7 +58,7 @@ class FileWatcher implements Closeable {
private final Object lock = new Object();
private WatcherThread thread;
private @Nullable WatcherThread thread;
/**
* Create a new {@link FileWatcher} instance.
@ -241,6 +242,7 @@ class FileWatcher implements Closeable { @@ -241,6 +242,7 @@ class FileWatcher implements Closeable {
Path directory = (Path) key.watchable();
for (WatchEvent<?> event : key.pollEvents()) {
Path file = directory.resolve((Path) event.context());
Assert.state(registrations != null, "'registrations' must not be null");
for (Registration registration : registrations) {
if (registration.manages(file)) {
actions.add(registration.action());

26
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/JksSslBundleProperties.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.ssl;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ssl.jks.JksSslStoreBundle;
/**
@ -54,52 +56,52 @@ public class JksSslBundleProperties extends SslBundleProperties { @@ -54,52 +56,52 @@ public class JksSslBundleProperties extends SslBundleProperties {
/**
* Type of the store to create, e.g. JKS.
*/
private String type;
private @Nullable String type;
/**
* Provider for the store.
*/
private String provider;
private @Nullable String provider;
/**
* Location of the resource containing the store content.
*/
private String location;
private @Nullable String location;
/**
* Password used to access the store.
*/
private String password;
private @Nullable String password;
public String getType() {
public @Nullable String getType() {
return this.type;
}
public void setType(String type) {
public void setType(@Nullable String type) {
this.type = type;
}
public String getProvider() {
public @Nullable String getProvider() {
return this.provider;
}
public void setProvider(String provider) {
public void setProvider(@Nullable String provider) {
this.provider = provider;
}
public String getLocation() {
public @Nullable String getLocation() {
return this.location;
}
public void setLocation(String location) {
public void setLocation(@Nullable String location) {
this.location = location;
}
public String getPassword() {
public @Nullable String getPassword() {
return this.password;
}
public void setPassword(String password) {
public void setPassword(@Nullable String password) {
this.password = password;
}

26
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PemSslBundleProperties.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.ssl;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ssl.pem.PemSslStoreBundle;
/**
@ -55,57 +57,57 @@ public class PemSslBundleProperties extends SslBundleProperties { @@ -55,57 +57,57 @@ public class PemSslBundleProperties extends SslBundleProperties {
/**
* Type of the store to create, e.g. JKS.
*/
private String type;
private @Nullable String type;
/**
* Location or content of the certificate or certificate chain in PEM format.
*/
private String certificate;
private @Nullable String certificate;
/**
* Location or content of the private key in PEM format.
*/
private String privateKey;
private @Nullable String privateKey;
/**
* Password used to decrypt an encrypted private key.
*/
private String privateKeyPassword;
private @Nullable String privateKeyPassword;
/**
* Whether to verify that the private key matches the public key.
*/
private boolean verifyKeys;
public String getType() {
public @Nullable String getType() {
return this.type;
}
public void setType(String type) {
public void setType(@Nullable String type) {
this.type = type;
}
public String getCertificate() {
public @Nullable String getCertificate() {
return this.certificate;
}
public void setCertificate(String certificate) {
public void setCertificate(@Nullable String certificate) {
this.certificate = certificate;
}
public String getPrivateKey() {
public @Nullable String getPrivateKey() {
return this.privateKey;
}
public void setPrivateKey(String privateKey) {
public void setPrivateKey(@Nullable String privateKey) {
this.privateKey = privateKey;
}
public String getPrivateKeyPassword() {
public @Nullable String getPrivateKeyPassword() {
return this.privateKeyPassword;
}
public void setPrivateKeyPassword(String privateKeyPassword) {
public void setPrivateKeyPassword(@Nullable String privateKeyPassword) {
this.privateKeyPassword = privateKeyPassword;
}

21
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java

@ -16,6 +16,12 @@ @@ -16,6 +16,12 @@
package org.springframework.boot.autoconfigure.ssl;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.ssl.SslBundleProperties.Key;
import org.springframework.boot.io.ApplicationResourceLoader;
import org.springframework.boot.ssl.SslBundle;
@ -60,11 +66,11 @@ public final class PropertiesSslBundle implements SslBundle { @@ -60,11 +66,11 @@ public final class PropertiesSslBundle implements SslBundle {
this.managers = SslManagerBundle.from(this.stores, this.key);
}
private static SslBundleKey asSslKeyReference(Key key) {
private static SslBundleKey asSslKeyReference(@Nullable Key key) {
return (key != null) ? SslBundleKey.of(key.getPassword(), key.getAlias()) : SslBundleKey.NONE;
}
private static SslOptions asSslOptions(SslBundleProperties.Options options) {
private static SslOptions asSslOptions(SslBundleProperties.@Nullable Options options) {
return (options != null) ? SslOptions.of(options.getCiphers(), options.getEnabledProtocols()) : SslOptions.NONE;
}
@ -120,13 +126,18 @@ public final class PropertiesSslBundle implements SslBundle { @@ -120,13 +126,18 @@ public final class PropertiesSslBundle implements SslBundle {
return new PropertiesSslBundle(storeBundle, properties);
}
private static PemSslStore getPemSslStore(String propertyName, PemSslBundleProperties.Store properties,
private static @Nullable PemSslStore getPemSslStore(String propertyName, PemSslBundleProperties.Store properties,
ResourceLoader resourceLoader) {
PemSslStoreDetails details = asPemSslStoreDetails(properties);
PemSslStore pemSslStore = PemSslStore.load(details, resourceLoader);
if (properties.isVerifyKeys()) {
CertificateMatcher certificateMatcher = new CertificateMatcher(pemSslStore.privateKey());
Assert.state(certificateMatcher.matchesAny(pemSslStore.certificates()),
Assert.state(pemSslStore != null, "'pemSslStore' must not be null");
PrivateKey privateKey = pemSslStore.privateKey();
Assert.state(privateKey != null, "'privateKey' must not be null");
CertificateMatcher certificateMatcher = new CertificateMatcher(privateKey);
List<X509Certificate> certificates = pemSslStore.certificates();
Assert.state(certificates != null, "'certificates' must not be null");
Assert.state(certificateMatcher.matchesAny(certificates),
() -> "Private key in %s matches none of the certificates in the chain".formatted(propertyName));
}
return pemSslStore;

26
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/SslBundleProperties.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.ssl; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.ssl;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.ssl.SslBundle;
/**
@ -79,26 +81,26 @@ public abstract class SslBundleProperties { @@ -79,26 +81,26 @@ public abstract class SslBundleProperties {
/**
* Supported SSL ciphers.
*/
private Set<String> ciphers;
private @Nullable Set<String> ciphers;
/**
* Enabled SSL protocols.
*/
private Set<String> enabledProtocols;
private @Nullable Set<String> enabledProtocols;
public Set<String> getCiphers() {
public @Nullable Set<String> getCiphers() {
return this.ciphers;
}
public void setCiphers(Set<String> ciphers) {
public void setCiphers(@Nullable Set<String> ciphers) {
this.ciphers = ciphers;
}
public Set<String> getEnabledProtocols() {
public @Nullable Set<String> getEnabledProtocols() {
return this.enabledProtocols;
}
public void setEnabledProtocols(Set<String> enabledProtocols) {
public void setEnabledProtocols(@Nullable Set<String> enabledProtocols) {
this.enabledProtocols = enabledProtocols;
}
@ -109,26 +111,26 @@ public abstract class SslBundleProperties { @@ -109,26 +111,26 @@ public abstract class SslBundleProperties {
/**
* The password used to access the key in the key store.
*/
private String password;
private @Nullable String password;
/**
* The alias that identifies the key in the key store.
*/
private String alias;
private @Nullable String alias;
public String getPassword() {
public @Nullable String getPassword() {
return this.password;
}
public void setPassword(String password) {
public void setPassword(@Nullable String password) {
this.password = password;
}
public String getAlias() {
public @Nullable String getAlias() {
return this.alias;
}
public void setAlias(String alias) {
public void setAlias(@Nullable String alias) {
this.alias = alias;
}

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for SSL bundles.
*/
@NullMarked
package org.springframework.boot.autoconfigure.ssl;
import org.jspecify.annotations.NullMarked;

14
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.task; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.task;
import java.time.Duration;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
@ -86,7 +88,7 @@ public class TaskExecutionProperties { @@ -86,7 +88,7 @@ public class TaskExecutionProperties {
* Set the maximum number of parallel accesses allowed. -1 indicates no
* concurrency limit at all.
*/
private Integer concurrencyLimit;
private @Nullable Integer concurrencyLimit;
public boolean isRejectTasksWhenLimitReached() {
return this.rejectTasksWhenLimitReached;
@ -96,11 +98,11 @@ public class TaskExecutionProperties { @@ -96,11 +98,11 @@ public class TaskExecutionProperties {
this.rejectTasksWhenLimitReached = rejectTasksWhenLimitReached;
}
public Integer getConcurrencyLimit() {
public @Nullable Integer getConcurrencyLimit() {
return this.concurrencyLimit;
}
public void setConcurrencyLimit(Integer concurrencyLimit) {
public void setConcurrencyLimit(@Nullable Integer concurrencyLimit) {
this.concurrencyLimit = concurrencyLimit;
}
@ -215,7 +217,7 @@ public class TaskExecutionProperties { @@ -215,7 +217,7 @@ public class TaskExecutionProperties {
/**
* Maximum time the executor should wait for remaining tasks to complete.
*/
private Duration awaitTerminationPeriod;
private @Nullable Duration awaitTerminationPeriod;
public boolean isAwaitTermination() {
return this.awaitTermination;
@ -225,11 +227,11 @@ public class TaskExecutionProperties { @@ -225,11 +227,11 @@ public class TaskExecutionProperties {
this.awaitTermination = awaitTermination;
}
public Duration getAwaitTerminationPeriod() {
public @Nullable Duration getAwaitTerminationPeriod() {
return this.awaitTerminationPeriod;
}
public void setAwaitTerminationPeriod(Duration awaitTerminationPeriod) {
public void setAwaitTerminationPeriod(@Nullable Duration awaitTerminationPeriod) {
this.awaitTerminationPeriod = awaitTerminationPeriod;
}

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java

@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.task; @@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.task;
import java.util.List;
import java.util.concurrent.Executor;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@ -54,7 +56,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @@ -54,7 +56,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
*/
class TaskExecutorConfigurations {
private static TaskDecorator getTaskDecorator(ObjectProvider<TaskDecorator> taskDecorator) {
private static @Nullable TaskDecorator getTaskDecorator(ObjectProvider<TaskDecorator> taskDecorator) {
List<TaskDecorator> taskDecorators = taskDecorator.orderedStream().toList();
if (taskDecorators.size() == 1) {
return taskDecorators.get(0);

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations.java

@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.task; @@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.task;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -45,7 +47,7 @@ import org.springframework.scheduling.config.TaskManagementConfigUtils; @@ -45,7 +47,7 @@ import org.springframework.scheduling.config.TaskManagementConfigUtils;
*/
class TaskSchedulingConfigurations {
private static TaskDecorator getTaskDecorator(ObjectProvider<TaskDecorator> taskDecorator) {
private static @Nullable TaskDecorator getTaskDecorator(ObjectProvider<TaskDecorator> taskDecorator) {
List<TaskDecorator> taskDecorators = taskDecorator.orderedStream().toList();
if (taskDecorators.size() == 1) {
return taskDecorators.get(0);

14
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingProperties.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.task; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.task;
import java.time.Duration;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
@ -84,13 +86,13 @@ public class TaskSchedulingProperties { @@ -84,13 +86,13 @@ public class TaskSchedulingProperties {
* Set the maximum number of parallel accesses allowed. -1 indicates no
* concurrency limit at all.
*/
private Integer concurrencyLimit;
private @Nullable Integer concurrencyLimit;
public Integer getConcurrencyLimit() {
public @Nullable Integer getConcurrencyLimit() {
return this.concurrencyLimit;
}
public void setConcurrencyLimit(Integer concurrencyLimit) {
public void setConcurrencyLimit(@Nullable Integer concurrencyLimit) {
this.concurrencyLimit = concurrencyLimit;
}
@ -106,7 +108,7 @@ public class TaskSchedulingProperties { @@ -106,7 +108,7 @@ public class TaskSchedulingProperties {
/**
* Maximum time the executor should wait for remaining tasks to complete.
*/
private Duration awaitTerminationPeriod;
private @Nullable Duration awaitTerminationPeriod;
public boolean isAwaitTermination() {
return this.awaitTermination;
@ -116,11 +118,11 @@ public class TaskSchedulingProperties { @@ -116,11 +118,11 @@ public class TaskSchedulingProperties {
this.awaitTermination = awaitTermination;
}
public Duration getAwaitTerminationPeriod() {
public @Nullable Duration getAwaitTerminationPeriod() {
return this.awaitTerminationPeriod;
}
public void setAwaitTerminationPeriod(Duration awaitTerminationPeriod) {
public void setAwaitTerminationPeriod(@Nullable Duration awaitTerminationPeriod) {
this.awaitTerminationPeriod = awaitTerminationPeriod;
}

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for task execution and scheduling.
*/
@NullMarked
package org.springframework.boot.autoconfigure.task;
import org.jspecify.annotations.NullMarked;

26
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProviders.java

@ -23,6 +23,8 @@ import java.util.List; @@ -23,6 +23,8 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
@ -72,7 +74,14 @@ public class TemplateAvailabilityProviders { @@ -72,7 +74,14 @@ public class TemplateAvailabilityProviders {
* @param applicationContext the source application context
*/
public TemplateAvailabilityProviders(ApplicationContext applicationContext) {
this((applicationContext != null) ? applicationContext.getClassLoader() : null);
this(getClassLoader(applicationContext));
}
private static ClassLoader getClassLoader(ApplicationContext applicationContext) {
Assert.notNull(applicationContext, "'applicationContext' must not be null");
ClassLoader classLoader = applicationContext.getClassLoader();
Assert.state(classLoader != null, "'classLoader' must not be null");
return classLoader;
}
/**
@ -107,10 +116,11 @@ public class TemplateAvailabilityProviders { @@ -107,10 +116,11 @@ public class TemplateAvailabilityProviders {
* @param applicationContext the application context
* @return a {@link TemplateAvailabilityProvider} or null
*/
public TemplateAvailabilityProvider getProvider(String view, ApplicationContext applicationContext) {
public @Nullable TemplateAvailabilityProvider getProvider(String view, ApplicationContext applicationContext) {
Assert.notNull(applicationContext, "'applicationContext' must not be null");
return getProvider(view, applicationContext.getEnvironment(), applicationContext.getClassLoader(),
applicationContext);
ClassLoader classLoader = applicationContext.getClassLoader();
Assert.state(classLoader != null, "'classLoader' must not be null");
return getProvider(view, applicationContext.getEnvironment(), classLoader, applicationContext);
}
/**
@ -121,8 +131,8 @@ public class TemplateAvailabilityProviders { @@ -121,8 +131,8 @@ public class TemplateAvailabilityProviders {
* @param resourceLoader the resource loader
* @return a {@link TemplateAvailabilityProvider} or null
*/
public TemplateAvailabilityProvider getProvider(String view, Environment environment, ClassLoader classLoader,
ResourceLoader resourceLoader) {
public @Nullable TemplateAvailabilityProvider getProvider(String view, Environment environment,
ClassLoader classLoader, ResourceLoader resourceLoader) {
Assert.notNull(view, "'view' must not be null");
Assert.notNull(environment, "'environment' must not be null");
Assert.notNull(classLoader, "'classLoader' must not be null");
@ -143,8 +153,8 @@ public class TemplateAvailabilityProviders { @@ -143,8 +153,8 @@ public class TemplateAvailabilityProviders {
return (provider != NONE) ? provider : null;
}
private TemplateAvailabilityProvider findProvider(String view, Environment environment, ClassLoader classLoader,
ResourceLoader resourceLoader) {
private @Nullable TemplateAvailabilityProvider findProvider(String view, Environment environment,
ClassLoader classLoader, ResourceLoader resourceLoader) {
for (TemplateAvailabilityProvider candidate : this.providers) {
if (candidate.isTemplateAvailable(view, environment, classLoader, resourceLoader)) {
return candidate;

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/template/TemplateRuntimeHints.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.template;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@ -27,7 +29,7 @@ import org.springframework.aot.hint.RuntimeHintsRegistrar; @@ -27,7 +29,7 @@ import org.springframework.aot.hint.RuntimeHintsRegistrar;
class TemplateRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
hints.resources().registerPatternIfPresent(classLoader, "templates", (hint) -> hint.includes("templates/**"));
}

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Base classes for template Auto-configuration.
*/
@NullMarked
package org.springframework.boot.autoconfigure.template;
import org.jspecify.annotations.NullMarked;

10
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.web;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
@ -24,6 +26,7 @@ import org.springframework.context.annotation.Condition; @@ -24,6 +26,7 @@ import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.lang.Contract;
import org.springframework.util.ClassUtils;
/**
@ -64,8 +67,13 @@ class OnEnabledResourceChainCondition extends SpringBootCondition { @@ -64,8 +67,13 @@ class OnEnabledResourceChainCondition extends SpringBootCondition {
return ConditionOutcome.noMatch(message.because("disabled"));
}
private Boolean getEnabledProperty(ConfigurableEnvironment environment, String key, Boolean defaultValue) {
@Contract("_, _, !null -> !null")
private @Nullable Boolean getEnabledProperty(ConfigurableEnvironment environment, String key,
@Nullable Boolean defaultValue) {
String name = "spring.web.resources.chain." + key + "enabled";
if (defaultValue == null) {
return environment.getProperty(name, Boolean.class);
}
return environment.getProperty(name, Boolean.class, defaultValue);
}

95
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebProperties.java

@ -21,6 +21,8 @@ import java.time.temporal.ChronoUnit; @@ -21,6 +21,8 @@ import java.time.temporal.ChronoUnit;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.convert.DurationUnit;
@ -39,7 +41,7 @@ public class WebProperties { @@ -39,7 +41,7 @@ public class WebProperties {
* Locale to use. By default, this locale is overridden by the "Accept-Language"
* header.
*/
private Locale locale;
private @Nullable Locale locale;
/**
* Define how the locale should be resolved.
@ -48,11 +50,11 @@ public class WebProperties { @@ -48,11 +50,11 @@ public class WebProperties {
private final Resources resources = new Resources();
public Locale getLocale() {
public @Nullable Locale getLocale() {
return this.locale;
}
public void setLocale(Locale locale) {
public void setLocale(@Nullable Locale locale) {
this.locale = locale;
}
@ -155,7 +157,7 @@ public class WebProperties { @@ -155,7 +157,7 @@ public class WebProperties {
* Whether to enable the Spring Resource Handling chain. By default, disabled
* unless at least one strategy has been enabled.
*/
private Boolean enabled;
private @Nullable Boolean enabled;
/**
* Whether to enable caching in the Resource chain.
@ -177,7 +179,7 @@ public class WebProperties { @@ -177,7 +179,7 @@ public class WebProperties {
* @return whether the resource chain is enabled or {@code null} if no
* specified settings are present.
*/
public Boolean getEnabled() {
public @Nullable Boolean getEnabled() {
return getEnabled(getStrategy().getFixed().isEnabled(), getStrategy().getContent().isEnabled(),
this.enabled);
}
@ -213,7 +215,8 @@ public class WebProperties { @@ -213,7 +215,8 @@ public class WebProperties {
this.customized = true;
}
static Boolean getEnabled(boolean fixedEnabled, boolean contentEnabled, Boolean chainEnabled) {
static @Nullable Boolean getEnabled(boolean fixedEnabled, boolean contentEnabled,
@Nullable Boolean chainEnabled) {
return (fixedEnabled || contentEnabled) ? Boolean.TRUE : chainEnabled;
}
@ -299,7 +302,7 @@ public class WebProperties { @@ -299,7 +302,7 @@ public class WebProperties {
/**
* Version string to use for the fixed Version Strategy.
*/
private String version;
private @Nullable String version;
public boolean isEnabled() {
return this.enabled;
@ -319,11 +322,11 @@ public class WebProperties { @@ -319,11 +322,11 @@ public class WebProperties {
this.paths = paths;
}
public String getVersion() {
public @Nullable String getVersion() {
return this.version;
}
public void setVersion(String version) {
public void setVersion(@Nullable String version) {
this.customized = true;
this.version = version;
}
@ -351,7 +354,7 @@ public class WebProperties { @@ -351,7 +354,7 @@ public class WebProperties {
* by the 'spring.web.resources.cache.cachecontrol' properties.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration period;
private @Nullable Duration period;
/**
* Cache control HTTP headers, only allows valid directive combinations.
@ -365,11 +368,11 @@ public class WebProperties { @@ -365,11 +368,11 @@ public class WebProperties {
*/
private boolean useLastModified = true;
public Duration getPeriod() {
public @Nullable Duration getPeriod() {
return this.period;
}
public void setPeriod(Duration period) {
public void setPeriod(@Nullable Duration period) {
this.customized = true;
this.period = period;
}
@ -402,169 +405,169 @@ public class WebProperties { @@ -402,169 +405,169 @@ public class WebProperties {
* suffix is not specified.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration maxAge;
private @Nullable Duration maxAge;
/**
* Indicate that the cached response can be reused only if re-validated
* with the server.
*/
private Boolean noCache;
private @Nullable Boolean noCache;
/**
* Indicate to not cache the response in any case.
*/
private Boolean noStore;
private @Nullable Boolean noStore;
/**
* Indicate that once it has become stale, a cache must not use the
* response without re-validating it with the server.
*/
private Boolean mustRevalidate;
private @Nullable Boolean mustRevalidate;
/**
* Indicate intermediaries (caches and others) that they should not
* transform the response content.
*/
private Boolean noTransform;
private @Nullable Boolean noTransform;
/**
* Indicate that any cache may store the response.
*/
private Boolean cachePublic;
private @Nullable Boolean cachePublic;
/**
* Indicate that the response message is intended for a single user and
* must not be stored by a shared cache.
*/
private Boolean cachePrivate;
private @Nullable Boolean cachePrivate;
/**
* Same meaning as the "must-revalidate" directive, except that it does
* not apply to private caches.
*/
private Boolean proxyRevalidate;
private @Nullable Boolean proxyRevalidate;
/**
* Maximum time the response can be served after it becomes stale, in
* seconds if no duration suffix is not specified.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration staleWhileRevalidate;
private @Nullable Duration staleWhileRevalidate;
/**
* Maximum time the response may be used when errors are encountered, in
* seconds if no duration suffix is not specified.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration staleIfError;
private @Nullable Duration staleIfError;
/**
* Maximum time the response should be cached by shared caches, in seconds
* if no duration suffix is not specified.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration sMaxAge;
private @Nullable Duration sMaxAge;
public Duration getMaxAge() {
public @Nullable Duration getMaxAge() {
return this.maxAge;
}
public void setMaxAge(Duration maxAge) {
public void setMaxAge(@Nullable Duration maxAge) {
this.customized = true;
this.maxAge = maxAge;
}
public Boolean getNoCache() {
public @Nullable Boolean getNoCache() {
return this.noCache;
}
public void setNoCache(Boolean noCache) {
public void setNoCache(@Nullable Boolean noCache) {
this.customized = true;
this.noCache = noCache;
}
public Boolean getNoStore() {
public @Nullable Boolean getNoStore() {
return this.noStore;
}
public void setNoStore(Boolean noStore) {
public void setNoStore(@Nullable Boolean noStore) {
this.customized = true;
this.noStore = noStore;
}
public Boolean getMustRevalidate() {
public @Nullable Boolean getMustRevalidate() {
return this.mustRevalidate;
}
public void setMustRevalidate(Boolean mustRevalidate) {
public void setMustRevalidate(@Nullable Boolean mustRevalidate) {
this.customized = true;
this.mustRevalidate = mustRevalidate;
}
public Boolean getNoTransform() {
public @Nullable Boolean getNoTransform() {
return this.noTransform;
}
public void setNoTransform(Boolean noTransform) {
public void setNoTransform(@Nullable Boolean noTransform) {
this.customized = true;
this.noTransform = noTransform;
}
public Boolean getCachePublic() {
public @Nullable Boolean getCachePublic() {
return this.cachePublic;
}
public void setCachePublic(Boolean cachePublic) {
public void setCachePublic(@Nullable Boolean cachePublic) {
this.customized = true;
this.cachePublic = cachePublic;
}
public Boolean getCachePrivate() {
public @Nullable Boolean getCachePrivate() {
return this.cachePrivate;
}
public void setCachePrivate(Boolean cachePrivate) {
public void setCachePrivate(@Nullable Boolean cachePrivate) {
this.customized = true;
this.cachePrivate = cachePrivate;
}
public Boolean getProxyRevalidate() {
public @Nullable Boolean getProxyRevalidate() {
return this.proxyRevalidate;
}
public void setProxyRevalidate(Boolean proxyRevalidate) {
public void setProxyRevalidate(@Nullable Boolean proxyRevalidate) {
this.customized = true;
this.proxyRevalidate = proxyRevalidate;
}
public Duration getStaleWhileRevalidate() {
public @Nullable Duration getStaleWhileRevalidate() {
return this.staleWhileRevalidate;
}
public void setStaleWhileRevalidate(Duration staleWhileRevalidate) {
public void setStaleWhileRevalidate(@Nullable Duration staleWhileRevalidate) {
this.customized = true;
this.staleWhileRevalidate = staleWhileRevalidate;
}
public Duration getStaleIfError() {
public @Nullable Duration getStaleIfError() {
return this.staleIfError;
}
public void setStaleIfError(Duration staleIfError) {
public void setStaleIfError(@Nullable Duration staleIfError) {
this.customized = true;
this.staleIfError = staleIfError;
}
public Duration getSMaxAge() {
public @Nullable Duration getSMaxAge() {
return this.sMaxAge;
}
public void setSMaxAge(Duration sMaxAge) {
public void setSMaxAge(@Nullable Duration sMaxAge) {
this.customized = true;
this.sMaxAge = sMaxAge;
}
public CacheControl toHttpCacheControl() {
public @Nullable CacheControl toHttpCacheControl() {
PropertyMapper map = PropertyMapper.get();
CacheControl control = createCacheControl();
map.from(this::getMustRevalidate).whenTrue().toCall(control::mustRevalidate);

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebResourcesRuntimeHints.java

@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.web; @@ -18,6 +18,8 @@ package org.springframework.boot.autoconfigure.web;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@ -33,7 +35,7 @@ public class WebResourcesRuntimeHints implements RuntimeHintsRegistrar { @@ -33,7 +35,7 @@ public class WebResourcesRuntimeHints implements RuntimeHintsRegistrar {
"public/");
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = (classLoader != null) ? classLoader : getClass().getClassLoader();
String[] locations = DEFAULT_LOCATIONS.stream()
.filter((candidate) -> classLoaderToUse.getResource(candidate) != null)

20
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/DateTimeFormatters.java

@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.web.format; @@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.web.format;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
import org.jspecify.annotations.Nullable;
import org.springframework.util.StringUtils;
/**
@ -30,13 +32,13 @@ import org.springframework.util.StringUtils; @@ -30,13 +32,13 @@ import org.springframework.util.StringUtils;
*/
public class DateTimeFormatters {
private DateTimeFormatter dateFormatter;
private @Nullable DateTimeFormatter dateFormatter;
private String datePattern;
private @Nullable String datePattern;
private DateTimeFormatter timeFormatter;
private @Nullable DateTimeFormatter timeFormatter;
private DateTimeFormatter dateTimeFormatter;
private @Nullable DateTimeFormatter dateTimeFormatter;
/**
* Configures the date format using the given {@code pattern}.
@ -77,19 +79,19 @@ public class DateTimeFormatters { @@ -77,19 +79,19 @@ public class DateTimeFormatters {
return this;
}
DateTimeFormatter getDateFormatter() {
@Nullable DateTimeFormatter getDateFormatter() {
return this.dateFormatter;
}
String getDatePattern() {
@Nullable String getDatePattern() {
return this.datePattern;
}
DateTimeFormatter getTimeFormatter() {
@Nullable DateTimeFormatter getTimeFormatter() {
return this.timeFormatter;
}
DateTimeFormatter getDateTimeFormatter() {
@Nullable DateTimeFormatter getDateTimeFormatter() {
return this.dateTimeFormatter;
}
@ -97,7 +99,7 @@ public class DateTimeFormatters { @@ -97,7 +99,7 @@ public class DateTimeFormatters {
return this.dateFormatter != null || this.timeFormatter != null || this.dateTimeFormatter != null;
}
private static DateTimeFormatter formatter(String pattern) {
private static @Nullable DateTimeFormatter formatter(String pattern) {
return StringUtils.hasText(pattern)
? DateTimeFormatter.ofPattern(pattern).withResolverStyle(ResolverStyle.SMART) : null;
}

4
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java

@ -20,6 +20,8 @@ import java.time.format.DateTimeFormatter; @@ -20,6 +20,8 @@ import java.time.format.DateTimeFormatter;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.format.datetime.DateFormatterRegistrar;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
@ -79,7 +81,7 @@ public class WebConversionService extends DefaultFormattingConversionService { @@ -79,7 +81,7 @@ public class WebConversionService extends DefaultFormattingConversionService {
dateTime.registerFormatters(this);
}
private void configure(Supplier<DateTimeFormatter> supplier, Consumer<DateTimeFormatter> consumer) {
private void configure(Supplier<@Nullable DateTimeFormatter> supplier, Consumer<DateTimeFormatter> consumer) {
DateTimeFormatter formatter = supplier.get();
if (formatter != null) {
consumer.accept(formatter);

3
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/package-info.java

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Support classes for web-specific formatting.
*/
@NullMarked
package org.springframework.boot.autoconfigure.web.format;
import org.jspecify.annotations.NullMarked;

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

@ -17,4 +17,7 @@ @@ -17,4 +17,7 @@
/**
* Auto-configuration for common web concerns.
*/
@NullMarked
package org.springframework.boot.autoconfigure.web;
import org.jspecify.annotations.NullMarked;

2
core/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/template/TemplateAvailabilityProvidersTests.java

@ -73,7 +73,7 @@ class TemplateAvailabilityProvidersTests { @@ -73,7 +73,7 @@ class TemplateAvailabilityProvidersTests {
void createWhenApplicationContextIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new TemplateAvailabilityProviders((ApplicationContext) null))
.withMessageContaining("'classLoader' must not be null");
.withMessageContaining("'applicationContext' must not be null");
}
@Test

Loading…
Cancel
Save