Wednesday, April 28, 2010

Fighting java.lang.NoClassDefFoundError: org/cyberneko/html/parsers/SAXParser on Grails-1.2.1

This was a problem that occured while using HttpBuilder for making HTTP requests.

1. When I say httpBuilder.request(GET, HTML){}, it throws
java.lang.NoClassDefFoundError: org/cyberneko/html/parsers/SAXParser


ParserRegistry source:

public GPathResult parseHTML( HttpResponse resp ) throws IOException, SAXException {
return new XmlSlurper( new org.cyberneko.html.parsers.SAXParser() )
.parse( parseText( resp ) );

My BuildConfig contained:

build ('org.codehaus.groovy:http-builder:0.5.0-SNAPSHOT'){
excludes "junit", "xml-apis", "xercesImpl"

Diagnosis: The class "org/cyberneko/html/parsers/SAXParser" belongs to nekohtml.jar. HttpBuilder has a dependency on nekohtml.jar. This dependency gets resolved in the Grails dependency resolution step. However I still get the above exception. Stupid class loading issue.

2. So added to my BuildConfig:
 runtime ('net.sourceforge.nekohtml:nekohtml:1.9.9'){
This lead to:

Error executing script RunApp: loader constraint violation: when resolving overridden method "org.apache.xerces.jaxp.SAXParserImpl.getParser()Lorg/xml/sax/Parser;" the class loader (instance of org/codehaus/groovy/grails/cli/support/GrailsRootLoader) of the current class, org/apache/xerces/jaxp/SAXParserImpl, and its superclass loader (instance of ), have different Class objects for the type org/xml/sax/Parser used in the signature

        at org.apache.xerces.jaxp.SAXParserFactoryImpl.newSAXParser(Unknown Sour

Diagnosis: It seems that nekohtml has a dependency on xercesImpl that in turn has a dependency on xml-apis.jar that contains the class org/xml/sax/Parser. However this class had already been loaded by some parent class loader from somewhere else.

3. So I modified my BuildConfig:
runtime ('xerces:xercesImpl:2.8.1'){
excludes "xml-apis"
 runtime ('net.sourceforge.nekohtml:nekohtml:1.9.9'){
excludes "xercesImpl"