IM 8.1.0 — Jackson 2 to 3 Migration

Jackson 2.21.4 → Jackson 3.2.1 · package com.fasterxml.jacksontools.jackson · Camel camel-jackson / camel-jacksonxmlcamel-jackson3 / camel-jackson3xml

Jackson 3 is a new major line with a new root package. IM 8.1.0 moves its own code, the pfx-client API model and the Camel JSON dataformats onto Jackson 3.

The good news first. Most IM customers are not affected: if your routes marshal and unmarshal JSON through the jackson dataformat and you never wrote Java/Groovy against the Jackson API, everything keeps working. The changes below matter if you (a) touch Jackson classes from Groovy, or (b) depend on the exact byte-for-byte shape of produced JSON.


1. What changed at a glance

IM 8.0.x

IM 8.1.0

Root package

com.fasterxml.jackson.*

tools.jackson.*

Annotations package

com.fasterxml.jackson.annotation.*

unchanged — still com.fasterxml.jackson.annotation.*

Camel dataformat component

camel-jackson, camel-jacksonxml

camel-jackson3, camel-jackson3xml

Dataformat name in route XML

jackson / jacksonXml

unchanged

Exceptions

checked IOException / JsonProcessingException

unchecked JacksonException

ObjectMapper

mutable (configure(...) after construction)

immutable — configure via builder

Property order in output

declaration order

alphabetical by default

java.time support

needed JavaTimeModule

built in

The annotations package did NOT move

This surprises people, so it is worth stating plainly: Jackson 3 has no tools.jackson.annotation package. tools.jackson.core:jackson-databind itself depends on com.fasterxml.jackson.core:jackson-annotations. Your DTO annotations stay exactly as they are:

Groovy
import com.fasterxml.jackson.annotation.JsonProperty   // still correct in IM 8.1.0
import com.fasterxml.jackson.annotation.JsonIgnore     // still correct

2. Changes that affect customer scripts

2.1 Sandbox whitelist moved to tools.jacksonDEPLOY-FAIL

The Groovy sandbox allows a fixed list of classes. The Jackson entries changed package, so a script importing the old ones is rejected.

Groovy
// BEFORE (IM 8.0.x)
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken

// AFTER (IM 8.1.0)
import tools.jackson.databind.JsonNode
import tools.jackson.core.JsonParser
import tools.jackson.core.JsonToken

This fails rather than misbehaves — the class simply is not on the allow-list any more.

2.2 ObjectMapper is immutable — DEPLOY-FAIL / RUNTIME

In Jackson 3 an ObjectMapper cannot be reconfigured after construction. The mutator methods are gone; configuration happens on a builder.

Groovy
// BEFORE
def mapper = new ObjectMapper()
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
mapper.registerModule(new JavaTimeModule())
mapper.setDateFormat(new StdDateFormat())

// AFTER
import tools.jackson.databind.json.JsonMapper
def mapper = JsonMapper.builder()
        .disable(tools.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        .defaultDateFormat(new StdDateFormat())
        .build()
// no JavaTimeModule needed - java.time is supported out of the box

To adjust an existing mapper, rebuild it:

Groovy
def tuned = mapper.rebuild().enable(SomeFeature.X).build()

2.3 Parsing errors are unchecked now — SILENT (error handling)

JsonProcessingException and the IOException signatures are replaced by unchecked tools.jackson.core.JacksonException (malformed input surfaces as tools.jackson.core.exc.StreamReadException).

Groovy
// BEFORE
try {
    mapper.readValue(body, Map)
} catch (IOException e) {          // AFTER: never thrown -> catch block is dead code
    handleBadPayload(e)
}

// AFTER
try {
    mapper.readValue(body, Map)
} catch (tools.jackson.core.JacksonException e) {
    handleBadPayload(e)
}

This is the dangerous one. A catch (IOException) block does not fail to compile in Groovy — it simply never matches, so a payload that used to be handled gracefully now propagates as an unhandled error. Search your scripts for catch blocks around JSON parsing.

2.4 TextNode renamed to StringNodeDEPLOY-FAIL

Groovy
// BEFORE
TextNode.valueOf("x")

// AFTER
StringNode.valueOf("x")

Other node types (ObjectNode, ArrayNode, IntNode, BooleanNode, NullNode, DecimalNode, …) keep their names.


3. Changes that affect produced JSON

3.1 Property order — handled by IM for the Pricefx API, relevant for your own mappers

Jackson 3 enables SORT_PROPERTIES_ALPHABETICALLY by default; Jackson 2 did not. The same object therefore serialises with its fields in a different order.

JSON
// Jackson 2 (declaration order)
{"operator":"equals","fieldName":"label","value":"Test"}

// Jackson 3 default (alphabetical)
{"fieldName":"label","operator":"equals","value":"Test"}

What IM does for you. For calls to the Pricefx API, IM explicitly disables alphabetical sorting so the wire format is unchanged from IM 8.0.x. You do not need to do anything for pfx-api: / pfx-client traffic.

Where it can still reach you. If one of your routes marshals JSON with the jackson dataformat and the receiving system is order-sensitive, or if you assert on exact JSON strings in your own tests, expect alphabetical order from the dataformat. Well-behaved JSON consumers do not care about member order — but strict schema validators and string comparisons do.

3.2 Trailing content is rejected by default — RUNTIME

Jackson 3 enables FAIL_ON_TRAILING_TOKENS by default. Input with anything after the first JSON value (including a stray second document, or a malformed payload that happens to have parsed so far) now throws where Jackson 2 quietly ignored the remainder.

What IM does for you. IM deliberately disables this for the two paths that read customer-supplied and external-system data — filter definitions and REST/HTTP responses handled by pfx-client — to preserve IM 8.0.x leniency. Your own ObjectMapper instances get the Jackson 3 default unless you disable it yourself.

3.3 Unknown properties are ignored by default

Jackson 3 turns FAIL_ON_UNKNOWN_PROPERTIES off by default (Jackson 2 had it on). Deserialising a payload with extra fields now succeeds where it previously threw.

Watch for. Scripts that relied on the exception as validation — "if it parses, the payload is the right shape" is no longer true by default. Enable it explicitly if you depend on it:

Groovy
JsonMapper.builder().enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).build()

3.4 java.time is built in

JavaTimeModule no longer exists and is not needed; LocalDate, Instant and friends serialise out of the box. Remove the registration — it will not compile otherwise.

3.5 Large payloads

IM applies its integration.jackson.max-string-length limit to both Jackson majors, so the protection you configured on IM 8.0.x still applies. Jackson 3 also carries its own StreamReadConstraints defaults; note that Jackson 3 lowered the default maximum nesting depth from 1000 to 500 — deeply nested JSON that previously parsed could now be rejected.


4. Camel dataformat

The component behind the jackson dataformat changed from camel-jackson to camel-jackson3.

XML
<!-- unchanged in your route XML -->
<unmarshal><json library="Jackson"/></unmarshal>
<marshal><json library="Jackson"/></marshal>

The dataformat name and syntax are unchanged — Camel resolves whichever implementation is on the classpath. What changes is the behaviour underneath it: the defaults in §3 apply.

pfx-event with jsonParser=jackson likewise keeps its configuration and moves to Jackson 3.


5. Where Jackson 2 still exists

Jackson 2 has not disappeared from the runtime; it is pulled in by four third-party dependencies that have no Jackson 3 build yet:

dependency

Jackson 2 artifacts it needs

used for

camel-openapi-java

jackson-dataformat-yaml, jackson-datatype-joda, jackson-jakarta-rs-json-provider, jackson-jakarta-rs-base, jackson-module-jakarta-xmlbind-annotations

Rest DSL /api-doc generation

camel-metrics

jackson-core, jackson-databind

metrics serialisation

google-cloud-storage (via camel-google-storage)

jackson-dataformat-xml

GCS client internals

kubernetes-client-api

jackson-datatype-jsr310

k8s model

No IM code imports com.fasterxml.jackson.databind or .core. These are internal to the libraries above and will disappear as each ships a Jackson 3 build.


6. Search patterns for your repository

What to find

Pattern

Section

Old Jackson imports

`com\.fasterxml\.jackson\.(databind\

core\

dataformat\

datatype\

module)`

§2.1

Annotation imports (leave alone)

com\.fasterxml\.jackson\.annotation

§1

Mapper mutation

`\.configure\(\

registerModule\

setDateFormat\

setSerializationInclusion`

§2.2

Dead catch blocks

`catch\s\(\s(IOException\

JsonProcessingException)`

§2.3

TextNode

TextNode

§2.4

JavaTimeModule

JavaTimeModule

§3.4

Exact-JSON assertions

assert.*\{".*"\}

§3.1


7. Sources

  • Jackson 3.0 release notes and migration notes

  • Apache Camel camel-jackson3 component documentation

  • Verified against IM's own migration: IM's 4 000+ tests and pfx-client's 513 tests run on Jackson 3.2.1; the behaviours in §3.1, §3.2 and §3.3 were each observed and handled during that migration.