Tracking down a NoSuchMethodError

Caused by: java.lang.NoSuchMethodError: org.apache.xml.serializer.Encodings.isRecognizedEncoding(Ljava/lang/String;)Z
        at org.apache.xml.serializer.dom3.LSSerializerImpl.write(LSSerializerImpl.java:926)
        at ...

If you’ved ever had the unpleasant task of figuring out which of the 200+ JAR dependencies in your project that are causing the a NoSuchMethodError (usually in some XML or webservice code), then this is the trick for you:

Consider the following POM (distilled from a real-world scenario):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>net.bystrup</groupId>
    <artifactId>nsm-example</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>xalan</groupId>
            <artifactId>xalan</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>xalan</groupId>
            <artifactId>serializer</artifactId>
            <version>2.7.1</version>
        </dependency>
    </dependencies>
</project>

When parsing an XML document, the error at the top of the post might occur… You know the symptom, you know the probable root cause – but how do you find the conflicting JARs?

ClassLoader.getResources() to the rescue! The following snippet will list all resources/JARs containing the clas with the missing method:

import java.net.URL;
import java.util.Enumeration;

public class Main
{
    /**
     * The project depends on both xalan:2.7.0 and serializer:2.7.1 which both
     * contain the org.apache.xml.serializer.Encodings class, albeit with different
     * signatures...
     *
     * @param argv
     */
    public static void main( String argv[] ) throws Exception
    {
        Enumeration<URL> res = new Main().getClass().getClassLoader().getResources( "org/apache/xml/serializer/Encodings.class" );
        while ( res.hasMoreElements() )
        {
            URL url = res.nextElement();
            System.out.println( url.toExternalForm() );
        }
    }
}

The operative piece of code

this.getClass().getClassLoader().getResources( "org/apache/xml/serializer/Encodings.class" )

might even be evaluated in eg. IDEAs “Evaluate Expression” window (Alt-F8) if you’re in a debugging situation.

The only problem remaining is: How does one remember where to find this guide next time the problem occurs… 🙂

This entry was posted in Coding, Java. Bookmark the permalink.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.