Generating JPA2 Metamodel from a Gradle build script
Asked Answered
S

7

21

I'm trying to set up a Gradle build script for a new project. That project will use JPA 2 along with Querydsl.

On the following page of Querydsl's reference documentation, they explain how to set up their JPAAnnotationProcessor (apt) for Maven and Ant.

I would like to do the same with Gradle, but I don't know how and my beloved friend did not help me much on this one. I need to find a way to invoke Javac (preferably without any additional dependencies) with arguments to be able to specify the processor that apt should use (?)

Sticky answered 21/6, 2011 at 19:39 Comment(0)
M
12

I did not test it but this should work:

repositories {
    mavenCentral()
}
apply plugin: 'java'
dependencies {
   compile(group: 'com.mysema.querydsl', name: 'querydsl-apt', version: '1.8.4')
   compile(group: 'com.mysema.querydsl', name: 'querydsl-jpa', version: '1.8.4')
   compile(group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.6.1')
}

compileJava {
    doFirst {
        Map otherArgs = [
            includeAntRuntime: false,
            destdir: destinationDir,
            classpath: configurations.compile.asPath,
            sourcepath: '',
            target: targetCompatibility,
            source: sourceCompatibility
        ]
        options.compilerArgs = [
            '-processor', 'com.mysema.query.apt.jpa.JPAAnnotationProcessor',
            '-s', "${destinationDir.absolutePath}".toString()
        ]
        Map antOptions = otherArgs + options.optionMap()
        ant.javac(antOptions) {
            source.addToAntBuilder(ant, 'src', FileCollection.AntType.MatchingTask)
            options.compilerArgs.each {value ->
                compilerarg(value: value)
            }
        }
    }
}

Hope it helps.

Maurice answered 22/6, 2011 at 22:49 Comment(4)
Doesn't your solution add a dependency to ant in the build? I would like to avoid that if possibleSticky
Ant is how Gradle builds. It's in Gradle core so no dependencies needed. Happy to know it worked.Maurice
Good to know, that'll teach me to RTFM before I comment ;-) Thanks again.Sticky
gradle is ant, but in groovy instead of xml.Cutlery
L
16

While I have no problem with the use gradle makes of Ant, I agree with the original poster that it is undesirable in this case. I found a github project by Tom Anderson here that describes what I believe is a better approach. I modified it a small amount to fit my needs (output to src/main/generated) so that it looks like:

sourceSets {
     generated
}

sourceSets.generated.java.srcDirs = ['src/main/generated']

configurations {
     querydslapt
}

dependencies {     
    compile 'mine go here'
    querydslapt 'com.mysema.querydsl:querydsl-apt:2.7.1'
}

task generateQueryDSL(type: Compile, 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

This approach makes a lot more sense to me than the other, if it does to you too, then you have another option for querydsl generation.

Layfield answered 23/8, 2012 at 18:3 Comment(2)
thank you Joeg: I like the approach of keeping separated the source code generation step and the code compilation step :)Crashaw
Thank you! this did the job for m, but I had to replace type:Compile with type:JavaCompileDag
M
12

I did not test it but this should work:

repositories {
    mavenCentral()
}
apply plugin: 'java'
dependencies {
   compile(group: 'com.mysema.querydsl', name: 'querydsl-apt', version: '1.8.4')
   compile(group: 'com.mysema.querydsl', name: 'querydsl-jpa', version: '1.8.4')
   compile(group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.6.1')
}

compileJava {
    doFirst {
        Map otherArgs = [
            includeAntRuntime: false,
            destdir: destinationDir,
            classpath: configurations.compile.asPath,
            sourcepath: '',
            target: targetCompatibility,
            source: sourceCompatibility
        ]
        options.compilerArgs = [
            '-processor', 'com.mysema.query.apt.jpa.JPAAnnotationProcessor',
            '-s', "${destinationDir.absolutePath}".toString()
        ]
        Map antOptions = otherArgs + options.optionMap()
        ant.javac(antOptions) {
            source.addToAntBuilder(ant, 'src', FileCollection.AntType.MatchingTask)
            options.compilerArgs.each {value ->
                compilerarg(value: value)
            }
        }
    }
}

Hope it helps.

Maurice answered 22/6, 2011 at 22:49 Comment(4)
Doesn't your solution add a dependency to ant in the build? I would like to avoid that if possibleSticky
Ant is how Gradle builds. It's in Gradle core so no dependencies needed. Happy to know it worked.Maurice
Good to know, that'll teach me to RTFM before I comment ;-) Thanks again.Sticky
gradle is ant, but in groovy instead of xml.Cutlery
B
9

This guy's gist worked for me: https://gist.github.com/EdwardBeckett/5377401

sourceSets {
    generated {
        java {
            srcDirs = ['src/main/generated']
        }
    }
}

configurations {
    querydslapt
}

dependencies {
    compile 'org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final'
    compile "com.mysema.querydsl:querydsl-jpa:$querydslVersion"
    querydslapt "com.mysema.querydsl:querydsl-apt:$querydslVersion"
}

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
    options.warnings = false
    classpath += sourceSets.main.runtimeClasspath
}

clean {
    delete sourceSets.generated.java.srcDirs
}

idea {
    module {
        sourceDirs += file('src/main/generated')
    }
}
Brendon answered 23/8, 2013 at 22:49 Comment(1)
I'm using Gradle 1.10 and this worked like a charm! Thanks @Ryan.Melicent
L
4

With Gradle 1.3 and newer (older not tested) you can use Querydsl APT like this:

configurations {
  javacApt
}
dependencies {
  javacApt 'com.mysema.querydsl:querydsl-apt:3.3.0'
}
compileJava {
  options.compilerArgs <<
    '-processorpath' << (configurations.compile + configurations.javacApt).asPath <<
    '-processor' << 'com.mysema.query.apt.jpa.JPAAnnotationProcessor'
}

These compiler args are passed directly to javac.

To use with groovy compiler replace compileJava with compileGroovy.

Lothaire answered 15/1, 2013 at 12:31 Comment(1)
Hi Pavel! I tried the solution you're suggesting for my entities (which are written in groovy) but it would not work. It would work, however, if anything was in groovy but the entities. I posted a solution as comment to a similar question for cases where you want @Entity classes written in Groovy to be picked up by the querydsl generator hereRagnar
O
4

Here is simple setup that works and integrates seamlessly with netbeans. Javac will basicly do all the job needed without much intervention. The rest are small treaks that will make it work with IDEs like Netbeans.

apply plugin:'java'

dependencies {
    // Compile-time dependencies should contain annotation processors
    compile(group: 'com.mysema.querydsl', name: 'querydsl-apt', version: '1.8.4')
    compile(group: 'com.mysema.querydsl', name: 'querydsl-jpa', version: '1.8.4')
    compile(group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.6.1')
}

ext {
    generatedSourcesDir = file("${buildDir}/generated-sources/javac/main/java")
}

// This section is the key to IDE integration.
// IDE will look for source files in both in both
//
//  * src/main/java
//  * build/generated-sources/javac/main/java
//
sourceSets {
    main {
        java {
            srcDir 'src/main/java'
            srcDir generatedSourcesDir
        }
    }
}

// These are the only modifications to build process that are required.
compileJava {
    doFirst {
        // Directory should exists before compilation started.
        generatedSourcesDir.mkdirs()
    }
    options.compilerArgs += ['-s', generatedSourcesDir]
}

And that's it. Javac will make the rest of the job.

Obryan answered 22/4, 2014 at 10:54 Comment(1)
Excellent! This is what I was looking for!Cutlery
F
2

To use the JPA Metamodel Generator with Gradle I'm successfully using the following in my build.gradle and it works like a charm:

buildscript {
    ext {}
    repositories { // maven central & plugins.gradle.org/m2 }
    dependencies {
        // other dependencies, e.g. Spring
        classpath('gradle.plugin.at.comm_unity.gradle.plugins:jpamodelgen-plugin:1.1.1')
    }

    apply plugin: 'at.comm_unity.gradle.plugins.jpamodelgen'

    dependencies {
        compile('org.hibernate:hibernate-jpamodelgen:5.1.0.Final')
    }

    jpaModelgen {
        jpaModelgenSourcesDir = "src/main/java"
    }

    compileJava.options.compilerArgs += ["-proc:none"]
}

Within the build task, the static metamodel classes suffixed with '_' are generated. Afterwards they are located in the same directory as my @Entity models are.

Fiord answered 20/4, 2016 at 15:11 Comment(1)
I don't recommend adding the generated models to the main sources. I rather would add them to a separate source dir like src/generated/java. This path has then to be added to the main java sourceSet. I don't know the sense of the compile dependency and the compileJava args, why are you adding them?Pelage
C
1

The Querydsl Ant example should work pretty much as is when you take all the XML out. So it ends up being something like this:

javac -sourcepath ${src} -cp ${cp} -proc:only -processor com.mysema.query.apt.jpa.JPAAnnotationProcessor -s ${generated}

src, cp and generated you will probably be able to extract from Gradle.

Careful answered 21/6, 2011 at 21:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.