Skip to content

CAMEL-22857 Convert camel to Jackson 3 - use jackson 3 in all camel components, use camel-jackson3 over camel-jackson#21800

Draft
cunningt wants to merge 9 commits intoapache:mainfrom
cunningt:jackson3upgrade
Draft

CAMEL-22857 Convert camel to Jackson 3 - use jackson 3 in all camel components, use camel-jackson3 over camel-jackson#21800
cunningt wants to merge 9 commits intoapache:mainfrom
cunningt:jackson3upgrade

Conversation

@cunningt
Copy link
Contributor

@cunningt cunningt commented Mar 7, 2026

Description

  • convert camel to Jackson 3 (com.fasterxml.jackson -> tools.jackson, API changes)
  • all components that used camel-jackson now use camel-jackson3
  • import the tools.jackson:jackson-bom instead of the com.fasterxml.jackson:jackson bom in parent/pom.xml
  • update ObjectMapper references for immutability changes
  • drop wizard metrics upgraded to 4.2.38 to support Jackson 3
  • networknt-json-schema-validator upgrade from 1.5.9 -> 3.0.0 along with API changes (in order to support Jackson 3) -
  • jsonschema-generator upgrade to 5.0.0
  • flowable upgrade to 8.0.0 (in order to support Jackson 3)
  • jackson-annotations does not change groupId/package (jackson 2 annotations supports both Jackson 2 and Jackson 3, introduced a property for jackson2-annotations-version)

There are five components that cannot upgrade to Jackson 3. They are still using Jackson 2 but since Jackson 2 and Jackson 3 maintain different package names there do not seem to be any issues with them staying on Jackson 2 temporarily

  • camel-openapi (open PR for Jackson 3 support for swagger, will upgrade it to Jackson 3 when PR is merged and released)
  • camel-opensearch (open PR for Jackson 3 support for opensearch, will upgrade it when PR is merged and released)
  • camel-jslt (open PR for Jackson 3 support for jslt, will upgrade it when PR is merged and released)
  • camel-json-patch (Jackson 3 not supported yet, project seems abandoned, camel-json-patch deprecated, will not try to upgrade before removal)
  • camel-torchserve (Jackson 3 not supported yet, camel-torchserve is deprecated, will not try to upgrade before removal)

Target

  • I checked that the commit is targeting the correct branch (Camel 4 uses the main branch)

Tracking

  • If this is a large change, bug fix, or code improvement, I checked there is a JIRA issue filed for the change (usually before you start working on it).

Apache Camel coding standards and style

  • [x ] I checked that each commit in the pull request has a meaningful subject line and body.

  • [x ] I have run mvn clean install -DskipTests locally from root folder and I have committed all auto-generated changes.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 7, 2026

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using build-all, build-dependents, skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@jamesnetherton
Copy link
Contributor

Are we planning to do this for 4.19? There wont be any Jackson 3 support in Quarkus until 4.x is released later this year.

Copy link
Contributor

@gnodet gnodet left a comment

Choose a reason for hiding this comment

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

In-depth Review of Jackson 3 Migration

Overall this is a thorough and well-executed migration across 500+ files. The import renames, API changes (e.g., JsonSerializerValueSerializer, fields()properties(), etc.), and ObjectMapper immutability patterns are generally handled well. CI passes on both JDK 21 and JDK 25.

Bugs Found

1. CBORDataFormat: prettyPrint rebuild result discarded

In components/camel-cbor/src/main/java/org/apache/camel/component/cbor/CBORDataFormat.java, the prettyPrint block does:

objectMapper.rebuild()
        .enable(SerializationFeature.INDENT_OUTPUT)
        .build();

The result of .build() is not assigned back to objectMapper, so INDENT_OUTPUT is silently lost. Compare with the enableFeatures/disableFeatures blocks in the same file which correctly do objectMapper = objectMapper.rebuild()...build().

2. ObjectMapperHelper (LevelDB): customModule registration discarded

In components/camel-leveldb/src/main/java/.../ObjectMapperHelper.java:

if (customModule != null) {
    objectMapper.rebuild().addModule(customModule);
}
return objectMapper;

Two issues: (a) .build() is never called, and (b) the result is never assigned back. The custom module is completely ignored. Should be:

if (customModule != null) {
    objectMapper = objectMapper.rebuild().addModule(customModule).build();
}

Concerns

3. Inconsistent asText() vs asString() usage

In Jackson 3, JsonNode.asText() was renamed to asString(). The PR mixes both:

  • DefaultJsonUriSchemaLoader.java uses node.get("$schema").asText() (Jackson 2 name)
  • AsNestedPropertyDeserializer.java uses node.asText() (Jackson 2 name)
  • YamlTestSupport.groovy uses SCHEMA_NODE.get('$schema').asString() (Jackson 3 name)

While asText() may still work as a deprecated alias, the PR should be consistent and use asString() everywhere.

4. Unused properties in parent POM

Two new properties appear unused:

  • nitrite-version (3.4.4) — no nitrite files changed in this PR
  • jackson-datatype-version (3.0.0-rc2) — not referenced by any ${jackson-datatype-version}

5. Alpha dependency: jackson-jq

jackson-jq-version is set to 2.0.0-alpha1. If the alpha API changes before GA, it could break the build.

6. Public API change (intentional but needs documentation)

Multiple components now expose tools.jackson.databind.ObjectMapper instead of com.fasterxml.jackson.databind.ObjectMapper in their public APIs (json-validator, salesforce, servicenow, ocsf). This is binary-incompatible. Should be documented in the migration guide/release notes.

Positive Observations

  • Import migration is thorough — no stale com.fasterxml.jackson references in new code
  • JavaTimeModule removals are correct (Jackson 3 has built-in java.time support)
  • Velocity templates for Salesforce code generation properly handle the annotation package split
  • networknt json-schema-validator migration (1.5.9 → 3.0.0) is done comprehensively
  • Jackson 2 coexistence for remaining components (camel-opensearch, camel-jslt) is correctly handled with version pinning

@cunningt
Copy link
Contributor Author

cunningt commented Mar 9, 2026

Fixed 1-4.

5. Alpha dependency: jackson-jq

jackson-jq-version is set to 2.0.0-alpha1. If the alpha API changes before GA, it could break the build.

Double checked jackson-jq and 2.0.0-alpha1 is still the only 2.0.0 release. The 2.0.0 milestone is necessary because it provides Jackson 3 support.

@davsclaus
Copy link
Contributor

For some of those components then we may need to add a camel-xxxx2 component that has the old jackson v2 that CEQ would need as Q is still jackson v2.

And then when we can upgrade to Q4 then we can drop these v2 components. However we can maybe track this in another JIRA and the build up a list of components that CEQ then would need.

The main jackson components are already there as both v2 and v3.

gnodet and others added 2 commits March 10, 2026 16:02
…ang-mcp

jackson-annotations uses a different versioning scheme since 2.20 (no
patch version), so jackson-annotations:2.21.1 does not exist. Remove the
explicit version so the Jackson 2 BOM manages it correctly to 2.21.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n3-avro

Remove the local Jackson 3 BOM import from camel-jackson3-avro. The
parent POM already imports both Jackson 2 and Jackson 3 BOMs in the
correct order (Jackson 2 first). The local import was overriding
jackson-annotations to 2.20 (from Jackson 3 BOM) while jackson-databind
remained at 2.21.1 (from parent's Jackson 2 BOM). Since jackson-databind
2.21.1 requires jackson-annotations 2.21 (for JsonSerializeAs), this
caused NoClassDefFoundError at runtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet
Copy link
Contributor

gnodet commented Mar 11, 2026

In-depth Review of Jackson 3 Migration

Impressive effort migrating 507 files across the entire Camel codebase. The dual-BOM approach (Jackson 2 first, Jackson 3 second) in the parent POM is well-structured, and the 5 excluded components are properly isolated. Here are the findings organized by severity.


Critical / High

1. Salesforce JsonUtils.createObjectMapper() silently drops date features

The old code configured:

objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);

The new code drops both. WRITE_DATES_AS_TIMESTAMPS defaults to true, so dates will serialize as numeric timestamps instead of ISO strings — a silent behavioral regression affecting all Salesforce API interactions involving date fields.

2. ServiceNow getOrCreateMapper() drops all custom date/time serialization

The method was drastically simplified, removing JavaTimeModule registration with custom date/time serializers using dateFormat, timeFormat, and dateTimeFormat patterns. These configuration properties still exist on ServiceNowConfiguration but are now dead code. Users with custom date/time format settings will find them silently ignored.

3. CBOR registry lookup changed from ObjectMapper to TokenStreamFactory

In CBORDataFormat, old code looked up ObjectMapper instances in the registry:

Set<ObjectMapper> set = camelContext.getRegistry().findByType(ObjectMapper.class);

New code looks for TokenStreamFactory instead. Users who registered a CBORMapper in the Camel registry will no longer be auto-discovered — a breaking change in the component's contract.


Medium

4. SObjectCompositeResponse/SObjectCompositeResult — behavioral fix hidden in migration

@JsonProperty changes from "results""compositeResponse" and "referenceID""referenceId" are bug fixes to match the actual Salesforce API field names, not pure migration changes. Should be called out in the PR description.

5. jackson-jq upgraded to 2.0.0-alpha1

Using an alpha release in production carries stability risk. This is necessary for Jackson 3 compatibility, but worth flagging.

6. Exception handling regressions from checked → unchecked migration

Several places lost meaningful error handling when IOException/JsonProcessingException (checked) became JacksonException (unchecked):

  • LoginConfigHelper.loadFromSfCliCredentials() — try-catch removed entirely; malformed credentials now crash instead of being gracefully logged and skipped
  • AbstractDTOBase.toString() — can now throw unchecked from toString() instead of returning fallback string
  • DefaultBulkApiV2Client.marshalRequest()/unmarshalResponse()SalesforceException wrapping lost; raw JacksonException propagates, changing the error contract

7. MicrometerModule — half-completed IOException migration

serializeStatistics() still declares throws IOException and the caller wraps it in a try-catch, but Jackson 3's JsonGenerator no longer throws checked IOException. The throws IOException is dead code.

8. Deleted test testUndertowPojoTypePutUserFail

In RestUndertowHttpPojoTypeTest, the test validating that sending a wrong POJO type returns HTTP 400 was removed entirely. This could mask a behavioral change in Jackson 3's type handling.

9. LocalDate serializer/deserializer dropped from Salesforce TimeModule

Registration was removed entirely. If any Salesforce DTO uses LocalDate, it falls back to Jackson 3's default handling, which may differ from Jackson 2's JavaTimeModule.


Low / Minor

10. Hardcoded version in camel-salesforce-maven-plugin

jsonschema-generator is pinned to 4.38.0 while the parent property is 5.0.0. Should use the property or document why.

11. Inconsistent asText()asString() vs textValue() migration

Some files use asString() (correct Jackson 3 rename), others use textValue() (returns null for non-text nodes instead of converting). GistHelper and GitHubHelper use textValue() which changes behavior.

12. Redundant ${jackson3-version} on some deps

Several components specify explicit versions on tools.jackson deps that are already managed by the parent BOM (e.g., camel-docling, camel-langchain4j-chat, camel-flowable). Not harmful, just inconsistent.

13. Inefficient repeated rebuild().build() in CBORDataFormat

Each feature toggle creates a new ObjectMapper. Should rebuild() once, configure all features, then build() once.

14. new ObjectMapper() vs JsonMapper.builder().build()

Several files (MongoDbEndpoint, LoginConfigHelper, NodeState) use new ObjectMapper() directly. In Jackson 3, the idiomatic pattern is JsonMapper.builder().build(). Not a bug but inconsistent with the rest of the PR.

15. Dead property jackson-databind-nullable-version

Defined in parent POM but appears unused across the entire codebase.


What looks good

  • Dual-BOM strategy with correct import order
  • Jackson 2 annotations (com.fasterxml.jackson.annotation) correctly kept unchanged
  • TextNodeStringNode consistently applied
  • fieldNames()propertyNames().iterator() correctly applied
  • ObjectMapper immutability handled correctly in most places (Salesforce JsonUtils, SObjectCompositeTest, etc.)
  • AsNestedPropertyDeserializer correctly adds strictTypeIdHandling=false for Jackson 3
  • networknt json-schema-validator API migration appears correct
  • JSONAssert properly introduced for order-insensitive JSON comparison in tests
  • 5 excluded components properly isolated with no classpath conflicts

- Salesforce JsonUtils: restore WRITE_DATES_AS_TIMESTAMPS and
  ADJUST_DATES_TO_CONTEXT_TIME_ZONE (moved to DateTimeFeature in Jackson 3)
- ServiceNow: restore custom date/time format serializers using
  dateFormat/timeFormat/dateTimeFormat config properties
- CBOR: fix registry lookup to find ObjectMapper (not TokenStreamFactory),
  and consolidate repeated rebuild().build() into single call
- Micrometer: remove dead IOException throws and try-catch from
  serializer methods (Jackson 3 uses unchecked exceptions)
- Salesforce: restore exception handling in AbstractDTOBase.toString(),
  LoginConfigHelper, StreamingApiConsumer, DefaultBulkApiV2Client

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet
Copy link
Contributor

gnodet commented Mar 11, 2026

I've created PR #21921 with fixes for the critical and medium issues identified above. It should be merged after this PR lands.

Copy link
Contributor

@gnodet gnodet left a comment

Choose a reason for hiding this comment

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

Thorough Jackson 3 migration. CI is green and we've pushed fixes for the issues found during review (date feature restoration, ServiceNow date/time config, CBOR registry lookup, exception handling, Micrometer dead code). LGTM.

@gnodet
Copy link
Contributor

gnodet commented Mar 11, 2026

@davsclaus Good point about CEQ. Here's an analysis of the impact.

Components that moved to Jackson 3

26 components switched from camel-jackson to camel-jackson3 (transitive dependency):
camel-aws-bedrock, camel-aws2-ddb, camel-dhis2, camel-google-sheets, camel-google-vertexai, camel-groovy, camel-iso8583, camel-jetty, camel-jq, camel-jsonpath, camel-kafka, camel-kamelet, camel-langchain4j-tools, camel-lra, camel-mongodb, camel-mongodb-gridfs, camel-neo4j, camel-netty-http, camel-oauth, camel-openai, camel-platform-http-vertx, camel-qdrant, camel-rest-openapi, camel-servlet, camel-undertow

~65 components now use tools.jackson APIs directly, including:
camel-aws-secrets-manager, camel-azure-cosmosdb, camel-azure-key-vault, camel-azure-storage-blob, camel-azure-storage-queue, camel-bonita, camel-cbor, camel-chatscript, camel-clickup, camel-cxf-spring-rest, camel-cyberark-vault, camel-docling, camel-dropbox, camel-elasticsearch, camel-elasticsearch-rest-client, camel-elytron, camel-flowable, camel-google-firestore, camel-google-secret-manager, camel-graphql, camel-hashicorp-vault, camel-huaweicloud-*, camel-huggingface, camel-ibm-secrets-manager, camel-jolt, camel-json-validator, camel-jsonata, camel-keycloak, camel-knative, camel-kubernetes, camel-langchain4j-chat, camel-leveldb, camel-lumberjack, camel-metrics, camel-micrometer, camel-ocsf, camel-plc4x, camel-pqc, camel-pubnub, camel-salesforce, camel-sap-netweaver, camel-servicenow, camel-splunk-hec, camel-spring-ai-tools, camel-stitch, camel-stripe, camel-swift, camel-tahu, camel-telegram, camel-telemetry-dev, camel-wasm, camel-weather, camel-whatsapp, camel-wordpress, camel-xj, camel-zeebe, camel-zookeeper-master

Which ones need Jackson 2 wrappers for CEQ?

Since Jackson 2 (com.fasterxml.jackson) and Jackson 3 (tools.jackson) use different packages, they can coexist on the classpath. The camel-jackson / camel-jackson3 data format wrappers already exist side by side.

Jackson 2 wrappers would only be needed for components where Jackson 3 types leak into the component's public API (endpoint config, data types, etc.) AND the component has a CEQ extension. For components that only use Jackson internally, both versions coexist without conflict.

The components most likely to need wrappers are: camel-salesforce, camel-servicenow, camel-cbor, camel-jsonpath, camel-jq, camel-xj. But this should be validated against what CEQ actually supports.

Should we create a JIRA to track this?

@gnodet gnodet marked this pull request as ready for review March 11, 2026 08:35
@davsclaus
Copy link
Contributor

Yeah create a JIRA

@gnodet
Copy link
Contributor

gnodet commented Mar 11, 2026

I'll create a JIRA ticket for tracking the CEQ Jackson 2 wrapper work.

Key candidates that expose Jackson types in their public API and have CEQ extensions:

  • camel-salesforce, camel-servicenow, camel-cbor, camel-jsonpath, camel-jq, camel-xj
  • camel-jackson3 itself (needs a Jackson 2 wrapper data format for CEQ)

Also noting that the fixes from the review have been pushed directly to this branch (PR #21921 was closed in favor of direct commits).

@jamesnetherton
Copy link
Contributor

Jackson 2 wrappers would only be needed for components where Jackson 3 types leak into the component's public API (endpoint config, data types, etc.) AND the component has a CEQ extension. For components that only use Jackson internally, both versions coexist without conflict.

Not sure that's true. The native compiler will find paths to Jackson 3 types, regardless of whether they are exposed as public API or not.

@gnodet
Copy link
Contributor

gnodet commented Mar 11, 2026

@jamesnetherton Good catch — you're right. My analysis was thinking about JVM mode where both Jackson 2 and 3 coexist fine via different packages. But in GraalVM native compilation, the native image builder traces all reachable code paths and will discover tools.jackson classes used internally, not just public API. If CEQ doesn't have Jackson 3 dependencies, those classes won't be resolvable at native build time.

However, since core modules (camel-core, camel-support, camel-yaml-io, camel-yaml-dsl) are also migrated to Jackson 3 by this PR, and core modules can't be wrapped — CEQ would need to adopt Jackson 3 at the core level. Once Jackson 3 is on the classpath via core, components that only use Jackson 3 internally would work without any wrappers.

The wrapper/compatibility approach would then only be needed for components that expose Jackson types in their public API (where CEQ users interact with Jackson types directly in code).

Cross-reference: components modified by this PR that have a CEQ extension

60 components touched by this PR have a corresponding Camel Quarkus extension:

Category Components
Jackson / Data Formats (12) camel-cbor, camel-jackson, camel-jackson-avro, camel-jackson-protobuf, camel-jacksonxml, camel-jolt, camel-jq, camel-jslt, camel-json-validator, camel-jsonata, camel-jsonpath, camel-xj
AWS (3) camel-aws-bedrock, camel-aws-secrets-manager, camel-aws2-ddb
Azure (3) camel-azure-key-vault, camel-azure-storage-blob, camel-azure-storage-queue
Google (2) camel-google-secret-manager, camel-google-sheets
Messaging (8) camel-jms, camel-kafka, camel-kamelet, camel-lumberjack, camel-pubnub, camel-splunk-hec, camel-swift, camel-telegram
HTTP / Web (7) camel-graphql, camel-keycloak, camel-netty-http, camel-openapi-java, camel-rest-openapi, camel-sap-netweaver, camel-servlet
AI / ML (6) camel-docling, camel-langchain4j-agent, camel-langchain4j-chat, camel-langchain4j-tools, camel-openai, camel-qdrant
Database / Storage (4) camel-elasticsearch-rest-client, camel-leveldb, camel-mongodb, camel-mongodb-gridfs
Cloud / Kubernetes (3) camel-knative, camel-kubernetes, camel-wasm
Monitoring (3) camel-lra, camel-micrometer, camel-telemetry-dev
Security / Vault (4) camel-cyberark-vault, camel-hashicorp-vault, camel-iso8583, camel-oauth
Other (5) camel-dropbox, camel-groovy, camel-salesforce, camel-servicenow, camel-weather

Plus core modules: camel-core, camel-support, camel-yaml-io, camel-yaml-dsl (these have corresponding extensions-core in CEQ).

Since core already requires Jackson 3, most of these 60 components would "just work" once CEQ adopts Jackson 3 at the core level. The main work items for CEQ would be:

  1. Adopt Jackson 3 in core (non-optional, since core modules use it)
  2. Update data format extensions that expose Jackson types in public API: camel-jackson, camel-cbor, camel-jacksonxml, camel-jackson-avro, camel-jackson-protobuf, camel-jsonpath, camel-jq, camel-xj
  3. Update components with Jackson types in DTOs/config: camel-salesforce, camel-servicenow
  4. Native image reflection configuration for any components using Jackson 3 types that need reflection at runtime

@jamesnetherton jamesnetherton marked this pull request as draft March 11, 2026 09:00
@gnodet
Copy link
Contributor

gnodet commented Mar 11, 2026

Analysis: Remaining Jackson 2 (com.fasterxml.jackson) Dependencies

After investigating the jackson3upgrade branch, here's the status of modules still referencing com.fasterxml.jackson.core:jackson-databind:

Module Jackson 2 Usage Migration Status
camel-jackson Core Jackson 2 data format component Intentional — parallel camel-jackson3 exists
camel-jacksonxml Core Jackson 2 XML data format component Intentional — parallel camel-jackson3xml exists
camel-jslt JsltEndpoint uses ObjectMapper, JsonNode Blocked — JSLT library (0.1.14) depends on com.fasterxml.jackson.core:jackson-databind at runtime
camel-opensearch OpensearchActionRequestConverter, OpensearchProducer Blocked — OpenSearch client 3.7.0 depends on Jackson 2
camel-openapi-java RestOpenApiSupport, RestModelConverters Blocked — Swagger libraries (swagger-core-jakarta 2.2.36) depend on Jackson 2
camel-jbang-mcp No direct source code usage (test-scope deps only) Blocked — Swagger + Quarkus transitive deps need Jackson 2

Conclusion

The Jackson 2 BOM cannot be removed from parent/pom.xml yet. All remaining Jackson 2 usages are either:

  1. Intentional (Jackson 2 data format components kept alongside Jackson 3 variants), or
  2. Blocked by upstream libraries (JSLT, OpenSearch client, Swagger) that haven't released Jackson 3-compatible versions

The camel-jbang-mcp pom already has a comment capturing this: "temporarily needed until a Jackson 3 capable swagger is released".

@gnodet
Copy link
Contributor

gnodet commented Mar 11, 2026

Final Analysis: Ready to Merge

Jackson 2 BOM

The com.fasterxml.jackson:jackson-bom import in parent/pom.xml should be kept. Several modules still depend on Jackson 2, and the BOM ensures version alignment across all com.fasterxml.jackson.* artifacts — including transitive dependencies pulled in by Swagger, OpenSearch, JSLT, and Quarkus. Managing those individually would be fragile and error-prone. This is temporary until upstream libraries release Jackson 3-compatible versions.

Remaining modules (blocked by upstream)

Module Blocker
camel-jackson Intentional — Jackson 2 data format (parallel camel-jackson3 exists)
camel-jacksonxml Intentional — Jackson 2 XML data format (parallel camel-jackson3xml exists)
camel-jslt JSLT library (0.1.14) depends on com.fasterxml.jackson.core:jackson-databind at runtime
camel-opensearch OpenSearch client (3.7.0) depends on Jackson 2
camel-openapi-java Swagger libraries (swagger-core-jakarta 2.2.36) depend on Jackson 2
camel-jbang-mcp No direct source usage — Swagger + Quarkus transitive deps require Jackson 2 (test-scope only)

GraalVM Native / CEQ Impact

Regarding @jamesnetherton's concern about native compilation: the GraalVM native compiler traces all reachable code paths and will discover Jackson 3 types even when they're only used internally (not in public API). This means CEQ will need to handle Jackson 3 at the core level, since core modules (camel-support, camel-core-model, etc.) already require Jackson 3.

However, someone has to move forward first. CEQ is expected to stay on Camel 4.18 LTS for a while, and Quarkus 4.x (with Jackson 3 support) won't land until later this year. Delaying this PR won't change the upstream timeline — it just delays the Camel side of the migration. Once CEQ is ready to adopt Camel 4.19+, the Jackson 3 work will already be in place rather than blocking that upgrade.

Recommendation

This PR should be merged as-is. The Jackson 3 migration is as complete as it can be — all remaining Jackson 2 usages are either intentional (dual Jackson 2/3 data format components) or blocked by upstream libraries that haven't released Jackson 3-compatible versions yet. Those can be migrated incrementally as upstream catches up.

@cunningt
Copy link
Contributor Author

cunningt commented Mar 11, 2026

I think the better strategy than putting a dependencyManagement import of the Jackson 2 jackson-bom in parent/pom.xml https://github.com/apache/camel/pull/21800/changes#diff-b5a06276719e759fe07dfe6f75d781be5f83d2215179d82bdb195ad035348214R3281-R3291 would be to put the dependency management import of camel-bom in each of the individual modules that cannot be converted yet (camel-jackson, camel-jacksonxml, camel-jslt, camel-opensearch, camel-openapi-java, camel-jbang-mcp). That would minimize the recognition of Jackson 2 to just those components.

Putting the Jackson 2 jackson-bom dependencyManagement entry in camel-bom is going to make it apply to all modules when we just want it to apply to a select six, and it may lead to situations where Jackson 2 dependencies are reintroduced in other modules by accident.

@jamesnetherton
Copy link
Contributor

Just want to restate the CQ situation (previous AI generated assumptions aside).

If we do this change in 4.19, then CQ is effectively stuck on 4.18 until Quarkus 4 comes out in 6+ months. Otherwise, we'd need a bunch of Jackson 2 compatible components for the items listed above (which is maybe not feasible given how many there are).

Or CQ needs to find some alternate strategy to deal with the change.

@cunningt cunningt marked this pull request as ready for review March 11, 2026 17:07
@davsclaus
Copy link
Contributor

I think the better strategy than putting a dependencyManagement import of the Jackson 2 jackson-bom in parent/pom.xml https://github.com/apache/camel/pull/21800/changes#diff-b5a06276719e759fe07dfe6f75d781be5f83d2215179d82bdb195ad035348214R3281-R3291 would be to put the dependency management import of camel-bom in each of the individual modules that cannot be converted yet (camel-jackson, camel-jacksonxml, camel-jslt, camel-opensearch, camel-openapi-java, camel-jbang-mcp). That would minimize the recognition of Jackson 2 to just those components.

Putting the Jackson 2 jackson-bom dependencyManagement entry in camel-bom is going to make it apply to all modules when we just want it to apply to a select six, and it may lead to situations where Jackson 2 dependencies are reintroduced in other modules by accident.

Yes that is a good point Tom. Limit jackson 2 to only those components that directly use it.

@davsclaus
Copy link
Contributor

Just want to restate the CQ situation (previous AI generated assumptions aside).

If we do this change in 4.19, then CQ is effectively stuck on 4.18 until Quarkus 4 comes out in 6+ months. Otherwise, we'd need a bunch of Jackson 2 compatible components for the items listed above (which is maybe not feasible given how many there are).

Or CQ needs to find some alternate strategy to deal with the change.

Can you remove/disable native mode for these components; and then for Q4 then if possible add it back.
In JVM mode they ought to be able to work side by side.

We have other CEQ extensions that are JVM only.

@jamesnetherton
Copy link
Contributor

jamesnetherton commented Mar 11, 2026

Can you remove/disable native mode for these components

In theory, yes (although that'd make life quite difficult elsewhere).

The question is, do we need to make this specific change right now? We now have a bunch of camel-jackson3 components if users want to take advantage of those.

But, for the Camel internals, are users going to care if they use Jackson 2.x for a short(ish) period?

@Croway
Copy link
Contributor

Croway commented Mar 11, 2026

I agree with James, why the rush? from a Camel Spring Boot perspective this PR is fine, jackson2 and jackson3 can coexhist, therefore, we can stay on jackson2 for a while and wait for the quarkus jackson3 release, or am I missing something?

@davsclaus
Copy link
Contributor

davsclaus commented Mar 11, 2026

The 4.18 LTS is the last stable release for Jackson 2 and Quarkus 3 as we know it.

The 4.19 onwards releases are a bumpy road to bring SB v4 GA in the Camel 4.22 LTS to give the best SB4 experience we can give Camel users.

At that point in time I don't really think it makes sense to have a CEQ LTS release knowing that Camel is not a well fit at this point, and that Quarkus4 is the major goal, and that Quarkus4 has a LTS planned for Q1 2027 which then would allow CEQ LTS as well. But as early as in Q3 2026 there can be Quarkus 4 developer releases that then allows us to jump forward with CEQ and the Jackson v3 migration.

But it still stands that a Q3 2026 LTS release for CEQ that are based on Q3 and Jackson2 makes less sense, knowing the current state where Camel 4 is going, and that Camel 4.18 LTS is already there as a stable LTS release for Q3 and Jackson2 users.

But in regards to this PR as it is now. Then I agree that this PR may be invasive with all the gazillion of already changes since 4.18. And this is a also a big huge and complex.

So maybe we should park it for now and focus on getting current code base releases as 4.19, after the 4.18.1 patch release.

And then after the 4.19 release we can split this PR into smaller upgrades over 4.20 and 4.21 releases when we identify that the best SB4 experience would be for the camel-xxx component to be Jackson 3 out of the box. Then we can judge whether it makes sense to make a duplicate camel-xxx2 component for Jackson2 for the sake of CEQ.

@cunningt
Copy link
Contributor Author

cunningt commented Mar 11, 2026

Would it make sense to take this PR into draft for a while so it doesn't get accidentally merged and revisit in 4.21 or 4.23?

@davsclaus davsclaus marked this pull request as draft March 11, 2026 18:49
@davsclaus
Copy link
Contributor

This PR has a great analytics from the AIs and massive work from Tom and GNodet so we are well started for all the work ahead to bring Jackson3 upgrades to the remainder Camel components.

@orpiske
Copy link
Contributor

orpiske commented Mar 11, 2026

This is such a large change, that I think it would be possible to consider merging it to an specific branch (i.e.: devel-jackson-3), have some CI jobs setup on ASF Jenkins to test this (and, maybe, rebase it from time to time).

@gnodet
Copy link
Contributor

gnodet commented Mar 11, 2026

Proposed Migration Strategy

After investigating Spring Boot 4's Jackson support and Quarkus 4's timeline, here's a phased approach that could work:

Key Findings

  • Spring Boot 4 does NOT mandate Jackson 3. It ships a deprecated spring-boot-jackson2 module as a stop-gap. You can exclude spring-boot-jackson and use spring-boot-jackson2 instead. Jackson 2 dependency management is still in Boot 4's BOM.
  • Caveat: Spring Data REST and Spring HATEOAS already require Jackson 3 (no Jackson 2 fallback). spring-boot-jackson2 is deprecated and will be removed in a future Boot release.
  • Quarkus 4.0 (which brings Jackson 3) targets Beta 1 around Sept 2026, LTS in Q1 2027.
  • Jackson annotations (com.fasterxml.jackson.core:jackson-annotations) are shared between Jackson 2 and 3 — annotation-only usage doesn't need changes.

Phased Plan

Release Jackson Notes
4.18 LTS Jackson 2 Last stable LTS with Jackson 2 + Quarkus 3
4.19 – 4.21 Jackson 2 in core camel-spring-boot uses spring-boot-jackson2 bridge or starts selective Jackson 3 adoption. No CEQ releases expected for these.
4.22 LTS Jackson 3 Full migration. Aligns with Quarkus 4 availability (LTS Q1 2027). Use OpenRewrite UpgradeJackson_2_3 recipe to automate the bulk of the ~689 file migration.

What To Do With This PR

This PR represents significant and valuable work. Rather than letting it go stale, consider:

  1. Keep it as draft — rebase periodically against main
  2. Or merge to a devel-jackson-3 branch as @orpiske suggested — allows CI validation and incremental progress without blocking the main line
  3. Target the actual merge to main for the 4.21 or 4.22 timeframe, once the 5 blocked components (openapi, opensearch, jslt, json-patch, torchserve) have upstream Jackson 3 support

This avoids rushing the migration while camel-quarkus is still on Jackson 2, and gives us the best shot at a clean 4.22 LTS with full Jackson 3 + Spring Boot 4 + Quarkus 4 alignment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants