Adding libraries into Ant classpath only

(Eero Helenius) #1

I’m the maintainer of a Gradle plugin for a documentation tool called DITA Open Toolkit.

I originally wrote the plugin when I discovered that the Gradle daemon decreases DITA-OT build times dramatically because of its ability to reuse JVM instances, but Gradle has a whole bunch of features that are very well-suited for a tool like DITA-OT.

The way to run DITA-OT is to basically run to put its dependencies into the classpath and run Ant, so what I do in my plugin is to add the DITA-OT dependencies into the Ant class loader like this:

jars.each {

This worked fine until DITA-OT added Guava into its list of dependencies. Ever since, builds that use my plugin keep failing with errors like this one:

Could not create service of type FileSnapshotter using TaskExecutionServices.createFileSnapshotter().
>$SimpleStatsCounter cannot be cast to$StatsCounter

(There’s a number of different Guava-related errors that can pop up.)

Presumably the reason is that Gradle depends on a different version of Guava than DITA-OT and the classloader picks the version at random and hands it to Gradle.

You can reproduce the issue with a Gradle buildfile like this (the Gradle daemon needs to be enabled):

defaultTasks 'x'

task x  {
    def url = ''
    def file = new File('guava-19.0.jar')

    if (!file.exists()) {
        def stream = file.newOutputStream()
        stream << new URL(url).openStream()

    // Comment this line and the build will succeed.

Is there any way around this issue? I could fork the JVM for DITA-OT, of course, but that’ll mean losing the performance benefit, which can be up to 170%, so I’d like to avoid that if possible.

(Lari Hotari) #2

I replied to this in the thread Guava classpath conflict and the Gradle daemon . Using the internal IsolatedAntBuilder seems to be the way to add libraries to Ant classpath only.