You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Federico Mariani (Jira)" <ji...@apache.org> on 2026/07/16 09:40:00 UTC

[jira] [Updated] (CAMEL-24169) camel-jackson-avro / camel-jackson-protobuf - schema resolver latches the first resolved schema forever, breaking multi-type routes

     [ https://issues.apache.org/jira/browse/CAMEL-24169?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Federico Mariani updated CAMEL-24169:
-------------------------------------
    Attachment: AvroSchemaResolverLatchesFirstSchemaIssueTest.java

> camel-jackson-avro / camel-jackson-protobuf - schema resolver latches the first resolved schema forever, breaking multi-type routes
> -----------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24169
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24169
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-jackson-avro
>            Reporter: Federico Mariani
>            Priority: Major
>              Labels: ai-assisted-review, dataformat
>         Attachments: AvroSchemaResolverLatchesFirstSchemaIssueTest.java
>
>
> *Severity:* High
> *Affects:* 4.x
> h3. Problem
> {{AvroSchemaResolver.computeIfAbsent()}} (and the {{ProtobufSchemaResolver}} twin) begins with {{if (this.schema != null) return this.schema;}} and ends with {{if (answer != null) this.schema = answer;}}. So the *first* exchange that resolves a schema permanently caches it in the instance field, and every later exchange short-circuits to it regardless of its own body type or per-exchange {{schema}} / {{X-Content-Class}} property. The per-type {{schemes}} {{ConcurrentMap}} (which exists to cache per content class) becomes dead after the first hit. The write is also unsynchronized from exchange threads.
> These resolvers are auto-discovered from the registry by {{AbstractJacksonDataFormat.doStart()}} and shared across all routes/data formats in the context, so a single resolver cross-contaminates different routes.
> h3. Failure scenario (reproduced)
> One {{AvroSchemaResolver}}; exchange 1 resolves a {{Person}} schema (latched), exchange 2 supplies its own {{Animal}} schema but resolves to the latched {{Person}} schema -> marshalling with the wrong schema (Jackson-Avro error or mis-encoded binary). Single-type kamelet usage hides it.
> h3. Suggested fix
> Only treat {{this.schema}} as authoritative when set explicitly via {{setSchema(...)}} (separate field/flag); rely on the {{schemes}} map + exchange properties for dynamic resolution; drop the trailing {{this.schema = answer}} latch. Apply to both Avro and Protobuf resolvers.
> h3. Reproducer
> Attached {{AvroSchemaResolverLatchesFirstSchemaIssueTest.java}}: drives one resolver through two exchanges carrying distinct inline schemas; exchange 2 resolves to {{Person}} (expected {{Animal}}). RED on current code.
> ----
> _Reported by Claude Code on behalf of Federico Mariani (Croway). A failing JUnit reproducer (confirmed RED on 4.22.0-SNAPSHOT) is attached._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)