Skip to content

Adopt the Spring Boot 4.1 baseline: compiling, booting, suite measurable - #2215

Open
ivosh wants to merge 3 commits into
integration/spring-boot-4.1from
refactor/2016-adopt-4.1-baseline
Open

ivosh wants to merge 3 commits into
integration/spring-boot-4.1from
refactor/2016-adopt-4.1-baseline

Conversation

@ivosh

@ivosh ivosh commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Core compiles, boots and runs its whole suite on Spring Boot 4.1.1 — 7254 tests, 102 failing, 98.59% green — and every failure is attributed to a sibling issue.

Closes the compile-and-measure half of #2016. This is the first sub-PR on the integration/spring-boot-4.1 branch.

What changed

Three commits, each reviewable on its own.

1. The dependency bump. Parent com.otilm:dependencies moves 1.4.3-SNAPSHOT2.0.0-SNAPSHOT. That brings Boot 4.1.1, Framework 7.0.9, Hibernate 7.4.5, Security 7.1.1 and JUnit 6.0.3. Jackson stays on 2.22.1, held there by the parent's explicit jackson-bom import. The com.otilm:interfaces coordinate moves to 2.20.0-SBM-SNAPSHOT.

Boot 4 split the monolithic jars, so spring-boot-http-client and spring-boot-jackson2 are now declared explicitly. spring-boot-jackson2 is load-bearing: it restores the Jackson2ObjectMapperBuilder bean, and without it every integration test fails on context load. spring-boot-webmvc-test is added test-scoped because @AutoConfigureMockMvc moved into it. hibernate-jpamodelgen becomes hibernate-processor, and the enhance plugin moves to org.hibernate.orm:hibernate-maven-plugin.

2. Compile breaks. Six main sources and 23 test sources. The substantive ones are ContextAwarePoolExecutor (Framework 7 removed ListenableFuture) and AbstractExternalAuthorizationManager (Security 7 removed check, and authorize widens to Supplier<? extends Authentication>). The rest are package relocations.

src/test/resources/schema.sql gains the Spring Session tables. Boot 4 commits a session on MockMvc requests. Flyway is disabled in the test profile and these are not JPA entities, so nothing else creates them. Every statement uses IF NOT EXISTS because the Testcontainer is reused and spring.sql.init.mode: always re-runs the script per context.

3. SortOrderBuilder. JpaOrder.nullPrecedence takes org.hibernate.query.NullPrecedence on Hibernate 6.6 and jakarta.persistence.criteria.Nulls on 7.x, with no overload on either side. jakarta.persistence-api:3.1.0 — what main resolves — ships no Nulls class at all. So there is no source form that compiles on both lines, and unlike the #2202 test shapes this could not be prepared on main. It is a separate commit because the branch head would not otherwise compile.

Two decisions worth a second opinion

The tomcat.version pin moves to the Tomcat 11 line — it is not dropped. #2205 pinned 10.1.59 against three critical bypass CVEs. Boot 4.1.1 manages Tomcat 11.0.24, a different Jakarta EE generation, so the 10.1.x override cannot apply here — but 11.0.24 is not safe. All three CVEs are fixed in 11.0.25 on the 11.0.x line, per GHSA-gcx9-497g-6cp6, GHSA-9xv2-5v5q-p794 and GHSA-h3x4-894j-xpx5, each listing org.apache.tomcat.embed:tomcat-embed-core [introduced=11.0.0-M1 fixed=11.0.25]. Inheriting the managed 11.0.24 would have reintroduced all three and failed the Trivy image gate #2205 exists to satisfy.

So the pin is re-expressed as 11.0.25 rather than deleted. dependency:tree confirms tomcat-embed-core, -el and -websocket all resolve at 11.0.25. 11.0.25 is published on Maven Central (HTTP 200) and is the head of the 11.0.x line — checked explicitly, because #2205 records that the announced 10.1.58 never reached Central and 10.1.59 was its successor.

The Testcontainers 1.21.4 pin stays. Boot 4.1.1 manages 2.0.5. Staying on 1.x is the decision already recorded in #2016 and #2019, and the spike verified it coexists with JUnit 6.0.3. Only the stale comment changed.

Measured

mvn -B verify, on this branch head:

tests failing green
this branch 7254 102 98.59%

Do not compare that against #2016's "125 failing / 5661 tests". That was measured on 2026-08-25, before #2149 and #2202 landed and before main grew by roughly 1600 tests.

Attribution of all 102:

count cause owner
56 RC#8 Unable to determine TableReference — HHH-20744 (55 raw, 1 wrapped in a JPA/tx failure) #2017
36 RC#6 unauthenticated MockMvc 401 #2018
1 RC#3 HttpStatus 422 split — ExceptionHandlingAdviceConnectorTest asserts UNPROCESSABLE_ENTITY, gets UNPROCESSABLE_CONTENT #2111
9 residual, not yet triaged

The RC#3 hit is worth noting: #2111 recorded that split as latent with no failing test. On this branch it fails, because the interfaces artifact now returns the new constant.

The 9 residual are 4 × ScepRegistrationEnrolmentITest (expected: <3> but was: <2>), 2 × PendingIssueReaperITest and 1 × V3AsyncPollITest (state never advances past PENDING_ISSUE), and 2 × AcmeProtocolFlowITest (internal error in AcmeServiceImpl.getOrder). The reaper and poll symptoms match RC#8's signature — the lock is silently not taken, so state never advances — and #2017 names PendingIssueReaper.reapOne as a hot-path call site. That is a plausible reading, not a proven one, and #2016 leaves the residual to be triaged on this branch.

Gates

No CI runs here. build_pr.yml triggers on pull_request into [main*, feat/*, hotfix/*], and this branch matches none of them, so everything below was run locally and the branch's RECONCILE.md records that the merge to main is the first time CI executes.

gate result
mvn test-compile -Dmaven.compiler.proc=full pass
mvn spotless:check checkstyle:check pass — 2019 files clean, 0 violations
build_identity_tables.py + git diff --exit-code pass, no drift
mvn verify fails on the 102 above, as expected
dependency:tree vs GHSA fixed versions pass — tomcat-embed-core 11.0.25 ≥ 11.0.25

The parent bump also moves the formatter engine to Spotless 3.7.0 / Eclipse JDT 4.40. It produced no reformat, so no .git-blame-ignore-revs entry is needed.

The interfaces dependency resolves from ~/.m2 only

com.otilm:interfaces:2.20.0-SBM-SNAPSHOT is published nowhere — 404 on Sonatype snapshots, absent from Maven Central and from GitHub Packages. The only remotely resolvable interfaces snapshot is 2.20.0-SNAPSHOT, built from interfaces main on the Boot 3.x parent, which cannot satisfy this branch.

So this branch builds only where it has been installed locally, from interfaces integration/spring-boot-4.1 at 0dd634ba. Clearing that is OmniTrustILM/interfaces#806, whose "3.0.0-SNAPSHOT is published for core to consume" criterion is still unchecked. RECONCILE.md records it.

Not done here

ContextSignatureGuardTest.BASELINE still reads 61 and the suite does not fail it, so no re-justification was needed. No test was disabled, ignored or weakened. The OpenTelemetry BOM imports still pin 1.60.1 / 2.26.1 against the parent's 1.62.0 — that belongs to #2020 and is left alone deliberately.

@ivosh
ivosh force-pushed the refactor/2016-adopt-4.1-baseline branch from 125ccfe to 237737f Compare September 3, 2026 20:12
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.

1 participant