Page 1 of 1

Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Thu Jun 07, 2012 8:54 pm
by gaucho
Hi there,

This topic is related withProblems with WordProcessingMLPackage.

I have a Weblogic domain with a bunch of deployments. One of them is using docx4j-2.7.1.jar. At some point the XmlUtils (org.docx4j.XmlUtils ) class is changing the javax.xml.parsers properties in the JVM. Unfortunately Weblogic is not using the required implementation, xalan/xerces, and the server is completely screw up. I.e., after changing these properties is not able to perform deploy/undeploy operations.

One workaround that I am thinking of is to override the setProperty method, via java.util.Properties extension, and forbid the setting of the javax.xml.parsers. See How to detect if a Java System property has changed?

Also I can declare, in the application, the use of a specific implementation:
Code: Select all
<xml>
      <parser-factory>
        <saxparser-factory>org.apache.xerces.jaxp.SAXParserFactoryImpl</saxparser-factory>
        <document-builder-factory>org.apache.xerces.jaxp.DocumentBuilderFactoryImpl</document-builder-factory>
        <transformer-factory>org.apache.xalan.processor.TransformerFactoryImpl</transformer-factory>
      </parser-factory>
</xml>


... and add the required libraries to the application Classpath, but how I can avoid the System.setProperty invocation? Change the source code of the docx4java library?

Any thoughts on this?

Thanks in advance,

Luis

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Thu Jun 07, 2012 11:34 pm
by jason
docx4j has real Xalan as a dependency, because I found the re-packaged version included in Java 6 was incomplete. docx4j 2.8.0 includes 2 ways of getting HTML output, one of which is via XSLT (and Xalan extensions). PDF output uses Xalan extension functions.

Also, I've encountered issues with Crimson in the past, hence a preference for com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl in Java 6.

Having said that, you ought to be able to use your own preferences, at your own risk.

If you could specify SAXParserFactory, TransformerFactory etc in docx4j.properties to match whatever you have in your application, would that work for you?

Out of interest, what does WebLogic use for the three factories?

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Fri Jun 08, 2012 5:27 am
by gaucho
Hi Jason,

Thank you very much for your answer!!!

Yes I think that your solution would work for me, but anyway I believe that I still would need to remove the System.setProperty from the docx4j, wouldn't I? The thing is that I should not modify the default JVM settings because over the same domain I have a bunch of applications.

Actually I think that your solution would be the same as specify the parser-factory in the application deployment descriptor:

Code: Select all
<parser-factory>
  <saxparser-factory>org.apache.xerces.jaxp.SAXParserFactoryImpl</saxparser-factory>
    <document-builder-factory>org.apache.xerces.jaxp.DocumentBuilderFactoryImpl</document-builder-factory>
    <transformer-factory>org.apache.xalan.processor.TransformerFactoryImpl</transformer-factory>
</parser-factory>


You can take a look in Configuring a Parser or Transformer for an Enterprise Application

Weblogic uses its default factories see ParsersIssues (thanks guys!!!):

Code: Select all
    SAXParserFactory: weblogic.xml.jaxp.RegistrySAXParserFactory
    SAXParser: weblogic.xml.jaxp.RegistrySAXParser
    DocumentBuilderFactory: weblogic.xml.jaxp.RegistryDocumentBuilderFactory
    DocumentBuilder: weblogic.xml.jaxp.RegistryDocumentBuilder
    TransformerFactory: weblogic.xml.jaxp.RegistrySAXTransformerFactory
    Xml-Apis version (if used): XmlCommonsExternal 1.3.04


Thanks again,

Luis

ps: anyway, this docx4j is a really nice implementation, thanks!

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Fri Jun 08, 2012 7:17 pm
by jason
Hi Luis

Thanks for your kind words.

Following recent commits - see https://github.com/plutext/docx4j/commi ... Utils.java
you should be able to do set what you need with SAXParserFactory and DocumentBuilderFactory in a docx4j.properties file: https://github.com/plutext/docx4j/blob/ ... properties

I've created a nightly for you to try at http://www.docx4java.org/docx4j/docx4j- ... 120608.jar

cheers .. Jason

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Fri Jun 08, 2012 11:34 pm
by gaucho
Hi Jason,

Thank you very much! I am going to test your build.

In the meantime I have built my own (docx4j-2.8.0-SNAPSHOT.jar), removing the System.SetProperty(...) invocations. I have created a simple sample web application (adding Xalan & Xerces) and It seems that it works! I mean:

    The sample application transforms the docx in html correctly. If I ask it for the parsers that it is using, it replies me with the Xalan/Xerces versions that are in its CLASSPATH
    I request to another application in the same managed server, and it replies me with the Weblogic default parsers.

Thank you very much.

Best regards,

Luis

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Sun Jun 17, 2012 10:45 pm
by Ivan
If the javax.xml.transform.TransformerFactory has not been set, then the altered code will still change the system property.

The current code does this:

Code: Select all
      javax.xml.transform.TransformerFactory tmpfactory = javax.xml.transform.TransformerFactory.newInstance();         
      TRANSFORMER_FACTORY_ORIGINAL = tmpfactory.getClass().getName();


Would it be better to fetch System.getProperty("javax.xml.transform.TransformerFactory") into the TRANSFORMER_FACTORY_ORIGINAL variable and set this value back?

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Sun Jun 17, 2012 11:15 pm
by Ivan
this seems to do the trick:

Code: Select all
   private static void instantiateTransformerFactory() {
      // docx4j requires real Xalan
      // See further docs/JAXP_TransformerFactory_XSLT_notes.txt
        String originalSystemProperty = System.getProperty("javax.xml.transform.TransformerFactory");

      javax.xml.transform.TransformerFactory tmpfactory = javax.xml.transform.TransformerFactory.newInstance();
      TRANSFORMER_FACTORY_ORIGINAL = tmpfactory.getClass().getName();
      log.debug("Set TRANSFORMER_FACTORY_ORIGINAL to " + TRANSFORMER_FACTORY_ORIGINAL);
      
      try {
         System.setProperty("javax.xml.transform.TransformerFactory",
               TRANSFORMER_FACTORY_PROCESSOR_XALAN);

         transformerFactory = javax.xml.transform.TransformerFactory
               .newInstance();
         // We've got our factory now, so set it back again!
            if (originalSystemProperty == null) {
                System.clearProperty("javax.xml.transform.TransformerFactory");
            } else {
             System.setProperty("javax.xml.transform.TransformerFactory",
                   TRANSFORMER_FACTORY_ORIGINAL);
            }
      } catch (javax.xml.transform.TransformerFactoryConfigurationError e) {
         
         // Provider org.apache.xalan.processor.TransformerFactoryImpl not found
         log.error("Warning: Xalan jar missing from classpath; xslt not supported",e);
         
         // but try anyway
            if (originalSystemProperty == null) {
                System.clearProperty("javax.xml.transform.TransformerFactory");
            } else {
                System.setProperty("javax.xml.transform.TransformerFactory",
               TRANSFORMER_FACTORY_ORIGINAL);
            }

         transformerFactory = javax.xml.transform.TransformerFactory
         .newInstance();
      }
      
      LoggingErrorListener errorListener = new LoggingErrorListener(false);
      transformerFactory.setErrorListener(errorListener);
   }

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Mon Jun 18, 2012 10:37 pm
by gaucho
Hi Ivan,

Looks good! Thank you very much!

Best regards,

Luis

ps: do you think that this could be use as a "remedy" for fixing the application server? I mean, imagine that the application A modifies the sax-parser. It would be great if I could "reset" the original property from the application B

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Wed Jun 20, 2012 8:39 am
by gaucho
Hi Ivan,

I have tested in a simple dev environment (one weblogic with only the admin server) and it does the trick, thanks!

I will test it in prepro and let you know...

Thank you very much and best regards,

Luis

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Thu Jun 21, 2012 11:13 pm
by jason

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Thu Jun 21, 2012 11:49 pm
by Ivan
Great!

Looking forward to the next release. I have temporarily forked the current snapshot to be able to try out docX4J, which seems like a great tool!

Re: Weblogic javax.xml.transform.TransformerFactory issue

PostPosted: Sat Jun 30, 2012 6:04 pm
by aaymerich
Hi,

as docx4j "requires real Xalan", insteadof setting system property, call javax.xml.transform.TransformerFactory.newInstance() and then back system property to original value, maybe it would be better to do an implicit instantiation of xalan transformer factory:

Code: Select all
tfactory = new org.apache.xalan.processor.TransformerFactoryImpl();


Yes, this makes a dependency with Xalan package... but docx4j needs it!

This change is working on a real production system with Weblogic 10.3.2, where we had this issue.

Regards
albert
PS:apologize for not sharing this earlier