Jeremias, thanks for the clarification about the FopFactory.
I had a look at your old commit at
http://svn.apache.org/viewvc?view=revision&revision=724163
The current situation in trunk is that in
PDFImageHandlerSVG.handleImage() the SVG document is not cloned but in
other places it is. Examples of cloning are in ImageConverterSVG2G2D,
AbstractGenericSVGHandler, AFPImageHandlerSVG, AFPSVGHandler,
Java2DSVGHandler, PSSVGHandler.
This should be the cause of all the stack traces I get. They all go
through PDFImageHandlerSVG and after adding the document cloning (see
attached patch), I can no longer reproduce the error.
It should be safe to add the SVG document cloning in there but I would
better reduce a little of code duplication. In all those places it is
required to build a GraphicsNode and the way of doing this is similar.
But maybe this is out of scope.
Any suggestion on how to proceed with this ?
On 2-9-10 11:28 AM, Jeremias Maerki wrote:
Peter could be right. And there I thought I had this under control. But
with so many open Bugzilla issues, things get lost quickly. I've seen
multi-threading issues inside Batik myself in a production system and
haven't been able to put my finger on it since I though I had this fixed,
but it could be that I haven't really fixed it for all cases. I'll have
to look into it.
At any rate, FopFactory is supposed to be thread-safe. I always have one
FopFactory instance per configuration and that is usually one for the
whole JVM.
On 02.09.2010 10:08:19 Alexios Giotis wrote:
Hi Peter,
Thanks for pointing this out. It differs in that the instance of
FOUserAgent was shared, but other than this, it's exactly the same case.
Finally, this leads to
https://issues.apache.org/bugzilla/show_bug.cgi?id=46360
which is still open.
As I read from the thread, this is a complex case and in batik they have
good reasons not to be thread-safe.
Finally, sorry for my other posting with the same title. I though that
only the subscribed email address can post.
Alexis
On 1-9-10 11:30 PM, Peter Coppens wrote:
Alexis,
This reminds me of something similar I ran into a while ago. I can't remember
the details nor how I eventually got around this and/or whether you run into
the same but the (weird) behavior you describe does look very similar.
See
http://old.nabble.com/Batik-exception-when-using-fop-with-svg-images-in-threaded-environment-td20809049.html
Perhaps it helps
Peter
On 01 Sep 2010, at 17:53, Alexios Giotis wrote:
Hello,
The javadoc and the class name suggest that FopFactory should be thread-safe
although this is not explicitly written. If this is not thread-safe then please
ignore what follows.
I am using FOP 1.0 to produce PDF documents concurrently from FOP intermediate
format. The PDF documents share a lot of common images, so I decided to use a
single instance of FopFactory to reduce memory requirements. From the single
FopFactory, I produce different instances for different threads like this:
FOUserAgent userAgent = fopFactory.newFOUserAgent();
IFDocumentHandler targetHandler =
fopFactory.getRendererFactory().createDocumentHandler(userAgent,outputFormat);
IFUtil.setupFonts(targetHandler);
targetHandler.setResult(new StreamResult(outStream));
IFConcatenator concatenator = new IFConcatenator(targetHandler, null);
for (int i = 0; i< numberOfDocumentsToConcatenate; i++) {
Source src = new SAXSource(myOwnApplicationXmlFilters, new
InputSource(myOwnInputStream));
concatenator.appendDocument(src);
}
The problem is that even on my 2-core laptop, I frequently get exceptions silently written in standard error. Different
stacktraces are attached and as you can see happen when batik parses the SVG files. For the same input the strings read are
corrupted. For example the overflow="visible" is read as "vssible" and then later as "vissibll".
Also the fill="#EC2227" is try to parse "E7E8" as color.
The workaround for my application is to have a new instance of FopFactory per
thread but I would like to fix it and create a patch. Since I am quite new to
FOP, I would like some advise on what should be the proper level. The higher
one would be the FopFactory (but it's too high and I could do it externally in
my code), then there is the org.apache.xmlgraphics.image.loader.ImageManager
and at the end we get to the very low level
org.apache.batik.css.engine.CSSEngine or org.apache.batik.css.parser.Parser.
Secondly, I think it's not a good practice that the exceptions are written in
STDERR instead of propagating to the application. What do you think ?
This is my first post to fop-dev and hopefully this is the proper one.
Thanks,
Alexis
<stacktraces.txt>
Jeremias Maerki
Index: PDFImageHandlerSVG.java
===================================================================
--- PDFImageHandlerSVG.java (revision 991883)
+++ PDFImageHandlerSVG.java (working copy)
@@ -38,6 +38,7 @@
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.image.loader.batik.BatikImageFlavors;
+import org.apache.fop.image.loader.batik.BatikUtil;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.RenderingContext;
import org.apache.fop.render.pdf.PDFLogicalStructureHandler.MarkedContentInfo;
@@ -46,6 +47,7 @@
import org.apache.fop.svg.PDFGraphics2D;
import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;
+import org.w3c.dom.Document;
/**
* Image Handler implementation which handles SVG images.
@@ -82,10 +84,14 @@
userAgent.getFactory().getImageManager(),
userAgent.getImageSessionContext(),
new AffineTransform());
+
+ //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like
the CSS engine)
+ //to it.
+ Document clonedDoc =
BatikUtil.cloneSVGDocument(imageSVG.getDocument());
GraphicsNode root;
try {
- root = builder.build(ctx, imageSVG.getDocument());
+ root = builder.build(ctx, clonedDoc);
builder = null;
} catch (Exception e) {
SVGEventProducer eventProducer = SVGEventProducer.Provider.get(