Hello,
I have just updated my castor version from 1.0 to 1.3, and I encountered
a problem with the Unmarshaller when using the same mapping object in
different threads.
In my current application, I noticed this as one of my objects was only
partially unmarshalled (it was missing some of the attributes in the
xml-file). This object was unmarshalled at the same time as another
object, both with separate Unmarshalle-objects, but using the same
Mapping-object.
First I tried to reproduce this behavior in a cleaner environment,
without luck. I guess it is a timing issue, which I cannot reproduce
under my artificial test-environment. Then I tried reproduce it with
breakpoints in my debugger and I managed to create a different bug, with
an exception:
org.exolab.castor.xml.MarshalException: Stream closed
at
org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:757)
at
org.castor.mapping.MappingUnmarshaller.loadMappingInternal(MappingUnmars
haller.java:247)
at
org.castor.mapping.MappingUnmarshaller.getMappingLoader(MappingUnmarshal
ler.java:155)
at
org.castor.mapping.MappingUnmarshaller.getMappingLoader(MappingUnmarshal
ler.java:130)
at
org.exolab.castor.xml.Unmarshaller.setMapping(Unmarshaller.java:525)
at test.DBConnectionCfg.unmarshal(DBConnectionCfg.java:111)
at test.DBConnectionCfg.unmarshal(DBConnectionCfg.java:121)
at test.Test$2.run(Test.java:41)
at java.lang.Thread.run(Thread.java:619)
The critical region is:
private void loadMappingInternal(final Mapping mapping, final
DTDResolver resolver,
final InputSource source)
throws MappingException {
// Clear all the cached resolvers, so they can be reconstructed
a
// second time based on the new mappings loaded
_registry.clear();
Object id = source.getSystemId();
if (id == null) { id = source.getByteStream(); }
if (id != null) {
//check that the mapping has already been processed
if (mapping.processed(id)) { return; }
// *** Critical, error is produced if both
// *** threads reach this point at the same time
//mark the mapping as being processed
mapping.markAsProcessed(id);
}
This is not the same issue which I discovered in my application, and I
could not reproduce this error without the debugger, but they are
somehow related. When I put a synchronized-block over
Unmarshaller.setMapping(), my original issue disappeared. I tried to
find the cause of my issue, but I this is the first time I have looked
into the source code, and I really don't know where to look.
So, should I report this as a bug?
Best regards,
Mads Stavang