Skip to content

Isolate Spring Boot <3.5 apps in smoke-tests subprojects for Gradle 9 compatibility#11379

Draft
bric3 wants to merge 7 commits into
masterfrom
bdu/smoke-tests-gradle-forward-compat
Draft

Isolate Spring Boot <3.5 apps in smoke-tests subprojects for Gradle 9 compatibility#11379
bric3 wants to merge 7 commits into
masterfrom
bdu/smoke-tests-gradle-forward-compat

Conversation

@bric3
Copy link
Copy Markdown
Contributor

@bric3 bric3 commented May 15, 2026

What Does This Do

Isolates Spring Boot <3.5 application subprojects in their own Gradle 8.14.5 subprocess, making smoke tests compatible with the main project's Gradle 9 build.

Three patterns of change:

  • Pattern D (kafkaschemaregistry): removed a Spring Boot plugin that was never used (module uses shadowJar, not bootJar).
  • Pattern B (6 modules: spring-boot-2.7-webflux, spring-boot-3.0-webflux, spring-boot-3.0-webmvc, spring-boot-3.0-native, spring-boot-3.3-webmvc, kafka-3): already had an application/ subproject; added a Gradle 8.14.5 wrapper and updated the parent Exec task to invoke application/gradlew instead of the root gradlew.
  • Pattern C (12 modules: springboot-thymeleaf, springboot-freemarker, springboot-velocity, springboot-java-11, springboot-java-17, springboot-jpa, springboot-tomcat, springboot-tomcat-jsp, springboot-jetty-jsp, openfeature, and others): migrated application source from src/main/ into a new application/ subproject with its own build.gradle, settings.gradle, and Gradle 8.14.5 wrapper.

Cross-project artifact dependencies (e.g. iast-util-11, dd-trace-api, feature-flagging-api) are forwarded as -PfooJar=<path> properties to the child build and consumed with if (hasProperty('fooJar')) { implementation files(property('fooJar')) }.

Motivation

Spring Boot Gradle plugin <3.5.0 calls Configuration.getUploadTaskName(), which was removed in Gradle 9. This causes a NoSuchMethodError at configuration time — before any task runs — making it impossible to load a Gradle 9 build that includes such a project.

Since these smoke tests exist specifically to test older Spring Boot versions, upgrading is not an option. See #10402 for the original compatibility analysis.

Additional Notes

Build isolation — Each application now runs in a fully isolated Gradle process. The Spring Boot plugin no longer pollutes the main build's configuration phase. The Exec tasks are input-tracked and cacheable (outputs.cacheIf { true }), so they are skipped when sources haven't changed.

Debugging — Build failures in child processes surface as Process finished with non-zero exit value 1 in the parent. Pass --info to the top-level Gradle invocation to see the child's output, or cd application/ && ./gradlew bootJar directly. This was already the case for the Pattern B modules that existed before this PR — all smoke test modules now follow the same pattern.

Maintainability — Each application/ subproject carries a gradle-wrapper.properties pinned to Gradle 8.14.5. These subprojects target stable, legacy Spring Boot versions unlikely to need further Gradle upgrades, so their wrapper version should remain stable. New smoke tests targeting Spring Boot 3.5+ can use the main Gradle 9 build directly without this isolation layer.

Contributor Checklist

Jira ticket: [PROJ-IDENT]

Note: Once your PR is ready to merge, add it to the merge queue by commenting /merge. /merge -c cancels the queue request. /merge -f --reason "reason" skips all merge queue checks; please use this judiciously, as some checks do not run at the PR-level. For more information, see this doc.

tag: no release note
tag: ai generated

bric3 and others added 6 commits May 13, 2026 17:37
profiling-controller-openjdk used
  files(project(':...:profiling-controller-jfr').sourceSets.test.output)

In Gradle 8 this worked: inside the `dependencies` closure,
`project(':foo')` resolved via `Project.project(String)` -- which is a
Groovy DSL lookup fallback, since `DependencyHandler` had no
`project(String)` method -- returning the real `Project` -- which has
the `sourceSets` property.

Gradle 9.5 added `DependencyHandler.project(String)` that returns a
`ProjectDependency`, which Groovy now resolves first. The instance is a
`DefaultProjectDependency`, which has no `sourceSets` property, and
as such fails with:

```
> Could not get unknown property 'sourceSets' for project ':dd-java-agent:agent-profiling:profiling-controller-jfr' of type org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency.
```

This commit instead rely on the java-test-fixtures plugin applied
to profiling-controller-jfr to share test resources, consumer projects
now declare : testFixtures(project(':...:profiling-controller-jfr')).
Gradle 9.5 added `DependencyHandler.project(String)` returning a
`ProjectDependency`, shadowing `Project.project(String)` in
`dependencies` closures. Since `ProjectDependency` implementation do
not has a `sourceSets` property it fails the build.

The goal of using `files(project(':foo').sourceSets.test.output)` is to
share test code in other projects which is supported by the test
java-test-fixtures plugin that is already applied to the `:mongo-common`
project. Also the nine mongo driver/test consumers already declared the
correct `testFixtures(project(':...:mongo-common'))` so this commit
drops the now-broken duplicate `sourceSets.test.output` dependency
declarations.
…registry

The kafkaschemaregistry smoke test had `id 'org.springframework.boot'` in its
plugins block even though it builds with the shadow plugin, not bootJar. The
Spring Boot Gradle plugin calls `Configuration.getUploadTaskName()` during
configuration, a method removed in Gradle 9, causing a NoSuchMethodError at
build time regardless of whether bootJar is used.

Since the module only needs shadowJar, removing the plugin and its companion
`spring-boot-plugin.gradle` apply is sufficient to restore Gradle 9
compatibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ion subprojects

The Spring Boot Gradle plugin calls `Configuration.getUploadTaskName()` which
was removed in Gradle 9. This affects every Spring Boot plugin version before
3.5.0. Six smoke test modules already follow the two-layer pattern (an inner
`application/` project built by an `Exec` task in the outer module) but still
delegated to the root project's `gradlew`, which now points to Gradle 9.

For each of these modules, give the `application/` subproject its own
Gradle 8.14.5 wrapper and update the parent `build.gradle` to invoke
`$appDir/gradlew` instead of `$rootDir/gradlew`:

- spring-boot-2.7-webflux  (Spring Boot 2.7.4)
- spring-boot-3.0-webflux  (Spring Boot 3.0.0)
- spring-boot-3.0-webmvc   (Spring Boot 3.0.0)
- spring-boot-3.0-native   (Spring Boot 3.0.0 + GraalVM)
- spring-boot-3.3-webmvc   (Spring Boot 3.3.5)
- kafka-3                  (Spring Boot 3.2.2)

The `.gitignore` files inside each `application/` directory previously
excluded `gradlew` and `gradle/` because those were never committed. Those
entries are removed so the new wrapper files can be tracked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@bric3 bric3 added tag: no release notes Changes to exclude from release notes comp: tooling Build & Tooling tag: ai generated Largely based on code generated by an AI or LLM labels May 15, 2026
@bric3 bric3 changed the title build(smoke-tests): isolate Spring Boot <3.5 apps in Gradle 8 subprojects for Gradle 9 compatibility Isolate Spring Boot <3.5 apps in smoke-tests subprojects for Gradle 9 compatibility May 15, 2026
…e Gradle 8 subprojects

The Spring Boot Gradle plugin is incompatible with Gradle 9 for all versions
before 3.5.0 because it calls `Configuration.getUploadTaskName()`, a method
removed in Gradle 9.

Twelve smoke-test modules were direct Gradle subprojects that applied the
Spring Boot plugin to build their bootJar/bootWar artefact. They cannot stay
as subprojects of the Gradle 9 root build.

For each of these modules, the application source is extracted into a new
`application/` subdirectory that is a fully self-contained Gradle project
(settings.gradle + build.gradle + Gradle 8.14.5 wrapper). The outer module
keeps the test source and delegates the application build via an `Exec` task
that invokes `application/gradlew`.

Modules converted (bootJar):
- springboot-thymeleaf   (Spring Boot 2.7.15, Java 8)
- springboot-freemarker  (Spring Boot 2.7.15 plugin / 1.5.18 starter, Java 8)
- springboot-velocity    (Spring Boot 2.7.15 plugin / 1.5.18 starter, Java 8)
- springboot-java-11     (Spring Boot 2.7.15, Java 11; passes iast-util-11 jar)
- springboot-java-17     (Spring Boot 2.7.15, Java 17; passes iast-util-17 jar)
- apm-tracing-disabled   (Spring Boot 2.7.15, Java 8; passes dd-trace-api jar)
- kafka-2                (Spring Boot 2.7.15, Java 8; passes iast-util jar)
- openfeature            (Spring Boot 2.7.15, Java 11; passes feature-flagging-api jar)

Modules converted (bootWar):
- springboot-jpa         (Spring Boot 2.6.0, Java 8; Lombok)
- springboot-tomcat-jsp  (Spring Boot 2.7.15, Java 8; JSP webapp)
- springboot-jetty-jsp   (Spring Boot 2.7.15, Java 8; JSP webapp)
- springboot-tomcat      (Spring Boot 2.5.12, Java 8; Ivy Tomcat download + unzip)

Where an application module depends on a project artifact from the main build
(e.g. iast-util-11, dd-trace-api), the jar path is forwarded as a Gradle
property (`-PfooJar=…`) from the Exec task and consumed via
`if (hasProperty('fooJar')) { implementation files(property('fooJar')) }`.

The spring-kafka-test test dependency in kafka-2 is pinned to 2.8.11 (the
version previously resolved from the Spring Boot BOM) since the test module
no longer has access to that BOM.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@bric3 bric3 force-pushed the bdu/smoke-tests-gradle-forward-compat branch from d4a50fe to 66fd737 Compare May 15, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: tooling Build & Tooling tag: ai generated Largely based on code generated by an AI or LLM tag: no release notes Changes to exclude from release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant