Skip to content

Modernize build toolchain: Gradle 9, bytecode-processing tooling bumps - #888

Merged
thibauult merged 8 commits into
mainfrom
spec/modernize-build-toolchain
Aug 5, 2026
Merged

Modernize build toolchain: Gradle 9, bytecode-processing tooling bumps#888
thibauult merged 8 commits into
mainfrom
spec/modernize-build-toolchain

Conversation

@thibauult

Copy link
Copy Markdown
Member

Summary

Moves the build itself onto current tooling before the BDK 4.x branch (next) baselines Java 25. None of this was a problem on JDK 17 — it becomes a hard blocker the moment the target JDK moves, since every bytecode-processing tool in the build carries a class-file-version floor. Doing it here keeps this mechanical, low-risk diff separate from the riskier Spring Boot / JDK migrations that follow, and lets those changes start from an already-modern build.

Deliberately out of scope: Java baseline (stays 17), Spring Boot version (stays 3.5.16), OpenAPI generator version (stays 6.6.0). Each of those gets its own change (see openspec/changes/).

  • Gradle 8.14.5 → 9.6.1, plus the deprecation cleanup it forces: the removed sourceCompatibility convention replaced with an explicit Java 17 toolchain in bdk.java-common-conventions, project.buildDirlayout.buildDirectory, tasks.createtasks.register, cross-project sourceSets access fixed in both Spring Boot starter modules, and the two Spring Boot Gradle plugin versions in the example modules bumped to match the BOM.
  • Bytecode-processing tooling raised to versions supporting current class file versions: byte-buddy 1.12.19 → 1.18.11, mapstruct/mapstruct-processor 1.4.2.Final → 1.6.3, archunit-junit5 1.2.1 → 1.5.0, plus an explicit jacoco.toolVersion. The MapStruct bump produces no behavior change in the generated UserDetailMapperImpl (diffed before/after).
  • mockserver-netty 5.15.0 → 7.5.0. Checked first whether a replacement (WireMock/MockWebServer) was needed since Spring Boot 4 also moves Netty — it wasn't; 7.5.0's own POM already targets Netty 4.2. Full test suite passes unmodified across the jump.
  • Lombok pinned explicitly in symphony-bdk-bom (1.18.46, same version currently resolved transitively) instead of inheriting from spring-boot-dependencies, so a future Spring Boot bump can't move it out from under the 13 modules that use it.
  • Dead dependencies removed: javax.xml.bind:jaxb-api:2.3.1 (zero source usage) and org.projectreactor:reactor-spring:1.0.1.RELEASE (2017 artifact, no module depends on it). javax.annotation:jsr250-api was investigated for the same treatment but is load-bearing — openapi-generator's jersey2 generator emits @javax.annotation.Generated across 335+ generated classes and jakarta.annotation-api doesn't provide that package — so it was left as-is.
  • JDK 25 forward-compatibility spike (throwaway branch, not merged): with all the above bumps in place, flipping the toolchain to Java 25 and running the full build/test/coverage suite produced zero failures. Recorded in openspec/changes/modernize-build-toolchain/tasks.md so the follow-up adopt-java-25-baseline change doesn't go looking for failures that don't exist.

Removing a BOM constraint (reactor-spring) and adding one (lombok) are consumer-visible dependency-resolution changes, so this ships as 3.6.0, not a patch.

Test plan

  • ./gradlew clean build --warning-mode all — warning-free
  • ./gradlew build jacocoTestReport jacocoTestCoverageVerification — all pass, no threshold adjustments
  • ./gradlew publishToMavenLocal — verified
  • Full test suite in symphony-bdk-core and symphony-bdk-http-webclient re-run unmodified across the mockserver-netty jump
  • Generated UserDetailMapperImpl diffed before/after the MapStruct bump (cosmetic only)
  • JDK 25 toolchain spike run on a throwaway branch with all tooling bumps in place

Bumps the wrapper to Gradle 9.6.1 and clears every deprecation/incompatibility
that surfaced along the way:

- Replace the removed project-level sourceCompatibility convention with a
  Java toolchain pinned at 17 in bdk.java-common-conventions, and add an
  explicit jacoco.toolVersion instead of relying on the Gradle-bundled default.
- Replace project.buildDir with layout.buildDirectory, and the two
  tasks.create(...) calls in symphony-bdk-core's apisToGenerate loop with
  tasks.register(...).
- Fix cross-project project(':x').sourceSets access in the two Spring Boot
  starter modules: dynamic property forwarding on ProjectDependency was
  removed in Gradle 9, so these now use a top-level project(...) accessor
  plus evaluationDependsOn.
- Bump com.github.ben-manes.versions 0.42.0 -> 0.54.0 (0.42.0 calls a
  LenientConfiguration API removed in Gradle 9).
- Bump the org.springframework.boot Gradle plugin in the two example modules
  (3.2.2, 3.5.4 -> 3.5.16) to match the BOM's existing spring-boot-dependencies
  constraint; both predated Gradle 9 support. No Spring Boot runtime version
  change.
- Fix the remaining deprecation warnings surfaced by
  --warning-mode all: Project.getProperties() -> findProperty, implicit
  parent-project property lookup of projectVersion, and Groovy
  space-assignment syntax in the two publishing blocks.

openapi-generator-gradle-plugin:6.6.0 and org.owasp.dependencycheck:12.2.2
both work under Gradle 9 unchanged (verified via generateAgent and a full
build). `./gradlew clean build --warning-mode all` is warning-free.
byte-buddy 1.12.19 -> 1.18.11 and mapstruct/mapstruct-processor
1.4.2.Final -> 1.6.3 in symphony-bdk-core, archunit-junit5 1.2.1 -> 1.5.0
in the BOM. All three read/write/instrument bytecode and need a floor
that supports class file version 69 ahead of the eventual Java 25 move.

The MapStruct bump produces no behaviour change in the generated
UserDetailMapperImpl (diffed before/after: only cosmetic import
qualification and the @generated comment differ). All 3 architecture
tests and jacocoTestCoverageVerification pass across every module with
no threshold adjustments.

assertj-core stays at 3.27.7, already the latest stable release.
D3 assumed a stale MockServer would need replacing (WireMock/OkHttp
MockWebServer) since it embeds Netty, which Spring Boot 4 also moves.
Checked first: mockserver-netty:7.5.0's own POM documents it now depends
on Netty 4.2, so a straight bump avoids being a version-conflict source
in two future migrations without the cost of rewriting test infrastructure.

Ran the full test suite in symphony-bdk-core and symphony-bdk-http-webclient
unmodified across the 5.x -> 7.x jump: all pass. The org.mockserver.* surface
in use (BdkMockServer/BdkMockServerExtension test helpers) is limited to
ClientAndServer.startClientAndServer(), HttpRequest/HttpResponse builders,
and basic when/respond wiring -- stable across that range.
Removes two artifacts with zero source usage anywhere in the tree:

- javax.xml.bind:jaxb-api:2.3.1 from symphony-bdk-core (verified: no
  javax.xml.bind reference anywhere in the codebase).
- org.projectreactor:reactor-spring:1.0.1.RELEASE from symphony-bdk-bom
  (a 2017 artifact that no module declares as a dependency, so the BOM
  constraint was inert).

Also adds an explicit org.projectlombok:lombok constraint to the BOM,
pinned at 1.18.46 -- the same version currently resolved from
spring-boot-dependencies:3.5.16, so this changes nothing today. It stops
a future Spring Boot bump from moving Lombok implicitly: Lombok is used
in 13 modules and lags JDK releases, so its version needs to move on its
own schedule.

javax.annotation:jsr250-api:1.0 was also proposed for removal/replacement
but turned out to be load-bearing: openapi-generator's java/jersey2
generator emits fully-qualified @javax.annotation.Generated across 335+
generated classes, and jakarta.annotation-api only provides
jakarta.annotation.Generated (a different package) -- swapping it broke
the build with 36 compile errors. Left as-is; see tasks.md 6.2 for the
full empirical trace.

Removing a BOM constraint is a consumer-visible dependency-resolution
change and ships as 3.6.0, not a patch.
Verified on a throwaway branch (discarded, not merged): flipping
bdk.java-common-conventions' toolchain to JavaLanguageVersion.of(25) and
running the full build/test/coverage suite produces zero failures, with
every tooling bump from this change already in place. Gradle 9.6.1
auto-detects the JDK 25 toolchain with no foojay-resolver plugin needed.

adopt-java-25-baseline's task 1.2 expects a residual failure list from
this spike as its starting inventory -- it's empty. Recorded here so that
change doesn't go looking for failures that don't exist.
Verifies the CI command and publishToMavenLocal are green with all of
this change's tooling bumps in place, drafts the 3.6.0 release notes
covering the two consumer-visible BOM changes (reactor-spring removed,
Lombok now pinned directly), and updates CLAUDE.md with the Gradle 9
daemon JVM requirement (17+) and the toolchain-vs-daemon JVM distinction.
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

SNAPSHOT published: PR-888-SNAPSHOT
Repository: https://central.sonatype.com/repository/maven-snapshots/

Change: modernize-build-toolchain
Schema: spec-driven
Archived to: openspec/changes/archive/2026-08-05-modernize-build-toolchain/
Specs: ✓ Synced — created new capability spec openspec/specs/build-toolchain/spec.md (5 requirements, since no prior main spec existed for this capability)

All artifacts complete (proposal, design, specs, tasks). All 35 tasks complete. No warnings.

@symphony-enrico symphony-enrico left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@thibauult
thibauult merged commit 0f4e0e6 into main Aug 5, 2026
5 checks passed
@thibauult
thibauult deleted the spec/modernize-build-toolchain branch August 5, 2026 15:07
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.

2 participants