Skip to content

removeUnusedImports strips @NonNull import on interface-override methods (HandlerInterceptor, WebMvcConfigurer) #1389

@geminiyellow

Description

@geminiyellow

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 unaffectedOncePerRequestFilter 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

  1. Create a class implementing HandlerInterceptor with @NonNull on preHandle parameters.
  2. Run google-java-format on the file.
  3. Observe the import org.springframework.lang.NonNull; is stripped.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions