Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy with Grape and AntBuilder classloader problem

I wanted to use groovy for a little ftp script and found this post http://www.hhhhq.org/blog/2009/05/01/ftp-using-groovy-and-ant/ Since there were several dependencies I wanted to use Grape. All dependencies are resolved and present in the cache. But I can't get Ant to find the optional tasks in the other libs. It always says

Caught: : Problem: failed to create task or type ftp
Cause: the class org.apache.tools.ant.taskdefs.optional.net.FTP was not found.
        This looks like one of Ant's optional components.
Action: Check that the appropriate optional JAR exists in
        -ANT_HOME\lib
        -the IDE Ant configuration dialogs

Do not panic, this is a common problem.
The commonest cause is a missing JAR.

This is not a bug; it is a configuration problem

        at GrabTest.runMe(GrabTest.groovy:15)
        at GrabTest.run(GrabTest.groovy:26)

Groovy Version: 1.6.5 JVM: 1.6.0_15

Here is my source code

@Grab(group='ant', module='ant', version='[1.6.5,)')
@Grab(group='ant', module='ant-nodeps', version='[1.0,)')
@Grab(group='ant', module='ant-apache-oro', version='[1.0,)') 
@Grab(group='ant', module='ant-commons-net', version='[1.0,)') 
@Grab(group='apache-oro', module='jakarta-oro', version='[2.0.8,)')
@Grab(group='commons-net', module='commons-net', version='[1.4,)')
def runMe() {
    // works
    println getClass().getClassLoader().loadClass("org.apache.tools.ant.taskdefs.optional.net.FTP")

    def ant = new AntBuilder()

    println getClass().getClassLoader() //groovy.lang.GroovyClassLoader$InnerLoader
    println ant.getClass().getClassLoader() //org.codehaus.groovy.tools.RootLoader
    ant.ftp( server:"ftp.foo.com",
            userid:"user",
            password:"passwd",
            passive:"yes",
            verbose:"yes",
            remotedir:"/pub/incoming",
            binary:"yes" ) {
                fileset( dir:"." ) { include( name:"**/*.gz" ) }
            }
}

runMe()

As you can see I suspect the classloader of being the problem, it seems that Grape doesn't inject the dependencies there. Any idea of how I can get it to work?

like image 216
Leonard Brünings Avatar asked Oct 29 '09 01:10

Leonard Brünings


1 Answers

You're right suspecting the classloader to be the root of the problem. As your code already reveals, the AntBuilder is loaded from the RootLoader, that doesn't have access to the classes loaded by the @Grab annotation. As GROOVY-3730 shows, Groovy 1.7 is going to address this problem.

However, you can solve your problem by directly using the groovy.grape.Grape.grab(Map dependency) method, in which you can set a specific classloader that should be used to load the dependencies:

import groovy.grape.Grape;

Grape.grab(group:'ant', module:'ant', version:'1.6.5', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group:'ant', module:'ant-nodeps', version:'1.6.5', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group:'ant', module:'ant-apache-oro', version:'1.6.5', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group:'ant', module:'ant-commons-net', version:'1.6.5', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group:'commons-net', module:'commons-net', version:'1.4.1', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group:'oro', module:'oro', version:'2.0.8', classLoader:this.class.classLoader.rootLoader)
like image 84
Christoph Metzendorf Avatar answered Nov 10 '22 23:11

Christoph Metzendorf