Today I tried to migrate our application to Spring Boot 4.0.0.

The first compilation failure is from Mono.map, which cannot accept a nullable result in the function.

@Bean
fun auditorAware(): ReactiveAuditorAware<String> = ReactiveAuditorAware<String> {
    ReactiveSecurityContextHolder.getContext()
        .map { it.authentication }
        .filter { it.isAuthenticated }
        .map { it.name }
        .switchIfEmpty { Mono.empty() }
}

The code above will cause a compiler error like this.

Return type mismatch: expected 'Any', actual 'Authentication?'

I am not sure which projects(reactor or Spring) add the null-safe annotation NonNull to the function in the Mono.map.

If I changed .map { it.authentication } to .map { it.authentication as Authentication}, the compilation is passed.

But obviously, we assume it is nullable here.

Comment From: bclozel

This is a type in the reactor project. And I believe the behavior here is correct. Null values are not allowed in reactive pipelines.

Comment From: sdeleuze

Yeah the behavior is correct, you may want to use mapNotNull for such use case.

If you are using NullAway, be aware of https://github.com/uber/NullAway/issues/1290 that may force you to suppress related warnings or cast the lambda until it is fixed.

Comment From: hantsy

I just upgraded my project to Spring Boot 4.0.0, a lot of similar codes are not complied. I did not configure nullAway, it could be from Spring Boot or Kotlin compiler.

From the Javadoc hint in IDE, Mono.map(@NonNull Function<....>)(in contrast, the mapNotNull, the result is marked as @NonNUll), and the two parameters in the Function are not marked as @NonNull, it means the result of this Function should be nullable.

But what I need, the result is nullable (it is the truth).

Comment From: hantsy

@bclozel @sdeleuze Maybe I misused it in the past, read the doc of map and mapNotNull, I think I should use mapNotNull here instead.

Comment From: hantsy

Yeah the behavior is correct, you may want to use mapNotNull for such use case.

Yeah, mapNotNull is better for my case. But map should accept a nullable result, and throw the NPE exception.