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 :)