Claus Ibsen created CAMEL-25924:
-----------------------------------

             Summary: camel-kafka - the producer sends a Jackson ObjectNode 
body as one record per field value, and drops a Jackson 3 scalar node
                 Key: CAMEL-25924
                 URL: https://issues.apache.org/jira/browse/CAMEL-25924
             Project: Camel
          Issue Type: Bug
          Components: camel-kafka
    Affects Versions: 4.18.0, 4.22.0, 4.23.0
            Reporter: Claus Ibsen
             Fix For: 4.24.0


With {{useIterator=true}} (the default), the Kafka producer sends a body it can 
iterate as one record per element. CAMEL-23883 narrowed this for a Jackson 
{{JsonNode}}: only a container node is split, so a scalar node is sent as one 
record. Two cases are left.

*1. A Jackson {{ObjectNode}} is split into its field values.* A {{JsonNode}} is 
an {{Iterable}} of its elements, and the elements of an object node are the 
values of its fields. So a body
{code:json}
{"orderId": 42, "customer": "acme", "total": 9.5}
{code}
as an {{ObjectNode}} (from {{unmarshal}} with {{unmarshalType: 
com.fasterxml.jackson.databind.JsonNode}}, or a jq expression that returns an 
object) is sent as three records, {{42}}, {{"acme"}} and {{9.5}}, without the 
field names. Checked with Jackson 2.22: {{isContainerNode()}} is true for the 
object node, and iterating it gives the three values.

*2. A Jackson 3 node is not recognized.* {{isIterable}} checks 
{{com.fasterxml.jackson.databind.JsonNode}} only. A Jackson 3 
{{tools.jackson.databind.JsonNode}} (camel-jackson3) is an {{Iterable}} too, so 
it takes the {{instanceof Iterable}} branch. A Jackson 3 scalar node such as 
{{IntNode}} has no elements, so nothing is sent and nothing fails: the case 
CAMEL-23883 fixed for Jackson 2. Checked with Jackson 3.2.3: an {{IntNode}} is 
an {{Iterable}} of size 0. A Jackson 3 object node is split as in 1.

{code:java}
// KafkaProducer.java:316 on main
private boolean isIterable(Object body) {
    if (body instanceof JsonNode node) {
        return node.isContainerNode();
    }
    if (body instanceof Iterable || body instanceof Iterator) {
        return true;
    }
    return false;
}
{code}

*Proposed change*: split only a JSON array ({{isArray()}}), for Jackson 2 and 
Jackson 3 nodes (Jackson 3 by its class name, as camel-kafka does not depend on 
it), and send an object node or a scalar node as one record. The 4.22 upgrade 
guide (CAMEL-23883) says that object nodes are still split, so the change needs 
an entry in the 4.24 upgrade guide.

The object node is split in 4.18.0, 4.22.0 and 4.23.0; the Jackson 3 scalar 
node is dropped in 4.22.0 and 4.23.0, which have camel-jackson3. Both the sync 
and the async send path iterate an empty iterator without sending.

_Claude Code on behalf of davsclaus_



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

Reply via email to