Skip to content

fix: update Jackson to 3.2.4 and Spring to 7.0.9, flush async responses - #1714

Merged
ckawl merged 2 commits into
aws:mainfrom
ckawl:chore/deps-jackson-spring-cves
Oct 22, 2026
Merged

ckawl merged 2 commits into
aws:mainfrom
ckawl:chore/deps-jackson-spring-cves

Conversation

@ckawl

@ckawl ckawl commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Updates Jackson and Spring to current patch releases, and fixes the async response hang that newer Spring versions cause. The Dependabot PRs couldn't go in on their own: the springboot4 job fails dependency convergence on each of them, and the Spring jobs hang until the 6 hour timeout.

Dependency changes

  • Jackson 3.0.2 -> 3.2.4. The jackson.version property moves from core to the parent pom so springboot4 can align on it.
  • Spring Framework 7.0.0 -> 7.0.9 and Spring Security 7.0.0 -> 7.0.7 in the spring module. The spring archetype gets 7.0.9 in both pom.xml and build.gradle (build.gradle was still on 6.2.8).
  • springboot4: Spring Boot 4.0.0 -> 4.0.8, Spring Framework 7.0.1 -> 7.0.9, Spring Security 7.0.0 -> 7.0.7, Spring Cloud Function 5.0.0 -> 5.0.4. Boot 4.0.x manages Jackson 3.1.5, so the module imports jackson-bom at core's version. slf4j-api and jspecify are pinned because Boot 4.0.8's own transitive dependencies disagree on them and trip dependencyConvergence.
  • springboot4 archetype: Boot parent 4.0.8, plus jackson-bom.version and jackson-2-bom.version overrides. Without the second one Boot's Jackson 2 BOM keeps jackson-annotations at 2.21, and Jackson 3.2 fails at startup with NoClassDefFoundError for JsonApplyView.
  • slf4j 2.0.17 -> 2.0.18 to match Boot.

Async fix

Since Spring Framework 7.0.6, ServletServerHttpResponse.getBody() returns a stream that ignores flush() unless spring.http.response.flush.enabled is set. We relied on that flush to commit the response after an async re-dispatch, and doFilter skips its own flush for ASYNC requests, so a DeferredResult endpoint never released the response latch. doFilter now flushes after the re-dispatch unless the dispatch target started a new async cycle, which is what a servlet container does. On Spring versions before 7.0.6 the response is already committed by then, so nothing changes there.

AsyncAppTest gets a 30 second timeout so a regression fails the build instead of holding a runner for 6 hours.

Notes for the release

  • Spring Boot projects take Jackson from Boot's dependency management, so upgrading this library alone leaves them on Boot's Jackson. To get Jackson 3.2.x they need to set jackson-bom.version and jackson-2-bom.version, as the springboot4 archetype now does.
  • Spring Cloud Function 5.0.4 changed ServerlessHttpServletRequest.isSecure() to return true, since getScheme() is always https. Apps that use SpringDelegatingLambdaContainerHandler with Spring Security will now get HSTS headers and Secure cookies. SpringBootLambdaContainerHandler isn't affected.

Supersedes #1656, #1701, #1705 and #1706, and the library and archetype parts of #1636, #1641 and #1711. Their samples/ changes and #1702 are left to Dependabot.

Testing

  • gha_build.sh for jersey, spring and springboot4 with archetypes and samples on JDK 17. jersey: 102 tests, spring: 86, springboot4: 128, no failures. All three archetype integration tests pass.
  • Core: all green apart from the two that depend on the local region and MIME setup (serverName_albHostHeader_returnsHostHeader, getMimeType_mimeTypeOfJavascript_expectApplicationJavascript). They fail the same way on main locally and pass in Actions.
  • AsyncAppTest times out after 30 seconds without the doFilter change and passes with it.
  • New AwsAsyncContextTest cases run the real doFilter with a plain servlet that starts async, dispatches, and writes without flushing. The flush case fails without the doFilter change; the case where the dispatch starts a new async cycle checks the response stays open. Core now runs 412 tests.
  • Older versions users may still run: the spring module passes on Spring 7.0.0, and springboot4 passes on Jackson 3.1.5 and on Boot 4.0.0 with Spring 7.0.1.
  • Projects generated from the released 3.0.3 archetypes build and pass their tests after switching to this version.
  • A test app on Spring 7.0.9 with Spring Security returns sync and DeferredResult responses and the security headers, on both Spring Security 7.0.0 and 7.0.7.
  • The GitHub advisory database has no advisories for any of the new versions.

Note: gha_build.sh doesn't check the exit code of the archetype's own mvn install. On a machine with an older archetype installed, a failing archetype integration test still reports success, because the next step generates from the old archetype. On CI it fails, but one step later with "The desired archetype does not exist". That's how the jackson-annotations problem nearly got past local testing. Releases aren't affected. Tracked in #1715.

Updates Jackson and Spring to current patch releases, and fixes the
async response hang that newer Spring versions cause.

Dependency changes:
- Jackson 3.0.2 -> 3.2.4. jackson.version moves from core to the parent
  pom so springboot4 can align on it.
- spring module: Spring Framework 7.0.0 -> 7.0.9, Spring Security
  7.0.0 -> 7.0.7. The spring archetype gets 7.0.9 in pom.xml and
  build.gradle.
- springboot4: Spring Boot 4.0.0 -> 4.0.8, Spring Framework 7.0.1 ->
  7.0.9, Spring Security 7.0.0 -> 7.0.7, Spring Cloud Function 5.0.0 ->
  5.0.4. Imports jackson-bom at core's version and pins slf4j-api and
  jspecify so dependencyConvergence passes.
- springboot4 archetype: Boot parent 4.0.8 with jackson-bom.version and
  jackson-2-bom.version overrides (Jackson 3.2 needs annotations 2.22).
- slf4j 2.0.17 -> 2.0.18 to match Boot.

Async fix:
Since Spring Framework 7.0.6, ServletServerHttpResponse.getBody() returns
a stream that ignores flush() unless spring.http.response.flush.enabled
is set. We relied on that flush to commit the response after an async
re-dispatch, and doFilter skips its own flush for ASYNC requests, so a
DeferredResult endpoint never released the response latch. doFilter now
flushes after the re-dispatch unless the dispatch target started a new
async cycle. AsyncAppTest gets a 30 second timeout so a regression fails
instead of hanging the build.
@ckawl
ckawl requested a review from bnusunny October 21, 2026 17:58
@seshubaws

Copy link
Copy Markdown

Note: gha_build.sh doesn't check the exit code of the archetype's own mvn install, so a failing archetype integration test passes silently. That's how the jackson-annotations problem nearly got through. Not fixed here.

Can we make an issue for this to track?

import org.junit.jupiter.api.Timeout;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

can we add a test with a servlet that starts async and dispatches, asserting the response gets flushed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added. Thanks!

Adds two AwsAsyncContextTest cases that run the real doFilter with a
plain servlet behaving like Spring MVC 7.0.6+: it starts async and
dispatches on the first pass, then writes the body without flushing on
the async dispatch. One asserts the container commits the response and
releases the latch; the other asserts the response stays open when the
dispatch starts a new async cycle. The first fails without the doFilter
flush change.
@ckawl

ckawl commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Note: gha_build.sh doesn't check the exit code of the archetype's own mvn install, so a failing archetype integration test passes silently. That's how the jackson-annotations problem nearly got through. Not fixed here.

Can we make an issue for this to track?

Good call, opened #1715. It only affects local runs (a stale archetype can make it pass) and the CI error message. Releases run the archetype Integration Tests through plain Maven, so they aren't affected.

@ckawl
ckawl merged commit 8830eb3 into aws:main Oct 22, 2026
5 checks passed
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