'Gradle can not compile the code with the generated sources by annotationProcessor
How to make the gradle build/compile a project using generated source by annotationProcessor?
I have a project with 2 modules
app-annotation -> is a module that defines one annotation and a successor of the AbstractProcessor
app-api -> contains Entities with annotation from the previous module
The idea was to generate default CRUD Repositories and Services for each entity, also if it is needed have the possibility to extend some service.
The problem is, it generates all the needed java files (even Intellij Idea see those files) but as soon as I want to extend one of the services it fails while it is being compiled because as I understand at the moment of compiling my class there is not its superclass which is generated after. If I do then recompile only my class then it is ok Moreover, eclipse somehow compiles with no error at all, only when I build with Idea or gradlew build.
To fix it the solution below is used, but it looks not very nice
configurations {
preProcessAnnotation
}
def defaultSrcDir = "$projectDir/src/main/java"
def entitySources = "$projectDir/src/main/java/com/abcd/app/entity"
def generatedSources = "$buildDir/generated/sources/annotationProcessor/java/main"
def generatedOutputDir = file("$generatedSources")
// Explicitly run the annotation processor against the entities
task preProcessAnnotation (type: JavaCompile) {
source = entitySources
classpath = sourceSets.main.compileClasspath
destinationDirectory = generatedOutputDir
options.sourcepath = sourceSets.main.java.getSourceDirectories()
options.annotationProcessorPath = configurations.getByName("preProcessAnnotation")
options.compilerArgs << "-proc:only"
options.encoding = "ISO-8859-1"
}
// Explicitly specify the files to compile
compileJava {
dependsOn(clean)
dependsOn(preProcessAnnotation)
def files = []
fileTree(defaultSrcDir).visit { FileVisitDetails details ->
files << details.file.path
}
fileTree(generatedSources).visit { FileVisitDetails details ->
files << details.file.path
}
source = files
options.compilerArgs << "-Xlint:deprecation"
options.compilerArgs << "-Xlint:unchecked"
options.encoding = "ISO-8859-1"
}
....
dependencies {
preProcessAnnotation project(':app-annotation')
// Generate the crud repositories and services
compile project(':app-annotation')
implementation project(':app-annotation')
...
}
I am just curious how similar frameworks of code generation such as Lombok, Dagger2 work without any problem.
PS. I feel it should be much simpler, doesn't it?
Solution 1:[1]
Eventually, all it is my mistake, I used wrong method to save a generated java file.
// Wrong!
javax.annotation.processing.Filer#createResource(StandardLocation.SOURCE_OUTPUT, packageName, className + ".java")
// Correct
javax.annotation.processing.Filer#createSourceFile(packageName + "." + className)
Solution 2:[2]
As you realised - any code generation must be done before compile.
A cleaner approach is to have your code generation logic / annotation as dependency.
task codeGen {
// creates under build/genSrc
}
//add to default source set
sourceSets.main.java.srcDir "build/genSrc"
//this has access to all code
compile.dependsOn codeGen
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | PrasadU |