Integrating Spring Boot + QueryDSL into Gradle Build

I’m running a Spring Boot application and I’ve found the QueryDSL library very useful for simplifying the code for this project. There is a QueryDSL library that a developer can use in a project to generate the necessary files to leverage the QueryDSL library. The docs are not very good explaining how this works in Gradle, so I’ve had to piece together from other examples what works, but still haven’t gotten Spring Boot to play nicely with the QueryDSL gradle helper, so I’m reaching out here while I dig into the source code of

com.mysema.querydsl:querydsl-apt:3.6.3:jpa

to determine why it might be interfering with Spring Boot being able to run. The updates required in the build.gradle file to get the QueryDSL files generated are as follows

sourceSets {
    generated
}
sourceSets.generated.java.srcDirs = ['src/main/generated']
configurations {
    querydslapt
}
dependencies {
    // other deps ....
    compile "com.mysema.querydsl:querydsl-jpa:3.6.3"
    compile "com.mysema.querydsl:querydsl-apt:3.6.3:jpa"
}
compileJava {
    classpath = configurations.compile + configurations.querydslapt
    options.compilerArgs = [
            "-proc:only",
            "-processor", "com.mysema.query.apt.jpa.JPAAnnotationProcessor"
    ]
    destinationDir = sourceSets.generated.java.srcDirs.iterator().next()
}

However, this mixed with spring boot causes Spring boots gradle task :build to error with

* What went wrong:
Execution failed for task ':mytestproj:bootRepackage'.
> Unable to find main class

Then I add to the build.gradle

springBoot {
    mainClass = "com.awarepoint.networkconfig.Application"
}

This makes the build task happy, but I cannot get bootRun to run successfully with the above mix of settings, it fails with

:mytestproj:findMainClass
Error: Could not find or load main class com.awarepoint.networkconfig.Application

Has anyone run across this? Does anyone have deep enough knowledge to be able to see what I might be doing wrong for Spring Boot’s plugin to not be happy with the above gradle code?

Interesting, I’ve been working on this for a couple of hours I was able to swap out

compileJava {
    classpath = configurations.runtime + configurations.querydslapt
    options.compilerArgs = [
            "-proc:only",
            "-processor", "com.mysema.query.apt.jpa.JPAAnnotationProcessor"
    ]
    destinationDir = sourceSets.generated.java.srcDirs.iterator().next()
}

with

task generateQueryDSL(type: JavaCompile, group: 'build', description: 'Generates the QueryDSL query types') {
    source = sourceSets.main.java
    classpath = configurations.compile + configurations.querydslapt
    options.compilerArgs = [
            "-proc:only",
            "-processor", "com.mysema.query.apt.jpa.JPAAnnotationProcessor"
    ]
    destinationDir = sourceSets.generated.java.srcDirs.iterator().next()
}

compileJava {
    dependsOn generateQueryDSL
    source generateQueryDSL.destinationDir
}

compileGeneratedJava {
    dependsOn generateQueryDSL
    classpath += sourceSets.main.runtimeClasspath
}

Wish I knew a bit more about Gradle to know why these are different, if you’ve got an inkling, would love to hear it for my own edification. This fixed the problem I’m now able to build and bootRun my Spring Boot application

I have found a better way!

In dependencies do compile("com.mysema.querydsl:querydsl-apt:3.7.4:jpa") The “jpa” in the end ensures that JPAAnnotationProcessor is run (Ref SO Answer). For me by default gradle put the generated sources in “build” directory along with the classes in order to change that the javac provies a “-s” option which specifies the destination directory for generated sources (How cool is that? - Javac Docs)

So your build.gradle becomes (Taken from SOAnswer 1, SO Answer 2)

compile("com.mysema.querydsl:querydsl-apt:3.7.4:jpa") 

compileJava {
    options.compilerArgs << "-s"
    options.compilerArgs << "$projectDir/generated/java"

    doFirst {
        // make sure that directory exists
        file(new File(projectDir, "/generated/java")).mkdirs()
    }
}

clean.doLast {
    // clean-up directory when necessary
    file(new File(projectDir, "/generated")).deleteDir()
}

sourceSets {
    generated {
        java {
            srcDir "$projectDir/generated/java"
        }
    }
}
2 Likes

Could you please share your findings?

Have edited the post above

1 Like