Apr 16, 2013

java.lang.AbstractMethodError: org.apache.xerces.dom.DeferredElementImpl.getTextContent()

org.w3c.dom.Node is an interface. org.apache.xerces.dom.DeferredElementImpl is an implementation of that interface. It seems that DeferredElementImpl does not implement getTextContent() properly. There are a lot of other implementations. If you write a program that uses DocumentBuilderFactory, then when you run it, you will actually be using one of the implementations.
You can choose between:
  • "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"  Is the standard implementation bundled in the Sun JRE.
  • "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl" The non-standard XML parser. Specified in a library on your classpath. That is perfectly fine, but it's something you should be aware of.
The method javax.xml.parsers.DocumentBuilderFactory#newInstance() uses the following ordered lookup procedure to determine the implementation class to load:. See Javadoc for details
  1. Use the javax.xml.parsers.DocumentBuilderFactory system property.
  2. Use the properties file "lib/jaxp.properties" in the JRE directory.
  3. Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for a classname in the file META-INF/services/javax.xml.parsers.DocumentBuilderFactory in jars available to the runtime.
  4. Platform default DocumentBuilderFactory instance.
Setting the jaxp.debug system property will cause this method to print a lot of debug messages to System.err
java -Djaxp.debug=1 YourProgram ....  or java -Djaxp.debug=true YourProgram ....
The method javax.xml.parsers.DocumentBuilderFactory#newInstance(String factoryClassName, ClassLoader classLoader) specifies the implementation class to load
How to find the JAXP implementations been used
private static void OutputJaxpImplementationInfo() {
   System.out.println(getJaxpImplementationInfo("DocumentBuilderFactory", DocumentBuilderFactory.newInstance().getClass()));
   System.out.println(getJaxpImplementationInfo("XPathFactory", XPathFactory.newInstance().getClass()));
   System.out.println(getJaxpImplementationInfo("TransformerFactory", TransformerFactory.newInstance().getClass()));
   System.out.println(getJaxpImplementationInfo("SAXParserFactory", SAXParserFactory.newInstance().getClass()));
   System.out.println(getJaxpImplementationInfo("SchemaFactory", SchemaFactory.newInstance().getClass()));
}
private static String getJaxpImplementationInfo(String componentName, Class componentClass) {
   CodeSource source = componentClass.getProtectionDomain().getCodeSource();
   return MessageFormat.format(
      "{0} implementation: {1} loaded from: {2}",
      componentName,
      componentClass.getName(),
      source == null ? "Java Runtime" : source.getLocation());
}
Possible Solutions
Update your JAXP jar implementation
  • Do a mvn dependency:tree and see if there are any xerces related jars that need to be removed or updated from an implied version  to declaring one that works
  • Google/Bing  the most recent verision of your jar library
Use the default implementation
  • Given the order used to determine the implementation to load, we can set System property javax.xml.parsers.DocumentBuilderFactory System.setProperty("javax.xml.parsers.DocumentBuilderFactory","com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
  • In command line add -Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
  • The best solution for me is passing a parameter to DocumentBuilderFactory to specify which parser to use: DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance("com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", null);
I hope you find this information useful‎, and if you have aditional information or questions you can leave a comment :)

5 comments:

  1. this post has save my life!
    very useful

    Thanks Xavier Figueroa!

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. I was trying to upgrade Jenkins from 1.642.4 to 2.7.4, and hit a similar AbstractMethodError. Your document help me understand the JAXP impl class loading order, and narrow down the issue to JRE. Thanks.

    hudson.util.HudsonFailedToLoad: java.lang.AbstractMethodError: javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V
    at hudson.WebAppMain$3.run(WebAppMain.java:241)
    Caused by: java.lang.AbstractMethodError: javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V
    at jenkins.util.xml.XMLUtils.setDocumentBuilderFactoryFeature(XMLUtils.java:235)
    at jenkins.util.xml.XMLUtils.newDocumentBuilderFactory(XMLUtils.java:226)
    at jenkins.util.xml.XMLUtils.parse(XMLUtils.java:117)
    at jenkins.util.xml.XMLUtils.parse(XMLUtils.java:144)
    at jenkins.util.xml.XMLUtils.getValue(XMLUtils.java:184)
    at jenkins.util.xml.XMLUtils.getValue(XMLUtils.java:168)
    at jenkins.install.InstallUtil.getLastExecVersion(InstallUtil.java:247)
    at jenkins.install.InstallUtil.getDefaultInstallState(InstallUtil.java:165)
    at jenkins.install.InstallUtil.access$000(InstallUtil.java:66)
    at jenkins.install.InstallUtil$2.apply(InstallUtil.java:118)
    at jenkins.install.InstallUtil$2.apply(InstallUtil.java:112)
    at jenkins.install.InstallUtil$ProviderChain.get(InstallUtil.java:83)
    at jenkins.install.UpgradeWizard$ListenForInstallComplete.getNextInstallState(UpgradeWizard.java:155)
    at jenkins.install.InstallUtil$1.apply(InstallUtil.java:107)
    at jenkins.install.InstallUtil$1.apply(InstallUtil.java:104)
    at jenkins.install.InstallUtil$ProviderChain.get(InstallUtil.java:83)
    at jenkins.install.InstallUtil.getNextInstallState(InstallUtil.java:135)
    at jenkins.install.InstallUtil.proceedToNextStateFrom(InstallUtil.java:91)
    at jenkins.model.Jenkins.(Jenkins.java:887)
    at hudson.model.Hudson.(Hudson.java:85)
    at hudson.model.Hudson.(Hudson.java:81)
    at hudson.WebAppMain$3.run(WebAppMain.java:227)

    ReplyDelete
  4. I just download the LTS jenkins.war and put into my Tomcat 8, and then got the same issue.
    Have to say thank you and this solution solved my problem.
    In command line add -Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl

    ReplyDelete
  5. Thank you for this post! I had to use the axis library for code generation from a wsdl file and notice these errors. Your article made it a quick fix to correct the issue. Very thorough, thanks again

    ReplyDelete