Skip to content

MAT-10132: update spring boot (from 3.5.14 to 4.0.6)#357

Open
etan-sb wants to merge 2 commits into
developfrom
feature/MAT-10132/spring-boot-4-upgrade
Open

MAT-10132: update spring boot (from 3.5.14 to 4.0.6)#357
etan-sb wants to merge 2 commits into
developfrom
feature/MAT-10132/spring-boot-4-upgrade

Conversation

@etan-sb

@etan-sb etan-sb commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

MADiE PR Template

Jira Ticket: MAT-10132
(Optional) Related Tickets:

Summary

Spring Boot 4 + Jackson 3 Upgrade Notes — madie-java-models

Part of the fleet-wide SB 3.5.14 → 4.0.6 + Jackson 2 → 3 migration. Common patterns live in
madie-fhir-service/SPRING_BOOT_4_UPGRADE.md; this file records only what was specific to this repo.

This library is the linchpin of the Jackson 3 migration: it owns VersionJsonSerializer, the custom
(de)serializer on Measure.version / CqlLibrary.version. It must be built and published before any
consumer can move to Jackson 3.

Version

0.9.6-SNAPSHOT0.10.0-SNAPSHOT

pom.xml

  • springboot.version 3.5.144.0.6.
  • BOM-less library → added the spring-boot-dependencies:${springboot.version} BOM import in
    <dependencyManagement> (manages Spring Framework 7 + Jackson 3 versions).
  • Jackson 2 → 3 coordinates: jackson-databind group com.fasterxml.jackson.coretools.jackson.core
    (version dropped, BOM-managed); jackson-annotations stays on com.fasterxml.jackson.core
    (BOM-managed). Removed the fasterxml.jackson.version property.
  • Added org.springframework.boot:spring-boot-jackson — provides @JacksonComponent, which the basic
    spring-boot-starter does not pull transitively.
  • maven-surefire-plugin 2.22.13.5.2 (see Test infra below).

Source — Jackson 3 API changes

  • VersionJsonSerializer: JsonSerializertools.jackson.databind.ValueSerializer; JsonDeserializer
    ValueDeserializer; SerializerProviderSerializationContext; JsonGenerator/JsonParser
    tools.jackson.core; inside the deserializer jp.getCodec().readTree(jp) (removed in Jackson 3) →
    ctxt.readTree(jp); @JsonComponent@JacksonComponent; dropped throws IOException (Jackson 3
    exceptions are unchecked).
  • Measure.java / CqlLibrary.java: the databind-level @JsonSerialize / @JsonDeserialize imports
    moved com.fasterxml.jackson.databind.annotation.*tools.jackson.databind.annotation.*. The ~90
    core annotations elsewhere (@JsonProperty, @JsonFormat, @JsonTypeInfo, etc.) are unchanged —
    jackson-annotations keeps the com.fasterxml.jackson.annotation package.

Test infrastructure

  • The old pinned maven-surefire-plugin:2.22.1 cannot launch under the JUnit Platform 6.x that the SB4
    BOM pulls in (NoClassDefFoundError: PreconditionViolationException) → bumped to 3.5.2.
  • Side effect worth knowing: with surefire 2.22.1 + junit:junit on the classpath, surefire selected
    the JUnit 4 provider and silently skipped all JUnit 5 Jupiter @Test methods. Bumping surefire
    makes them run for the first time, which surfaced two latent issues unrelated to Jackson:
    • ModelTypeTest asserted US Core "6.0.1" while MAT-10030 (commit ffb0815) had changed the enum to
      return "6.1.0" — the test had never executed. Fixed the assertion to "6.1.0".
    • RequiredByOtherFieldValidatorTest used @ExtendWith(SpringExtension.class) with @Mock fields;
      SB4 removed MockitoTestExecutionListener, so the mocks were null → switched to MockitoExtension.
  • Converted the one remaining JUnit 4 test (MeasurePopulationTest) to JUnit 5.
  • MeasureScoringValidatorTest: ObjectMappertools.jackson.databind; dropped the now-unchecked
    throws clause; InvalidFormatExceptiontools.jackson.databind.exc.

⚠️ Deserializer gotcha (Jackson 3 strict node coercion)

VersionDeserializer originally did Version.parse(node.asText()). Jackson 3's asText()/asString()
is strict
— it throws JsonNodeException on a non-scalar node, whereas Jackson 2 leniently returned
"". Some consumer fixtures store version as an object {major,minor,revisionNumber} (not a string),
so under Jackson 3 the deserializer threw, was caught, and returned null → downstream
NullPointerException on Measure.getVersion(). Restored the Jackson-2 lenient behavior explicitly:
Version.parse(node.isValueNode() ? node.asString() : "") (a non-scalar node → ""
Version.parse("")new Version(), exactly as before). This surfaced only when fhir-service ran its
real Measure-deserialization tests against the Jackson-3 lib — java-models' own unit tests did not cover
the object-form fixture.

Result

mvn clean install green — 153 tests. Installed to local ~/.m2 (publish to GitHub Packages at cutover).

All Submissions

  • This PR has the JIRA linked.
  • Required tests are included.
  • No extemporaneous files are included (i.e. Complied files or testing results).
  • This PR is merging into the correct branch.
  • All Documentation needed for this PR is Complete (or noted in a TODO or other Ticket).
  • Any breaking changes or failing automations are noted by placing a comment on this PR.

DevSecOps

If there is a question if this PR has a security or infrastructure impact, please contact the Security or DevOps engineer assigned to this project to discuss it further.

  • This PR has NO significant security impact (i.e Changing auth methods, Adding a new user type, Adding a required but vulnerable package).

Reviewers

By Approving this PR you are attesting to the following:

  • Code is maintainable and reusable, reuses existing code and infrastructure where appropriate, and accomplishes the task’s purpose.
  • The tests appropriately test the new code, including edge cases.
  • If you have any concerns they are brought up either to the developer assigned, security engineer, or leads.

@etan-sb etan-sb requested a review from a team as a code owner June 22, 2026 22:35
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Comment thread src/test/java/gov/cms/madie/models/common/ModelTypeTest.java Outdated
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