If you are trying to run Grails application you are developing and have an exception that says something on the order of: BeanCreationException: Error creating bean with name 'fooService': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: net/sf/cglib/core/DebuggingClassWriter (where fooService is obviously a placeholder for a service from your application, or even from a plugin that your application uses), then odds are you have a JAR-file conflict. But simply knowing that you have a JAR-file conflict isn’t enough, the important part is resolving the issue of course, and in this blog post we’ll talk about the issue we were having the other day and ways to fix it.

In our case, the JAR-conflict was caused by the use of XWiki Rendering Plugin in our Grails 2.2.3 application (although it also might happen if you simply use the XWiki Rendering Framework itself, without the Grails plugin). It will only happen though if you install the JAR that supports Markdown syntax — of all the rendering syntaxes supported by the framework, only Markdown (indirectly) relies on the ASM library. The bad thing about this is that Grails also relies on ASM library (more specifically, cglib framework relies on ASM, hence the message of the original exception mentions a class from cglib). Why is this bad? Well, the fact that Grails and XWiki both rely on ASM is not bad at all by itself. What is really bad about it is that they both rely on completely different, incompatible versions of the same library. So when the application is being run, both JARs are included into classpath, and that really confuses cglib (XWiki renderer works fine though).

Before I list the possible solutions to the problem, let me be specific here and clarify that cglib-2.2 requires asm-3.1, while parboiled-java-1.1.4 used by XWiki’s Markdown syntax parser relies on asm-4.1. Ivy does not resolve this version conflict because these versions use different groupIds — namely asm and org.ow2.asm respectively. So for Ivy these look like two different libraries, not two versions of the same library; and because these versions are incompatible (neither forwards, nor backwards), essentially they are two different libraries, with only minor remark about the fact they both use the same namespaces and some of the classes are similarly-named (so poor judgment on developers' part perhaps).

If this happens to you, from here you have three options.

Option One

Do not use Markdown syntax and therefore, omit the requirement for Markdown support by XWiki Renderer. This is by far the simplest option (and, arguably, the best one).

If however, you absolutely need support for Markdown syntax in your application, you’re bound to using one of the other two options described below. All of them have their own drawbacks.

Option Two

Downgrade to the version of parboiled that relies on asm library before version 4.0. Here is an example of how that can be done (edit the dependencies section of your BuildConfig.groovy file to look something like this):


    dependencies {
        compile("org.xwiki.rendering:xwiki-rendering-syntax-markdown:5.0") {
            excludes "xercesImpl", "slf4j-api", "parboiled-java"
        }
        // WARNING! Any newer version depends on asm-4.x, which conflicts with asm-3.x used by cglib-2.2
        // If both asm JARs are included, any transactional services will fail to create!
        compile "org.parboiled:parboiled-java:1.0.2"

        // .... other dependencies of your application
    }

Here the JAR that supports Markdown syntax is included, while the transitive dependency on parboiled is excluded (parboiled library consists of two JARs — parboiled-core and parboiled-java; the latter depends on parboiled-core, so by excluding parboiled-java, you effectively exclude parboiled-core as well). Also, by excluding parboiled you exclude its dependency on asm-4.1. Exclusions of xercesImpl and slf4j-api are in no way related to the original ‘ASM-problem’ and are here because you normally should have them in a Grails app when you specify dependencies on any of the rendering syntax JARs.

The second dependency explicitly specifies parboiled library of version 1.0.2 (because Markdown syntax JAR needs parboiled after all, you cannot completely eliminate it from your classpath and expect Markdown support to work).

Version 1.0.2 of parboiled is the latest version that uses asm-3.x (asm-3.3.1 to be specific, so since cglib-2.2 relies on asm-3.1, this leads to the version of asm library being upgraded).

This option’s downsides are that you’ll have to stick with much older version of parboiled (which might have bugs fixed by later versions), as well as upgrading asm to 3.3.1 (which might produce some unexpected compatibility issues).

Option Three

Upgrade to the version of cglib that relies on asm library of version 4.0 or later. At the time of writing this blog post, there existed only one such version — cglib-3.0, which relies on asm-4.0, moreover — the asm should be of version 4.0 exactly, any later version will cause your application not to function still.

With this in mind, your BuildConfig.groovy file will look something like this:


// .... some generic build settings

grails.project.dependency.resolution = {
    // Include all of the global dependencies
    inherits("global") {
        excludes "asm" // but exclude (yes, completely) the asm one
    }

    repositories {
        // .... some repository configuration
    }

    dependencies {
        runtime "cglib:cglib:3.0" // this will effectively upgrade cglib to version 3.0

        compile("org.xwiki.rendering:xwiki-rendering-syntax-markdown:5.0") {
            excludes "xercesImpl", "slf4j-api"
        }

        // .... other dependencies of your application
    }

    plugins {
        // .... dependencies on the plugins your application is using
    }
}

As with the previous option, exclusions for xercesImpl and slf4j-api are ‘normal’ exclusions you should have every time you include one of syntax-supporting modules of XWiki Rendering Framework.

The important thing to remark here is that because asm library is globally excluded, you cannot specify it as a dependency (somewhere near runtime "cglib:cglib:3.0" line for instance). Well, you can, but that will have no effect — no asm.jar will be included, and apparently you do need it for cglib and parboiled. So the way to proceed in this case is to download asm-4.0.jar manually (here is one possible location to find it) and put that file into the lib/ folder of your application.

It is probably worth noting that with this simple configuration other ASM JARs (asm-analysis, asm-tree and asm-util) will be of version 4.1. If you do not like this mix of versions and prefer all of the ASM JARs to be of the same version (which has to be 4.0, remember?), then change xwiki-rendering-syntax-markdown dependency to something like this:


        compile("org.xwiki.rendering:xwiki-rendering-syntax-markdown:5.0") {
            excludes "xercesImpl", "slf4j-api", "asm", "asm-analysis", "asm-tree", "asm-util"
        }

i.e. add all of the ASM-excludes. And then have explicit dependencies for all of the missing JARs:


        compile "org.ow2.asm:asm-analysis:4.0"
        compile "org.ow2.asm:asm-tree:4.0"
        compile "org.ow2.asm:asm-util:4.0"

On the downside, this option leads to upgrading to later versions of asm and cglib, which might not be completely compatible with current version of Grails (at the time of writing this post, the latest version of Grails is 2.3.0 milestone 2, which depends on cglib-2.2.2 and asm-3.3.1), so use this option at your own risk. Additionally, you have to provide asm-4.0.jar by hand, effectively disabling version and dependency management for it from Maven and Ivy.

Shameless plug

We develop mobile and web apps, you can hire us to work on your next project.