Hi,
I'm trying to move MarshalledValue to use an injected Marshaller rather
than relying on standard serialization and this is causing me a small
problem:
One of the trade offs when making JBoss Marshalling
marshaller/unmarshaller a thread local in JBoss Marshaller is reentrancy.
When marshalling a MarshalledValue, we call start() on the marshaller
and then we'd call marshallerValue.getRaw(). The most reasonable
implementation using an injected marshaller would call:
raw = marshaller.objectToBuffer(instance).getBuf();
By calling oTB again, you're calling start on the marshaller below and
since this is a thread local, this is exactly the same instance and you
get issues.
I don't think JBoss Marshalling marshaller/unmarshaller are meant to be
reentrant and this is not my intention.
A second option would be to simply create a new marshaller in
MarshalledValue.getRaw() but this means some initialisation that
involves reflection, so this is no good.
The third option, an my preferred one, would be to add a boolean
parameter to Marshaller.startObjectOutput() called cached. Based on this
parameter, you could either get the marshaller from the thread local or
if false, get a new one from the factory. This would get around the
issue and makes the API more flexible coping with reentrant marshalling
while for the rest of cases, taking advantage of the performance gains
from using thread locals. The code in marshallerValue.getRaw() would
then look like this:
ExposedByteArrayOutputStream baos = new ExposedByteArrayOutputStream(128);
ObjectOutput out = marshaller.startObjectOutput(baos, false);
try {
marshaller.objectToObjectStream(instance);
} finally {
marshaller.finishObjectOutput(out);
}
raw = baos.getRawBuffer();
Of course, I would document this accordingly in the API so that cached
is only set to false if reentrant marshalling could happen.
Thoughts?
--
Galder ZamarreƱo
Sr. Software Maintenance Engineer
JBoss, a division of Red Hat