Skip to content

fix(build): remove Spring Boot 2 Gradle plugin for Gradle 9 compatibility#5263

Draft
adinauer wants to merge 14 commits intodeps/scripts/update-gradle.shfrom
fix/spring-boot2-gradle9
Draft

fix(build): remove Spring Boot 2 Gradle plugin for Gradle 9 compatibility#5263
adinauer wants to merge 14 commits intodeps/scripts/update-gradle.shfrom
fix/spring-boot2-gradle9

Conversation

@adinauer
Copy link
Copy Markdown
Member

@adinauer adinauer commented Apr 2, 2026

📜 Description

Shadow 9.x DuplicatesStrategy fix

Shadow 9.x enforces DuplicatesStrategy before transformers (like mergeServiceFiles and AppendingTransformer) can process duplicates. This means FAIL or EXCLUDE prevents service files and Spring metadata from being merged. All shadow JAR tasks now use DuplicatesStrategy.INCLUDE to let transformers see all duplicate entries.

Spring Boot 2 Gradle plugin removal

Remove the Spring Boot 2 Gradle plugin (org.springframework.boot v2.7.18) which is incompatible with Gradle 9 due to use of removed API LenientConfiguration.getFiles().

Library modules (sentry-spring, sentry-spring-boot, sentry-spring-boot-starter):

  • These only used the plugin with apply false to access SpringBootPlugin.BOM_COORDINATES
  • Replaced with a direct BOM reference via version catalog (libs.springboot2.bom)

Sample apps (spring-boot, webflux, otel, netflix-dgs):

  • Replaced Spring Boot plugin + io.spring.dependency-management with Shadow plugin (com.gradleup.shadow) for fat JAR creation
  • Added application plugin for main class configuration
  • Uses platform(libs.springboot2.bom) for dependency version management
  • Shadow JAR configured with DuplicatesStrategy.INCLUDE + append() to merge Spring metadata files (spring.factories, spring.handlers, spring.schemas, spring-autoconfigure-metadata.properties)
  • BootRun task in otel sample replaced with standard JavaExec

OTel agent shadow JAR fix

  • sentry-opentelemetry-agent shadowJar switched from DuplicatesStrategy.FAIL to INCLUDE so mergeServiceFiles can merge inst/META-INF/services/ from the upstream OTel agent and the distro libs

System test runner

  • Auto-detects shadowJar vs bootJar build task per module
  • Fallback HTTP readiness check for shadow JAR apps (actuator web endpoints don't work in flat JARs)

Note: Spring Boot 3 and 4 plugins are unaffected — they are already Gradle 9 compatible.

💡 Motivation and Context

Stacked on top of #5063. The Spring Boot 2.7.x Gradle plugin uses LenientConfiguration.getFiles() which was removed in Gradle 9, causing bootJar and build tasks to fail. Shadow 9.x changed duplicate handling behavior requiring DuplicatesStrategy.INCLUDE for transformer-based merging to work.

💚 How did you test it?

  • ./gradlew :sentry-spring:compileJava :sentry-spring-boot:compileJava :sentry-spring-boot-starter:compileJava — passes
  • ./gradlew :sentry-spring:test — passes
  • All 5 sample shadow JARs build successfully with properly merged spring.factories (170+ lines)
  • Sample app starts, serves HTTP, detected as ready by system test runner
  • ./gradlew :sentry-opentelemetry:sentry-opentelemetry-agent:shadowJar — passes, service files properly merged
  • Verified merged service file contains entries from both upstream OTel agent and distro

📝 Checklist

  • No breaking change or entry added to the changelog.
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.

🔮 Next steps

Other Gradle 9 compatibility fixes in the parent PR.

#skip-changelog

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


This PR will not appear in the changelog.


🤖 This preview updates automatically when you update the PR.

@sentry
Copy link
Copy Markdown

sentry bot commented Apr 2, 2026

Sentry Build Distribution

App Name App ID Version Configuration Install Page
SDK Size io.sentry.tests.size 8.37.1 (1) release Install Build

Configure sentry-android build distribution settings

adinauer added 2 commits April 2, 2026 12:49
…lity

The Spring Boot 2.7.x Gradle plugin uses removed Gradle APIs
(LenientConfiguration.getFiles()) that are incompatible with Gradle 9.

Library modules (sentry-spring, sentry-spring-boot, sentry-spring-boot-starter):
- Replace SpringBootPlugin.BOM_COORDINATES with direct BOM reference
  via version catalog (libs.springboot2.bom)
- Remove the 'apply false' plugin declaration entirely

Sample apps (spring-boot, webflux, otel, netflix-dgs):
- Replace Spring Boot plugin with Shadow plugin for fat JAR creation
- Add application plugin for main class configuration
- Use platform(libs.springboot2.bom) for dependency version management
- Configure shadow JAR to merge Spring metadata files
- Replace BootRun task with JavaExec in otel sample
…erge

Shadow plugin 9.x defaults to DuplicatesStrategy.EXCLUDE, which drops
duplicate META-INF/spring.factories entries before transformers can
merge them. Setting INCLUDE allows the AppendingTransformer to see all
entries and properly concatenate spring.factories from all JARs.

Without this, the shadow JAR only contains spring.factories from a
single dependency, causing Spring Boot auto-configuration to fail
(e.g. missing RestTemplateBuilder, no embedded web server).
@adinauer adinauer force-pushed the fix/spring-boot2-gradle9 branch from 52ced43 to 9dd4f2f Compare April 2, 2026 10:49
adinauer and others added 12 commits April 2, 2026 12:50
- Auto-detect shadowJar vs bootJar build task based on build.gradle.kts
- Add fallback HTTP readiness check for shadow JAR apps that lack
  actuator endpoints (actuator web endpoints don't work in flat JARs)
- Append spring-autoconfigure-metadata.properties in shadow JAR config
Shadow 9.x enforces duplicatesStrategy before transformers run, so
DuplicatesStrategy.FAIL prevents mergeServiceFiles from merging
inst/META-INF/services/ files that exist in both the upstream OTel
agent JAR and the isolated distro libs. Switching to INCLUDE lets
the transformer see all duplicates and merge them correctly.
Shadow 9.x's ServiceFileTransformer strips the `inst/` prefix when using
`include("inst/META-INF/services/*")`, placing merged service files under
`META-INF/services/` instead of `inst/META-INF/services/`. This breaks
the OTel agent's classloader which expects isolated services under `inst/`.

Using `path = "inst/META-INF/services"` preserves the correct output path.

Also add missing `duplicatesStrategy = DuplicatesStrategy.INCLUDE` to
console-otlp, log4j2, and console-opentelemetry-noagent shadow JARs
so that mergeServiceFiles and Log4j2 transformers can see duplicates
before they are deduplicated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion

Shadow 9.x only applies package relocations to service files that are
claimed by a ServiceFileTransformer. The ContextStorageProvider service
file at META-INF/services/ was not being relocated because it wasn't
handled by any transformer — only the inst/META-INF/services/ files were.

Adding a default mergeServiceFiles() call ensures bootstrap service files
(like ContextStorageProvider) go through the transformer and get properly
relocated to their shaded paths.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lity

Shadow 9.x enforces DuplicatesStrategy before transformers run, which
breaks the `append` transformer for spring.factories and other Spring
metadata files. Only the last copy survives instead of being concatenated.

Replace `append` calls with a pre-merge task that manually concatenates
Spring metadata files (spring.factories, spring.handlers, spring.schemas,
spring-autoconfigure-metadata.properties) from the runtime classpath
before the shadow JAR is built. The merged files are included first in
the shadow JAR so they take precedence over duplicates from dependency
JARs.

This fixes the PersonSystemTest failure where @SentrySpan AOP and JDBC
instrumentation weren't working because SentryAutoConfiguration wasn't
properly registered in the merged spring.factories.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Lint 8.13.1 (set via android.experimental.lint.version) expects targetSdk 37
but we target 36. This is a test-only module so suppressing is safe.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 311.84 ms 355.26 ms 43.42 ms
Size 0 B 0 B 0 B

Baseline results on branch: deps/scripts/update-gradle.sh

Startup times

Revision Plain With Sentry Diff
7a32266 305.50 ms 364.17 ms 58.67 ms

App size

Revision Plain With Sentry Diff
7a32266 0 B 0 B 0 B

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants