Hi Gary, On 9.07.2025 14:35, Gary Gregory wrote: > Dare I ask my our build has Gradle horror in it?
It’s not a horror—it’s a tragedy. A well-intentioned series of events that slowly spiraled into pain: ## Episode 1: Runtime-Invisible Annotations Over the past two years, we began using several compile-time annotations with retention policy `CLASS`: * `@BaselineIgnore`: Suppresses binary compatibility warnings for changes that are technically incompatible but safe in practice—for example, removing a `public` class clearly marked as internal. * `@SuppressFBWarnings`: Suppresses SpotBugs reports for code that may appear insecure (e.g. file handling) but is verified to be safe. * `@InlineMe`: An Error Prone annotation that helps users migrate away from deprecated methods by suggesting inline replacements. These annotations are not retained at runtime, so we declared the corresponding libraries with `provided` scope, ensuring they aren't transitively exposed to downstream users. ## Episode 2: The JDK Linter Bug Despite being non-runtime annotations, the JDK’s `-Xlint:classfile` option still expects these annotations to be present at compile time. If they're missing, the linter emits warnings. This behavior seemed questionable, so I filed a bug report with the JDK team: https://bugs.openjdk.org/browse/JDK-8342833 While opinions vary on whether this check is useful, it introduced real-world complications in builds that rely on clean linter output. ## Episode 3: Build Failures and User Complaints The combination of annotations and linter sensitivity caused build failures for users compiling with strict flags like `-Xlint:all -Werror`. Example issue report and analysis: https://github.com/apache/logging-log4j2/issues/3110#issuecomment-2423586754 Although most of these annotations are in `log4j-core`—which shouldn't typically be on users' compile classpaths—many projects still include it during compilation, intentionally or not. ## Episode 4: Enter GMM Adding runtime dependencies just to silence compile-time linter warnings was not acceptable, but Maven’s limited scope model offers no good workaround. As a result, Maven users were simply told to ignore the warnings. However, for Gradle users, a better option emerged: Jendrik proposed using the Gradle Module Metadata Maven Plugin in https://github.com/apache/logging-log4j2/issues/3437 This plugin lets us publish enriched metadata that tells Gradle which dependencies are compile-only but transitive. Gradle can then resolve annotation libraries during compilation—without leaking them into the runtime classpath. ## Finale: Version 2.25.0 – Return of the Karma The plot thickened in the `2.25.0` release, when we unintentionally upgraded `spotbugs-annotations` to version `4.9.0`—a version **not compatible with Java 8**. At first glance, this seemed harmless. After all, `spotbugs-annotations` is a **compile-only** dependency. If you’re compiling with JDK 11+ and targeting Java 8, everything should be fine... right? Unfortunately, no. Due to a perfect storm of factors—including `spotbugs-annotations` publishing its own Gradle Module Metadata and our own use of the GMM plugin—Gradle users compiling for Java 8 found themselves unable to build against Log4j `2.25.0`. The issue is documented here: https://github.com/apache/logging-log4j2/issues/3754 So despite our best intentions, trying to improve metadata fidelity ended up triggering build failures for a portion of our users. The karma of well-meant tooling struck back. Scene, Piotr