0

I am trying to convert the code below to Coldfusion. I am currently stuck on how to convert the "Transformer transformer = TransformerFactory.newInstance().newTransformer()" line to Coldfusion. Can anyone help convert this code?

The error message I get when using transformer = loader.create("javax.xml.transform.TransformerFactory").newInstance().newTransfo‌rmer();

Error casting an object of type org.apache.xalan.processor.TransformerFactoryImpl cannot be cast to javax.xml.transform.TransformerFactory to an incompatible type. This usually indicates a programming error in Java, although it could also mean you have tried to use a foreign object in a different way than it was designed. org.apache.xalan.processor.TransformerFactoryImpl cannot be cast to javax.xml.transform.TransformerFactory

    Document svgXmlDoc = ...

    File svgFile = File.createTempFile("graphic-", ".svg");
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    DOMSource source2 = new DOMSource(svgXmlDoc);
    FileOutputStream fOut = new FileOutputStream(svgFile);
    try { transformer.transform(source2, new StreamResult(fOut)); }
    finally { fOut.close(); }

    // Convert the SVG into PDF
    File outputFile = File.createTempFile("result-", ".pdf");
   SVGConverter converter = new SVGConverter();
   converter.setDestinationType(DestinationType.PDF);
   converter.setSources(new String[] { svgFile.toString() });
   converter.setDst(outputFile);
   converter.execute();

Here is my code so far.

<cfscript>
paths = arrayNew(1);
paths[1] = expandPath("jar\avalon-framework-impl-4.2.0.jar");
paths[2] = expandPath("jar\batik-all-1.7.jar");
paths[3] = expandPath("jar\commons-io-1.3.1.jar");
paths[4] = expandPath("jar\commons-logging-1.0.4.jar");
paths[5] = expandPath("jar\fop-0.9.5.jar");
paths[6] = expandPath("jar\apache-log4j-1.2.15.jar");
paths[7] = expandPath("jar\xml-apis-ext.jar");
paths[8] = expandPath("jar\xmlgraphics-commons-1.3.1.jar");
paths[8] = expandPath("jar\javax.xml-1.3.4.jar");

loader = createObject("component", "javaloader.JavaLoader").init(paths);

destinationtype = loader.create("org.apache.batik.apps.rasterizer.DestinationType");
svgconverter = loader.create("org.apache.batik.apps.rasterizer.SVGConverter");


// SVG available as a DOM object (created programatically by my program)
svgXmlDoc = '<svg><text y="3.58in" x="1.5000in" id="fooddesc1" text-anchor="start" alignment-baseline="baseline">This is a test.</text></svg>';

// Save this SVG into a file (required by SVG -> PDF transformation process)
f = loader.create("java.io.File");
svgFile = f.createTempFile("graphic-", ".svg");
transformer = loader.create("javax.xml.transform.TransformerFactory");
source2 = loader.create("javax.xml.transform.dom.DOMSource").init(svgXmlDoc);
fOut  = loader.create("java.io.FileOutputStream").init(svgFile);
</cfscript>
SGekko
  • 335
  • 1
  • 19
  • Just skimming the code, it should be almost the same ie `transformer = loader.create("javax.xml.transform.TransformerFactory").newInstance().newTransformer();`. Obviously you can split it into multiple calls if preferred. – Leigh Apr 03 '15 at 20:04
  • I tried that but this is the error I receive. Error casting an object of type org.apache.xalan.processor.TransformerFactoryImpl cannot be cast to javax.xml.transform.TransformerFactory to an incompatible type – SGekko Apr 03 '15 at 20:09
  • (Edit) Hm.. let me check something. Meanwhile, can you update your question with the full error message? Not everyone reads comments. Also, what version of CF are you running? – Leigh Apr 03 '15 at 20:14
  • I am using ColdFusion 11. Just a FYI, I am not proficient in Java – SGekko Apr 03 '15 at 20:17
  • (Edit) Okay. BTW, for CF10+ you do not need the javaLoader. A rip of that awesome project is now [baked into CF10+](http://stackoverflow.com/questions/28670082/). I am assuming it is a jar conflict. Can you tell me where you download those specific jars? I want to test with the same versions you are using. – Leigh Apr 03 '15 at 20:31
  • Not specifically. I believe I used Google for some and some from FindJar.com. Think there may be a conflict? – SGekko Apr 03 '15 at 20:35
  • Can you please post the full error in your question? I am not very familiar w/newInstance(). Not sure if it is related to [the rules here](http://docs.oracle.com/javase/7/docs/api/javax/xml/transform/TransformerFactory.html#newInstance%28%29). Where did you get the code above? – Leigh Apr 03 '15 at 21:15

1 Answers1

1

Looks like the code you are translating is from this thread. I would suggest using the accepted answer instead. It is a bit simpler. However, you do not need to use the JavaLoader since you are running CF11. Starting from CF10, a rip of Mark Mandel's JavaLoader.cfc is baked into CF. Applications can load jars dynamically using this.javaSettings in the Application.cfc. The simplest option is to stick all of the jars in a separate directory, and point to that path in your application settings. Then you can load any of the classes with createObject().

   this.javaSettings = {LoadPaths = [ "/path/to/jars_folder/" ]};

Example:

transcoder = createObject("java", "org.apache.fop.svg.PDFTranscoder").init();

// load text into a reader and create the source input
svgText = '<svg xmlns="http://www.w3.org/2000/svg"><text y="3.58in" x="1.5000in" id="fooddesc1" text-anchor="start" alignment-baseline="baseline">This is a test.</text></svg>';
reader = createObject("java", "java.io.StringReader").init(svgText);
input = createObject("java", "org.apache.batik.transcoder.TranscoderInput").init(reader);

// for demo purposes, create a unique file name
outPath = ExpandPath("./"& createUUID() &".pdf");
fos = createObject("java", "java.io.FileOutputStream").init(outPath); 
output = createObject("java", "org.apache.batik.transcoder.TranscoderOutput").init(fos);

transcoder.transcode(input, output);
// ALWAYS close the stream
fos.close();

The simple example above was tested with the following jars under CF10, so YMMV.

  • avalon-framework-4.2.0.jar
  • commons-io-1.3.1.jar
  • batik-all-1.7.jar
  • fop-0.9.5.jar
  • xmlgraphics-commons-1.3.1.jar
  • xml-apis-ext-1.3.04.jar



Original Exception

Error casting an object of type org.apache.xalan.processor.TransformerFactoryImpl cannot be cast to javax.xml.transform.TransformerFactory

I am not entirely sure what was causing the ClassCastException. I suspect it is some sort of a class loader issue. CF is already bundled with several of the libraries you are loading. At least one of the core jars contains another version of the TransformerFactory. Under CF10, the error goes away if you omit the javax.xml-1.3.4.jar (and commons-logging-1.0.4.jar). So somehow the various pieces are not playing well together under the custom class loader. Hence why things blow up when you call TransformerFactory.newInstance(). However, since you do not really need that class anyway, I did not look into it further...

Update:

FWIW, the error was definitely caused by a class loader conflict. The original code works fine if you omit javax.xml-1.3.4.jar (and commons-logging-1.0.4.jar).

If you look at the source for TransformerFactory.newInstance() you can see a call to FactoryFinder.find() which references different class loaders depending on the conditions. Since CF already includes the javax.xml.* package, I suspect some of the objects are being created by CF's class loader ie org.apache.xalan.processor.TransformerFactoryImpl, while others ie TransformerFactoryare created by a different class loader ie JavaLoader.

Class loaders are notoriously finicky. You have to follow certain rules or the objects created by one class loader will NOT be recognized by another - not even if they represent the exact same class. That seems to be what is happening here. You could probably fiddle with the parent or context class loader to get around it, but in this case it is simpler to just omit the javax.xml-1.3.4.jar.

Now having said all that ... I do not think you need the TransformerFactory code at all. It sounds like you already have a valid SVG string. Simply simply save it to a file with FileWrite() and move on with the rest of the code.

Community
  • 1
  • 1
Leigh
  • 28,765
  • 10
  • 55
  • 103
  • Thanks Leigh. I will get back on this next week and rethink my approach based on your findings. – SGekko Apr 05 '15 at 11:57
  • Did a little more digging and found the cause of the original error. While you could use the original code with a few tweaks (see update) the other example is simpler. Assuming the results are the same, I would recommend using the simpler one instead. – Leigh Apr 07 '15 at 19:09
  • Thanks Leigh. I ended up using your example and received more errors. I had to change out a couple jar files and it finally worked. Thanks again. – SGekko Apr 08 '15 at 20:50
  • Welcome. It worked fine under CF10 (assuming we are using the same jars) so it is quite possible there are some differences in CF11. Out of curiosity, which ones did you end up using, so I can update the answer? – Leigh Apr 08 '15 at 23:47