Continuation of https://github.com/spring-projects/spring-boot/issues/46587.

High

  • [x] Add nullability to org.springframework.boot.json.JsonWriter (it's currently @NullUnmarked). Fixed in 06232756419462f7207174b110794f765e29541f
  • [x] Review if org.springframework.boot.metrics.autoconfigure.export.properties.PropertiesConfigAdapter.Getter is fine for us. Alternative: Rewrite with if.
  • [x] #47024 Take another look at org.springframework.boot.context.properties.PropertyMapper, especially alwaysApplyingWhenNonNull and whenNonNull (draft is in this branch)
  • [x] Run IntelliJ IDEA null checks and fix issues
  • [x] Check if org.springframework.boot.actuate.endpoint.SanitizableData#key can really be null. org.springframework.boot.actuate.endpoint.SanitizableData#getLowerCaseKey suggests so, but all the callers pass non-nullable strings.
  • [x] Review org.springframework.boot.context.config.ConfigDataLocation#of API. It's not possible to add a contract !null -> !null which makes it hard for users of that class. See #47221.

Medium

  • [x] Review org.springframework.boot.hibernate.SpringJtaPlatform#locateTransactionManager and org.springframework.boot.hibernate.SpringJtaPlatform#locateUserTransaction
  • [x] Review Mono.from(null) in org.springframework.boot.webflux.actuate.endpoint.web.AbstractWebFluxEndpointHandlerMapping.ReactiveWebOperationAdapter#handleResult
  • [x] Review Mono.error(getError(request))) in org.springframework.boot.webflux.autoconfigure.error.DefaultErrorWebExceptionHandler#renderErrorView
  • [x] Review org.springframework.boot.ResourceBanner#createNullDefaultSources. Eventually a MapPropertySource from a map containing null values is created, which shouldn't be possible according to the annotations on MapPropertySource.
  • [x] Review org.springframework.boot.context.properties.source.MapConfigurationPropertySource#put. It puts a null key in this.source, which is then used with MapPropertySource, which doesn't accept null keys (at least according to the annotations).
  • [ ] Review org.springframework.boot.test.json.JsonContentAssert#compare(java.lang.CharSequence, org.skyscreamer.jsonassert.JSONCompareMode) when passing null as first parameter
  • [x] Review map.from(this.properties::getLocale).to(configurer::setLocale); in org.springframework.boot.groovy.template.autoconfigure.GroovyTemplateAutoConfiguration.GroovyMarkupConfiguration#groovyMarkupConfigurer

Low

  • [x] Review https://github.com/spring-projects/spring-boot/commit/27c96d910986c9e282fb0bca767408185371ef44
  • [ ] Remove varargs checkstyle suppressions (needs release of https://github.com/spring-io/spring-javaformat)
  • [x] Remove suppression in graphql module once https://github.com/spring-projects/spring-graphql/issues/1276 is fixed
  • [x] Review @SuppressWarnings("NullAway") suppressions
  • [ ] Depending on https://github.com/spring-projects/spring-framework/issues/35369: Refactor SingletonSupplier usages to only use them with non-nullable suppliers
  • [x] Review the cast to AnnotationMetadata in org.springframework.boot.cache.autoconfigure.CacheCondition

To decide

  • Do we want to null-check buildSrc?
  • Do we want to null-check spring-boot-configuration-metadata?
  • Do we want to null-check spring-boot-configuration-metadata-changelog-generator?
  • Do we want to null-check / add annotations to spring-boot-docs?

Comment From: mhalbritter

When rewriting AppOpticsPropertiesConfigAdapter to ifs:

before:

    @Override
    public String apiToken() {
        return getRequired(AppOpticsProperties::getApiToken, AppOpticsConfig.super::apiToken);
    }

    @Override
    @SuppressWarnings("NullAway") // Lambda isn't detected with the correct nullability
    public @Nullable String hostTag() {
        return get(AppOpticsProperties::getHostTag, AppOpticsConfig.super::hostTag);
    }

After:

    @Override
    public String apiToken() {
        String apiToken = this.properties.getApiToken();
        return (apiToken != null) ? apiToken : AppOpticsConfig.super.apiToken();
    }

    @Override
    public @Nullable String hostTag() {
        String hostTag = this.properties.getHostTag();
        return (hostTag != null) ? hostTag : AppOpticsConfig.super.hostTag();
    }