[
https://issues.apache.org/jira/browse/CAMEL-24442?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Work on CAMEL-24442 started by Andrea Cosentino.
------------------------------------------------
> camel-thrift - unmarshal deserializes into and returns a single shared
> instance
> -------------------------------------------------------------------------------
>
> Key: CAMEL-24442
> URL: https://issues.apache.org/jira/browse/CAMEL-24442
> Project: Camel
> Issue Type: Bug
> Reporter: Andrea Cosentino
> Assignee: Andrea Cosentino
> Priority: Major
> Fix For: 4.23.0
>
>
> {{ThriftDataFormat.unmarshal()}} deserializes into the {{defaultInstance}}
> field and returns that same object:
> {code:java}
> if (contentTypeFormat.equals(CONTENT_TYPE_FORMAT_JSON)) {
> deserializer = new TDeserializer(new TJSONProtocol.Factory());
> deserializer.deserialize(defaultInstance,
> IOUtils.toByteArray(inputStream));
> } else if (contentTypeFormat.equals(CONTENT_TYPE_FORMAT_BINARY)) {
> ...
> }
> return defaultInstance;
> {code}
> The data format is a singleton shared by every exchange on the route, and
> {{TBase.read()}} sets only the fields present in the incoming bytes without
> clearing the object first. Three consequences:
> * A message that omits an optional field keeps the value left there by the
> *previous* message. This happens even with a single thread.
> * Concurrent unmarshals interleave field writes into the one object.
> * Every in-flight body is literally the same reference, so mutating one
> downstream changes the others.
> {{ProtobufDataFormat}} handles this correctly - it builds a new instance per
> unmarshal. Proposal: do the same here, using {{defaultInstance.deepCopy()}}
> (or {{instanceClass.getDeclaredConstructor().newInstance()}}) as the
> deserialization target, and create the {{TDeserializer}} per call or make it
> a thread-local.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)