Summary
google-java-format (tested with 1.25.2 and 1.35.0) incorrectly strips the org.springframework.lang.NonNull import from Java files that implement Spring interfaces which declare @NonNull on method parameters (HandlerInterceptor, WebMvcConfigurer).
Mechanism
Java parameter annotations are NOT inherited per JLS. When a class overrides an interface method that declares @NonNull on a parameter, the override must re-declare @NonNull on the same parameter for static analysis tools (NullAway, Checker Framework) to enforce nullability. The import for @NonNull is therefore necessary.
GJF's removeUnusedImports rule classifies this import as unused because it does not see the annotation as referenced at the usage site (the annotation is on the parameter of the overriding method), and strips it. After stripping, compilation fails with cannot find symbol: class NonNull.
Discriminating control case
GlobalRateLimitFilter (extends OncePerRequestFilter) is unaffected — OncePerRequestFilter does not declare @NonNull on its method parameters. The stripping only occurs when the interface declares @NonNull on the method parameter that the override is re-annotating.
Affected files / interfaces
OAuth2RateLimitInterceptor — implements org.springframework.web.servlet.HandlerInterceptor
RateLimitConfig — implements org.springframework.web.servlet.config.annotation.WebMvcConfigurer
Both implement interfaces from Spring Framework that declare @NonNull on method parameters. After spotless:apply (using GJF 1.25.2 or 1.35.0 with <removeUnusedImports/>), the import org.springframework.lang.NonNull; line is removed, causing javac to fail with cannot find symbol: class NonNull.
Reproduction
- Create a class implementing
HandlerInterceptor with @NonNull on preHandle parameters.
- Run
google-java-format on the file.
- Observe the
import org.springframework.lang.NonNull; is stripped.
- Run
javac — fails with cannot find symbol.
Version
Tested at GJF 1.25.2 and 1.35.0. Both exhibit the same behavior.
Impact
Projects using Spotless with <removeUnusedImports/> and Spring MVC interfaces with @NonNull parameters must exclude affected files from Spotless processing as a workaround.
Summary
google-java-format(tested with 1.25.2 and 1.35.0) incorrectly strips theorg.springframework.lang.NonNullimport from Java files that implement Spring interfaces which declare@NonNullon method parameters (HandlerInterceptor,WebMvcConfigurer).Mechanism
Java parameter annotations are NOT inherited per JLS. When a class overrides an interface method that declares
@NonNullon a parameter, the override must re-declare@NonNullon the same parameter for static analysis tools (NullAway, Checker Framework) to enforce nullability. The import for@NonNullis therefore necessary.GJF's
removeUnusedImportsrule classifies this import as unused because it does not see the annotation as referenced at the usage site (the annotation is on the parameter of the overriding method), and strips it. After stripping, compilation fails withcannot find symbol: class NonNull.Discriminating control case
GlobalRateLimitFilter(extendsOncePerRequestFilter) is unaffected —OncePerRequestFilterdoes not declare@NonNullon its method parameters. The stripping only occurs when the interface declares@NonNullon the method parameter that the override is re-annotating.Affected files / interfaces
OAuth2RateLimitInterceptor— implementsorg.springframework.web.servlet.HandlerInterceptorRateLimitConfig— implementsorg.springframework.web.servlet.config.annotation.WebMvcConfigurerBoth implement interfaces from Spring Framework that declare
@NonNullon method parameters. Afterspotless:apply(using GJF 1.25.2 or 1.35.0 with<removeUnusedImports/>), theimport org.springframework.lang.NonNull;line is removed, causingjavacto fail withcannot find symbol: class NonNull.Reproduction
HandlerInterceptorwith@NonNullonpreHandleparameters.google-java-formaton the file.import org.springframework.lang.NonNull;is stripped.javac— fails withcannot find symbol.Version
Tested at GJF 1.25.2 and 1.35.0. Both exhibit the same behavior.
Impact
Projects using Spotless with
<removeUnusedImports/>and Spring MVC interfaces with@NonNullparameters must exclude affected files from Spotless processing as a workaround.