Using custom gradle plugin, cant find class?


(Ryan Larson) #1

I am trying to write a custom gradle plugin that provides ssh/scp functionality by wrapping the AntBuilder.sshexec and AntBuilder.scp in gradle tasks since we use them in many different builds and its a pain to redefine the ant task in every build.

Everything seems to be working as far as applying the plugin and that structure, but when I try to invoke AntBuilder, I get an exception that the extra ant classes (ant-jsch) are not found. It’s like the classloaders are seperate and none of the transitive dependencies are getting picked up by the buildscript. I even built the custom plugin as a fatjar so the classes would have to be on the classpath, but got the same error.

apply plugin: 'base'
apply plugin: edu.pdx.cs.rylarson.RemotePlugin
  buildscript {
    repositories {
        mavenLocal()
    }
    dependencies {
        classpath group: 'co.ryanlarson', name: 'gradle-remote', version: '+'
    }
}
  task testSsh(type: edu.pdx.cs.rylarson.ssh.SshTask) {
    host = "hostname"
    user = "root"
    password = "toor"
    trust = true
    command = "uname"
}

I get the following error when I try to run the testSssh task:

* What went wrong:
Execution failed for task ':testSsh'.
> Problem: failed to create task or type sshexec
  Cause: the class org.apache.tools.ant.taskdefs.optional.ssh.SSHExec was not fo
und.
          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
    * Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug
option to get more log output.

This is the build for the plugin itself, the POM has the transitive dependencies:

apply plugin: 'groovy'
apply plugin: 'idea'
apply plugin: 'maven'
  group = 'co.ryanlarson'
version = '0.1.0'
  repositories {
    mavenCentral()
}
  dependencies {
    compile gradleApi()
    compile localGroovy()
    runtime 'org.apache.ant:ant-jsch:+'
    runtime 'com.jcraft:jsch:+'
}
  task wrapper(type: Wrapper) {
    gradleVersion = '1.6'
}
  task sourcesJar(type: Jar) {
    from sourceSets.main
    classifier = 'sources'
}
  //jar {
//
  doFirst {
//
      from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } }
//
  }
//
  exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
//}
  artifacts {
    archives jar
    archives sourcesJar
}

I have commented out the jar closure but that is what I used to build the fat jar with the same results.


(Peter Niederwieser) #2

You’d have to show your plugin code. gradle-ssh-plugin might be an alternative. Worked well for me.


(Ryan Larson) #3

Hey Peter. I have used the plugin in the past but the way remote hosts are defined feels weird to me, and we hope to extend this to handle ssh, psexec, scp, and multiple ssh commands executed in a session.

The plugin is extremely simple:

class RemotePlugin implements Plugin<Project> {
      @Override
    void apply(Project project) {
        project.task('scp', type: ScpTask)
    }
}

and the task:

class SshTask extends DefaultTask {
      def host
    def username, password
    def command
    def trust = false
    def port = 22
    def output
    def append = true
    def timeout = 0
    def verbose = false
    def usepty = false
    def suppresssystemout = false
      @TaskAction
    def sshTask(){
        AntBuilder ant = new AntBuilder()
        ant.sshexec(
                host:host,
                username:username,
                command:command,
                trust:trust,
                port:port,
                password:password,
                output:output,
                append:append,
                timeout:timeout,
                verbose:verbose,
                usepty:usepty,
                suppresssystemout:suppresssystemout
        )
    }
}

(Peter Niederwieser) #4

You should probably use ‘project.ant’. And more importantly, you’ll have to typedef the Ant task.


(Ryan Larson) #5

I know that is an option, but I am curious as to why the jars dont make it on the classpath of the test buildscript.


(Peter Niederwieser) #6

They probably made it on the build script class path. But without a taskdef or typedef, they won’t make it on the Ant class path.


(Jason Conway-Williams) #7

Has any one found a solution to this? I am also crating a custom plugin for internal use in our company to scp files to a server. I get the same error.


(Luke Daley) #8

As Peter points out, you need to use a taskdef or typedef to make the classes available to Ant.