I'm sure everyone has seen this thread on fop-users. Any particular
preferences on one of the two options I listed below? The first will
require coordination with Batik as they are supposed to migrate to that
class and it's basically their version. We used a modified version of
theirs. The second is probably cleaner but since the change is
backwards-incompatible for any ElementMapping implementation (Barcode4J,
for example), this is not to be taken lightly. I think the first is
easier, should not have any side-effects but feels more like patchwork.
On 15.05.2006 09:27:29 Jeremias Maerki wrote:
> On 13.05.2006 00:45:51 Ryan Gustafson wrote:
> > Hi Jeremias,
> > > The Service class is properly synchronized.
> > I downloaded the source, and agree.
> > > The ElementMapping
> > > classes, however, are recreated for each FopFactory. There's no
> > > sharing of these classes between multiple FopFactory instances.
> > I downloaded the XML Graphics Common code. And I've reviewed the
> > FOP code. I do not see it this way, see my further comments
> > below...
> > > Since you're using the deprecated Fop constructor a new
> > > FopFactory is instantiated for each new Fop instance. So I don't
> > > see why the ElementMapping classes need to be thread-safe.
> > It's true, we have unique FOP instances, each with unique FopFactory
> > instances, each with a unique ElementMappingRegistry instance.
> > Where they all come together is in the ElementMappingRegistry static
> > call to Service.providers(), which based on the code I saw in the
> > XML Graphics Common 1.0 version of Service.java, would appear to
> > return an Iterator over the _same_ statically cached list List,
> > which then contains the same ElementMapping objects. Thus, the
> > FopFactory objects end up using the same ElementMapping objects.
> > The Service code appears to be using standard ArrayList and HashMap,
> > so the Map.put()/Map.get() and List.iterator() method work normally
> > (no behind the scenes cloning/copying going on). Further, it is
> > directly placing a normal FOElementMapping instance into the list
> > (no special wrapping going on).
> Right, I should have placed a breakpoint earlier to see what happens. I
> was under the assumption that only the class names are stored in the
> list. The reason for that: We used a modified version of Batik's Service
> class which only saved the class names. When I populated XML Graphics
> Commons I took Batik's implementation and adjusted FOP's code to use
> that. Turns out this wasn't without side-effects. From this POV, the
> multi-threading issue is absolutely logical.
> > Should the Service be returning caller unique instances in the
> > Iterator? If so, it needs to be re-written. The JavaDoc doesn't
> > give me the feeling that is supposed to do this however.
> I see two possible routes:
> 1. Adding an optional parameter to the Service class' providers() method
> which allows to return class names instead of instances. This will
> restore the previous behaviour and maintain backwards compatibility with
> the existing ElementMapping implementations.
> 2. Change ElementMapping's constructor to accept the namespace URI as a
> parameter and call initialize() right after that. Drawback: It's a
> backwards-incompatible change.
> We'll discuss that on fop-dev and decide what to do.
> > I only spent about 20 minutes looking over this, so I may have
> > overlooked something?
> > > I don't buy it, yet. I can see from your stack trace that
> > something's
> > > wrong but I'm not sure you've found the right spot. What you can
> > > try is to synchronize ElementMapping.getTable() and check if this
> > > changes anything, but I just don't understand why two threads
> > > would modify the same HashMap in ElementMapping.
> > >
> > > I wish I could reproduce the problem. I've tried yesterday, but
> > > didn't succeed. I ran up to 60 threads in parallel with the
> > > deprecated constructor and had no problems. But on the other
> > > hand, I only had a single-processor machine to test on. Are you
> > > on a multi-processor box
> > Yup, multi-processor box. That definately makes it easier to expose
> > thread safety issues. I believe we were running about 5 thread max
> > through the FOP code. Also we've only seen it once so far, it may
> > be tricky to trigger.
> > Tell you what, I'm due to take over working on our FOP related code
> > in a couple weeks. When I do, I'll keep my eye out for this issue,
> > and if I find out anything more, I'll do what I can to find the
> > source and share what I find.
> > In the meantime, we'll move to the non-deprecated API, and presume
> > the issue is solved, until we get more Exceptions to prove
> > otherwise.
> Certainly a good move. I believe I know now what's wrong so we can take
> appropriate action. Thanks for being so persistent.