Question

I am new to gradle and trying to migrate our currently Maven based automated JAX-WS client building project, as gradle seems to provide an easier way for us to configure the builds for new projects.

I followed this tutorial here and was able to generate the client classes for a WSDL endpoint. What I want to achieve now is to put the Task definition in a new DefaultTask class to keep the build.gradle file cleaner, so I created the following file, put it in a new Groovy project and made it available to my build:

class WsimportTask extends DefaultTask {
    def List<String> wsdlUrls
    @OutputDirectory
    File destDir

    @TaskAction
    def wsimport() {
        wsdlUrls.each() {
            println "run wsimport for "+ it
            ant {
                sourceSets.main.output.classesDir.mkdirs()  
                destDir.mkdirs()
                taskdef(name:'wsimport',
                    classname:'com.sun.tools.ws.ant.WsImport',
                    classpath:configurations.jaxws.asPath)
                wsimport(keep:true,
                    destdir: sourceSets.main.output.classesDir,
                    sourcedestdir: destDir,
                    wsdl: it)
            }
        }
    }
}

As I want to come up with one single project that contains a subproject for each web service client that we have, I altered the build.gradle file of the main project and added:

main build.gradle

subprojects {
    configurations {
        wsimport
    }
    dependencies {
        wsimport group: 'com.mycompany.gradle', name: 'tasks', version: '0.0.2-SNAPSHOT'
    }
    task wsimport(type: com.mycompany.gradle.WsimportTask) {
        destDir = file("${buildDir}/generated")
    }
    compileJava.dependsOn(wsimport)
}

The subprojects itself should then only need to contain the following configuration:

subproject build.gradle

buildscript {
    wsimport {
        wsdlUrls = [
            "http://...endpoint1.wsdl",
            "http://...endpoint2.wsdl"
        ]
    }
}

On running gradle clean build on the main project, I get the following messages and Exception:

:clean UP-TO-DATE 
:Subproject:clean 
:Subproject:wsimport 
run wsimportfor http://endpoint1.wsdl 
:Subproject:wsimport 
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':Subproject:wsimport'.
....
FAILED Caused by: org.gradle.api.internal.MissingMethodException: Could not find method ant() for arguments [com.mycompany.gradle.WsimportTask$_wsimport_closure1_closure2@16caac05] on task ':Subproject:wsimport'.

So gradle understands my configuration, applies the WSDL endpoint and calls my custom task. Then ant {} is evaluated to a local method call the method ant(), which doesn't exist. This makes perfect sense to me, but how can I achieve my goal of calling the actual ant wsimport task from within this custom gradle task?


Solution Thanks Peter for your answer. I think i do start to understand how the Task is getting wired into my build script. I paste the complete Task for future strugglers, as I don't think the whole process of creating such a task (especially the first time) is somewhat inscrutable:

class WsimportTask extends DefaultTask {
    def List<String> wsdlUrls
    @OutputDirectory
    File outDir

    @TaskAction
    def wsimport() {
        wsdlUrls.each() {
            def temp = it
            println "run wsimport for "+ temp
            project.sourceSets.main.output.classesDir.mkdirs()  
            outDir.mkdirs()
            def classpath = project.configurations.jaxws.asPath
            def destDir = project.sourceSets.main.output.classesDir
            project.ant {
                taskdef(name:'wsimport',
                    classname:'com.sun.tools.ws.ant.WsImport',
                    classpath:classpath)
                wsimport(keep:true,
                    destdir: destDir,
                    sourcedestdir: outDir,
                    wsdl: temp)
            }
        }
    }
}

Also notable is the fact that the task must not be defined within the buildscipt block of the build.gradle file, like Peter pointed out

Was it helpful?

Solution

Unlike a build script, a task or plugin class has no implicit Project context. Hence, it's project.ant, project.file, etc. Also, tasks have to be declared and configured outside the buildscript block (see subproject build.gradle).

OTHER TIPS

Try this:


@TaskAction
def wsimport() {
    wsdlUrls.each() {
        println "run wsimport for "+ it

        sourceSets.main.output.classesDir.mkdirs()  
        destDir.mkdirs()

        ant.taskdef(name:'wsimport',
                classname:'com.sun.tools.ws.ant.WsImport',
                classpath:configurations.jaxws.asPath)
        ant.wsimport(keep:true,
                destdir: sourceSets.main.output.classesDir,
                sourcedestdir: destDir,
                wsdl: it)       
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top