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