I'm upgrading a Gradle 7.5 project that uses Spring Boot 2.7.5 and QueryDSL 5.0 from Java 8 to Java 17. The project was working before the upgrade, but afterword, it does not build because the final CompileJava execution logs a "cannot find symbol" error for all the Q class references in the code.
I think these classes are either being stored differently or are not being generated.
Also, in case this helps, I'm using VS Code as my IDE, but am running all my Gradle commands from a standard Windows command prompt.
I've looked at Stack Overflow and other sites for questions related to this. Unfortunately, though this question has been asked in various contexts, their answers did not work out for my context. Here are some places where I looked in case this helps others:
Here's my build.gradle. Please note that this was working when I had 'sourceCompatability = 1.8" and haden't started using the toolchain notation or even Java 17, yet. Also know that I did not create this file from scratch, but am editing one that someone else started.
Additionally, it's the "compileJava" command in the "bootRun" task that is failing (the main task to 'run' the app is "MyAppRun". It, in turn executes "preCompile", "generateJPA", "generateQueryDSL", and "bootRun" in that order). I expect something needs to change in the "generateQueryDSL" task.
I'm very new to Gradle and QueryDSL and would appreciate any advice.
Thanks in advance!
plugins {
id 'org.springframework.boot' version '2.7.5'
// id 'net.ltgt.apt' version '0.18'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.mydomain'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
// sourceCompatibility = '17.0.6'
repositories {
mavenLocal()
mavenCentral()
maven { url 'https://repo.spring.io/snapshot' }
maven { url 'https://repo.spring.io/milestone' }
}
configurations {
hibernatetool
querydslapt
}
configurations.implementation.canBeResolved = true
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
}
generated {
java {
srcDir "$projectDir/generated/java"
}
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
implementation 'org.springframework.boot:spring-boot-starter-jersey'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-config:5.6.8'
implementation 'org.springframework.security:spring-security-core:5.6.8'
implementation 'org.springframework.security:spring-security-oauth2-resource-server:5.6.8'
implementation 'org.springframework.security:spring-security-oauth2-jose:5.6.8'
runtimeOnly group: 'com.nimbusds', name: 'oauth2-oidc-sdk', version: '6.23'
implementation 'org.hibernate:hibernate-core:5.6.12.Final'
implementation 'org.hibernate:hibernate-tools:5.6.2.Final'
implementation 'org.springframework.data:spring-data-rest-hal-explorer'
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.3.2'
implementation group: 'org.json', name: 'json', version: '20200518'
runtimeOnly 'org.postgresql:postgresql'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
exclude group: 'junit', module: 'junit'
}
hibernatetool group:'org.hibernate', name:'hibernate-core', version:'5.6.12.Final'
hibernatetool group:'org.hibernate', name:'hibernate-tools', version:'5.6.2.Final'
hibernatetool group:'org.hibernate', name:'hibernate-entitymanager', version:'5.6.12.Final'
hibernatetool group:'org.postgresql', name:'postgresql'
implementation("com.querydsl:querydsl-core:5.0.0")
implementation("com.querydsl:querydsl-jpa:5.0.0")
implementation('com.google.guava:guava:31.1-jre')
implementation('com.google.code.findbugs:jsr305:3.0.2')
annotationProcessor("com.querydsl:querydsl-apt:5.0.0:jpa")
annotationProcessor('org.springframework.boot:spring-boot-starter-data-jpa')
annotationProcessor('org.springframework.boot:spring-boot-starter-data-rest')
annotationProcessor('javax.persistence:javax.persistence-api:2.2')
annotationProcessor('javax.annotation:javax.annotation-api:1.3.2')
implementation fileTree(include: ['*.jar'], dir: './libs')
/* annotationProcessor 'com.querydsl:querydsl-apt:4.2.1:jpa'
annotationProcessor 'org.springframework.boot:spring-boot-starter-data-jpa' // needed because the query dsl annotation processor doesn't recognize javax.persistence.Entity
compile 'com.querydsl:querydsl-jpa:4.2.1'*/
}
springBoot {
if (project.hasProperty('import')) {
mainClass = 'com.mydomain.MyAppservices.ImportApplication'
} else {
mainClass = 'com.mydomain.MyAppservices.MyAppApplication'
}
}
bootRun {
if (project.hasProperty('import')) {
args project.import
}
compileJava {
options.compilerArgs << "-proc:none"
}
}
task preCompile (type: JavaCompile) {
source = sourceSets.main.java.srcDirs
include 'com/mydomain/MyAppservices/config/MyAppReverseEngineeringStrategy.java'
classpath = configurations.implementation
destinationDirectory = file("build/classes/java/main")
}
task generateJPA {
group 'MyApp'
description 'Generate JPA Entities'
doLast{
delete 'src/main/java/com/mydomain/MyAppservices/model', '*'
delete fileTree('src/main/java/com/mydomain/MyAppservices/views') { include 'Q*' }
ant {
taskdef(name: 'hibernateTool',
classname: 'org.hibernate.tool.ant.HibernateToolTask',
classpath: configurations.hibernatetool.asPath)
hibernateTool {
jdbcconfiguration(propertyFile: 'resources/hibernate.reveng.properties',
detectmanytomany: 'true',
reversestrategy: 'com.mydomain.MyAppservices.config.MyAppReverseEngineeringStrategy',
packagename: 'com.mydomain.MyAppservices.model',
revengfile: 'resources/hibernate.reveng.xml')
hbm2java(destdir: 'src/main/java', ejb3: 'true', jdk5: 'true')
classpath {
pathElement(path: "build/classes/java/main")
}
}
}
}
}
task generateQueryDSL (type: JavaCompile) {
group 'MyApp'
description "Generate QueryDSL classes"
options.compilerArgs << "-s"
options.compilerArgs << "src/main/java/"
options.compilerArgs << "-proc:only"
options.compilerArgs << '-processor'
options.compilerArgs << 'com.querydsl.apt.jpa.JPAAnnotationProcessor'
options.annotationProcessorPath = configurations.annotationProcessor
source = sourceSets.main.java.srcDirs
classpath = configurations.implementation + configurations.annotationProcessor
destinationDirectory = file("build/classes/java/main")
}
generateJPA.dependsOn preCompile
generateQueryDSL.dependsOn generateJPA
task generate {
group 'MyApp'
description "Generate all JPAs and QueryDSL classes"
dependsOn generateQueryDSL
}
task MyAppRun {
dependsOn bootRun
dependsOn generate
tasks.findByName('bootRun').mustRunAfter 'generate'
}
task cleanGenerated {
doLast{
delete 'src/main/java/com/mydomain/MyAppservices/model', '*'
}
}
To answer my own question, a coworker ended up changing a line at the end of the generateJPA
task from
hbm2java(destdir: 'src/main/java', ejb3: 'true', jdk5: 'true')
to
hbm2java(destdir: 'src/main/java', ejb3: 'true', jdk5: 'true', templatepath: 'resources/templates')
and made sure we had a <Spring Boot project root>/resources/templates/pojo/Pojo.ftl file with this content:
${pojo.getPackageDeclaration()}
<#assign classbody>
<#include "PojoTypeDeclaration.ftl"/> {
<#if !pojo.isInterface()>
<#include "PojoFields.ftl"/>
<#include "PojoConstructors.ftl"/>
<#include "PojoPropertyAccessors.ftl"/>
<#include "PojoToString.ftl"/>
<#include "PojoEqualsHashcode.ftl"/>
<#else>
<#include "PojoInterfacePropertyAccessors.ftl"/>
</#if>
<#include "PojoExtraClassCode.ftl"/>
}
</#assign>
${pojo.generateImports()}
${classbody}
This solved it for us.