0 Replies Latest reply on Jul 7, 2014 6:46 AM by JOC

    Overriding DocumentBuilderFactory

    JOC Newbie

      Back in JBoss 4.3 , we had a global replacement for the standard DocumentBuilderFactory which used System.setProperty("javax.xml.parsers.DocumentBuilderFactory", replacementFactory)   to set a substitute factory.

      The new factory was packaged in a jar file and placed in the server/default/lib folder, and a startup servlet called it to set the property mentioned above.

       

      From the changes tracker I can see that this was added after a pen test pointed out potential problems with our webservices.  I know on JBoss7 for webservices there is no need to do this as it is done for us, but I have a feeling this was also put in place as a catch all to ensure that the default factory disabled entity expansion and enabled secure processing to protect against 3rd party libraries (of which we use a lot)  that might inadvertently expose the same problems elsewhere.

       

      I'm not the first to look at this, a previous developer moved us from JBoss4 to JBoss7.1.2  What he did was take the code for the jar file from the old version, packaged it as a custom module, put it in the JBoss modules folder and added it as a dependency to the ear's manifest.jar. The same method is used to register is - a startup servlet creates an instance of the factory class causing it to register itself.

      I believe it was working there as I did some work on the webservices on JBoss7.1.2 , but now we have moved to EAP 6 - alpha3 we are seeing some problems.

       

      Code from the startup servlet -

       

      ClassLoader classLoader = this.getClass().getClassLoader();
      Class<?> aClass = Class.forName(BISConstants.BIS_DOCUMENT_BUILDER_FACTORY_CLASS, false, classLoader);
      aClass.newInstance();
      

       

      A static initializer block in the replacement factory class sets it up and sets the property.

       

        static
        {
          DocumentBuilderFactory originalDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
          Class factoryClass = originalDocumentBuilderFactory.getClass();
          String factoryClassCanonicalName = factoryClass.getCanonicalName();
          ClassLoader factoryClassLoader = factoryClass.getClassLoader();
          originalFactoryClassName = factoryClassCanonicalName;
          originalClassLoader = factoryClassLoader;
          String customDocBuilder = BISDocumentBuilderFactory.class.getCanonicalName();
          System.setProperty("javax.xml.parsers.DocumentBuilderFactory", customDocBuilder);
        }
      

       

       

      When webservices try to do a "DocumentFactory.getInstance()" - we get a class not found exception with the name of our factory, so presumably the step above is working correctly - but the webservices classloader cannot see the new class?

       

      15:06:33,009 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/WebApp].[LogonServiceV1]] (http-/172.16.50.120:8080-1) JBWEB000236: Servlet.service() for servlet LogonServiceV1 threw exception: java.lang.ClassNotFoundException: com/bis/commonclasses/security/BISDocumentBuilderFactory
        at java.lang.Class.forName0(Native Method) [rt.jar:1.7.0_25]
        at java.lang.Class.forName(Class.java:270) [rt.jar:1.7.0_25]
        at javax.xml.parsers.FactoryFinder.getProviderClass(FactoryFinder.java:123) [rt.jar:1.7.0_25]
        at javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:178) [rt.jar:1.7.0_25]
        at javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:147) [rt.jar:1.7.0_25]
        at javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:219) [rt.jar:1.7.0_25]
        at javax.xml.parsers.DocumentBuilderFactory.newInstance(DocumentBuilderFactory.java:121) [rt.jar:1.7.0_25]
        at org.jboss.ws.common.DOMUtils.<clinit>(DOMUtils.java:88)
        at org.jboss.ws.core.server.WSDLRequestHandler.getDocumentForPath(WSDLRequestHandler.java:114)
      

       

      In the standalone.xml we have the following settings - not sure if this is relevant at all though.

       

              <subsystem xmlns="urn:jboss:domain:ee:1.2">
                  <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
                  <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
                  <jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
                  <annotation-property-replacement>false</annotation-property-replacement>
              </subsystem>
      

       

       

      Annoyingly, it does seem to work sometimes.

      I have also had 2 different errors from different servers - one was even giving me a class not found error for org.jboss.ws.common.DOMUtils

      In the cases it does appear to be working I'm not totally sure that its just not having the property set in those cases and so avoiding the problem altogether - I have yet to prove this theory though.

       

      Is there something obvious I'm missing here, or better still, is there a better / preferred way to do this that I haven't stumbled across yet.