Custom WSImport Task issues

I have created a custom wsimport task that successfully manages to control the up-to-date nature of the WSDL and schemas, but it feels like I am cheating to properly integrate the generated output of wsimport.

By default, I am outputting the class files to ‘project.sourceSets.main.output.classesDir’, which works appropriately enough, but I am not a fan of reusing the ‘main’ source set for generated code output.

As such, I created a ‘generated’ source set:

sourceSets {
    generated {
        // is this too specific?
        java.srcDirs = ["$buildDir/generated/java"]
    }
}

However, from there I am at a loss in the best practice to join the ‘generated’ source set back with the main code. Currently, I use the ‘compileGeneratedJava’ task, but it feels wrong, as I use it to manually add the source files (not classes even) to the main java source set, which seems like it is brittle if some other task decides to do something similar:

compileGeneratedJava {
    dependsOn(processWsdl)
    // currently unnecessary
    // options.warnings = false
          // dump generated code into the global codebase
    compileJava.source files(processWsdl.srcDir), sourceSets.main.java
}

However, in doing that, it will no longer consider the WSDL up to date, even when it is, thereby kicking off ‘processWsdl’ for every build.

What’s the best way to get the generated output into a separate folder, but still keep it a part of the build? The optimal feeling answer would be:

build/generated/java // or any variation of the name, such as build/generated/src/main/java

build/generated/classes

build/classes

And then, something knows to merge the two classes dirs (generated first) without the task even having to be made aware that it’s not part of the main code–it just spits generated output into a directory that you tell it too. It would be magical if IDEs could also pickup the structure and work with it.

Your code mixes up a few things. Most importantly, it doesn’t help to create a new source set if all you want to do is generating source code (without also compiling it separately). Instead, just declare a new Java source directory for the ‘main’ source set, make sure that ‘processWsdl’ writes to that directory, and make ‘compileJava’ depend on ‘processWsdl’.

Forgot to add that I recommend to keep generated sources outside the source tree and make it so that ‘gradle clean’ deletes them. A directory under ‘buildDir’ is good except that it can cause problems in IDEs, which typically exclude the build dir. Hence I typically keep generated sources in ‘"$projectDir/generated-sources"’ and configure the ‘clean’ task accordingly (‘clean.delete generatedSourcesDir’).

Thanks Peter.

Is there any way to have the generated ‘.class’ files put directly with the others, yet still picked up by ‘compileJava’? Realistically, I only want the generated ‘.java’ code for the IDEs and the ‘.class’ files for the compiler.

Who generates the class files? I thought ‘processWsdl’ only creates source files.

I only do that because I do not know how to get Gradle to pick up the premade ‘.class’ files for ‘compileJava’, which means that I am effectively making it double-compiling them. I was plugging them into ‘project.sourceSets.main.output.classesDir’ as the target of ‘wsimport’, but I can steer them anywhere.

Can’t you leave compilation to Gradle?

That’s a good point. I guess that I had been so used to taking the class output from ‘wsimport’ via ant that I did not even stop to think about doing it differently.

I’ll give that a shot tomorrow and post my results. Thanks for the idea.