Andrea Cosentino created CAMEL-24442:
----------------------------------------
Summary: 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
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)