문제

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

도움이 되었습니까?

해결책

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).

다른 팁

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)       
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top