(WIP)Upgrade to Spring Boot 4.1.1 and Jackson 3 - #1573
Draft
bradyyie wants to merge 10 commits into
Draft
Conversation
Moves the build onto the Spring Boot 4.1.1 BOM and migrates the codebase from Jackson 2 (com.fasterxml.jackson) to Jackson 3 (tools.jackson). Build: - Boot plugin and BOM 3.5.14 -> 4.1.1 - Removes overrides the BOM now covers: framework, security, log4j2, netty, kafka, groovy, jedis, tomcat, flyway, micrometer, awaitility, jackson - Keeps only the Elasticsearch and Testcontainers overrides, each with a reason - Drops dead version variables and the unused jsr311-api dependency - Pins spring-retry, which Boot 4 no longer manages Jackson 3: - ObjectMapperProvider builds an immutable mapper via JsonMapper.builder - ObjectMapperConfiguration removed; its settings move to the builder customizer - JsonProtoModule moves to ValueSerializer/ValueDeserializer - json-schema-validator 3.x and jackson-jq 2.0 for native Jackson 3 support - Elasticsearch and OpenSearch transports keep a Jackson 2 mapper at the boundary Spring AI 2.0, springdoc 3.1, and Boot 4 package relocations applied.
- e2e keeps Jackson 2: it drives the published client SDK, which is a Jackson 2 artifact, so those tests declare the Jackson 2 compile dependencies directly - Boot 4 test relocations: AutoConfigureMockMvc moved to spring-boot-webmvc-test, DataSource and Flyway auto-configuration to spring-boot-jdbc and spring-boot-flyway - groovy-all is not managed by groovy-bom, so specs depend on groovy plus groovy-json - JsonNode.findValuesAsText is findValuesAsString in Jackson 3 - OpenSearch test transports use a Jackson 2 mapper, matching the production config
- StartWorkflow now catches JacksonException as well: Jackson 3 no longer reports a failed convertValue as IllegalArgumentException, so a malformed startWorkflow payload stopped failing the task - Tests that rely on plain @mock fields open their mocks explicitly, since Boot 4 dropped the listener that used to do it - START_WORKFLOW_PARAMETER is package-private so the same-package Spock spec can read it under Groovy 5, which honours private access - DummyPayloadStorageTest accepts JacksonException, which no longer extends IOException
…uite - protobuf moves to 4.x. The 3.x pin from #964 was there because protobuf 4 with GraalVM polyglot 24.x made Gradle request a polyglot4 artifact that does not exist; GraalVM 25 resolves cleanly. Boot 4 forces the move regardless, since micrometer's OTLP registry now pulls opentelemetry-proto built on protobuf 4. protoc follows revProtoBuf so gencode and runtime agree - httpclient5 comes from the BOM. The stale 5.3.1 variable was masked by a force that this upgrade removed, and 5.3.1 lacks TlsSocketStrategy - json-jq surfaces the parser message again: jackson-jq 2.x changed the wrapper exception text the message filter was keyed on - test-harness excludes the six SDK-driven suites. The published conductor-client is Jackson 2 and links against this project's conductor-common, which is now Jackson 3; see issues.md
…efresh docs - The @Inject and @singleton annotations on the two publisher classes were inert: both are constructed explicitly, and Spring dropped javax.inject support in 6.x - management.metrics.web.server.request.autotime.percentiles no longer exists in Boot 4; percentiles move to management.metrics.distribution.percentiles, which restores the quantile series on /actuator/prometheus - AGENTS.md records which pins the upgrade retired and states the BOM-first rule - issues.md covers the container-gated suites and what was verified at runtime
The publisher posts from a background thread and the first notification pays the one-off cost of loading the serialization and metrics classes, measured at about 1.8s against a one second wait. Only the wait changes; the verification is the same.
Spring Boot 4 dropped spring-retry from its BOM because the functionality moved into spring-core. This replaces the library rather than pinning it. - RetryPolicy.builder() replaces SimpleRetryPolicy plus a backoff policy. Note maxRetries counts retries where maxAttempts counted attempts, so each budget drops by one to keep the same number of calls - the three SQL deadlock policies overrode canRetry to inspect the last throwable, which is what predicate(Predicate<Throwable>) is for, so they are now plain predicates rather than policy subclasses - Retryable takes no argument; the RetryContext parameter was unused at all twelve call sites - callbacks that only throw unchecked exceptions use invoke(), which rethrows the original cause once retries are exhausted. That keeps DefaultEventProcessor seeing a TransientException and keeps the SQLException as the cause of the NonTransientException the SQL DAOs raise - the two Elasticsearch executeWithRetry ladders unwrap RetryException before testing the exception type, otherwise every failure would have collapsed into a generic IOException TestDefaultEventProcessor still pins three attempts for a transient failure and one for a non-retriable one.
Enabling redis-concurrency-limit failed at startup because the module declares spring-data-redis compileOnly and the server never shipped it, so the feature could not load at all. The server now declares it runtimeOnly. issues.md records the Redis verification: a live Redis 7.4 backing persistence, queues and the Redisson lock through a full workflow lifecycle and 25 concurrent workflows, plus a direct check of Spring Data Redis 4.1.1 with Jedis 7.4.1 through the concurrency limit connection factory. That pairing is what the retired jedis 3.6.0 pin existed for.
bradyyie
marked this pull request as draft
August 25, 2026 20:07
…a validator test-harness: the conductor-client fat JAR was moved onto the test classpath as a files() dependency, which Gradle places ahead of the project modules. That flipped the precedence the module has always relied on, so the JAR's older copies of classes the project also ships won, and the SDK's TaskContext shadowed the one in conductor-common. Declaring the client as a module dependency after the project modules restores the original order. WorkflowFunctionalTest joins the excluded suites: it inherits SDK usage from FunctionalTestBase and hits the same Jackson 2 linkage as the others. json-schema-validator was applied to every module from the root build even though only common and ai use it, which dragged mockserver's 1.x transitive up to 3.x and broke its expectation validation. It is now declared where it is used, and the http-task test classpath keeps the version mockserver was built against. Removing that global exposed seven modules that were taking Jackson through it without declaring it. Each now declares what it imports.
The OpenSearch java client serialises with Jackson 2, so the type it is asked to deserialize into has to be a Jackson 2 type. The Jackson 3 migration rewrote these ObjectNode type tokens along with everything else, and the Jackson 2 mapper then tried to introspect Jackson 3's ObjectNode as a bean and failed on its overloaded setAll. Only the tokens crossing the client boundary change; the nodes this class builds from its own mapper stay on Jackson 3. es7, es8 and os2 are unaffected: they deserialize into Conductor model classes or Map, and Jackson annotations are shared between the two versions.
Contributor
Author
Contributor
Author
|
Branch will be used to create 4.0.0-alpha.X fixes made here or merges to this branch from other branches will be included The reason for this:
Fixes and PRs to this branch i am happy to approve HOWEVER please DO NOT file issues about this branch. Fix it or wait for it to be fixed 😄 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrades the framework stack to Spring Boot 4.1.1 and migrates the codebase from Jackson 2 to
Jackson 3. This brings Spring Framework 7, Spring Security 7, Tomcat 11, Jakarta EE 11, springdoc 3
and Spring AI 2.0 with it.
Versions now come from the Spring Boot BOM unless there is a stated reason not to. Overrides that
existed only because an older BOM lagged behind have been removed: framework, security, log4j2,
netty, kafka, groovy, tomcat, flyway, micrometer, awaitility and jackson.
tracks a client that will not talk to the older clusters