Gradle 5 QueryDsl Generating Duplicate Classes - gradle

I am using queryDsl to generate Q classes with Gradle. It used to work fine with Gradle 3.5, but on upgrading to Gradle 5.5.1, it is failing with duplicate class error.
My generateQueryDsl task works fine generating the classes under 'gensrc/' but on compileJava, the classes are generated again under 'build/generated/' which ends up giving duplicate class error.
dependencies {
api("org.springframework.boot:spring-boot-starter-data-jpa") {
exclude group: "org.hibernate", module: "hibernate-entitymanager"
exclude group: "org.hibernate", module: "hibernate-core"
exclude group: "org.apache.tomcat", module: "tomcat-jdbc"
}
api("com.zaxxer:HikariCP:${hikaricpVersion}")
api("com.h2database:h2:1.4.193")
api("mysql:mysql-connector-java")
api("com.microsoft.sqlserver:sqljdbc42:6.0.8112")
api("org.springframework.data:spring-data-jpa")
api("org.springframework:spring-jdbc")
api("org.springframework:spring-orm")
api("org.eclipse.persistence:javax.persistence:${eclipseLinkPersistenceVersion}")
api("org.eclipse.persistence:eclipselink:${eclipseLinkVersion}")
api("org.eclipse.persistence:org.eclipse.persistence.jpa:${eclipseLinkVersion}")
api("com.mysema.querydsl:querydsl-sql:${queryDslVersion}")
api("com.mysema.querydsl:querydsl-jpa:${queryDslVersion}")
api("com.mysema.querydsl:querydsl-apt:${queryDslVersion}")
annotationProcessor('com.mysema.querydsl:querydsl-apt:3.7.4:jpa')
annotationProcessor("org.springframework.boot:spring-boot-starter-data-jpa")
}
task generateQueryDSL(type: JavaCompile, group: 'build) {
source = sourceSets.main.java
classpath = configurations.compileClasspath
options.annotationProcessorPath = configurations.annotationProcessor
destinationDir = file('gensrc/main/java')
}
compileJava {
dependsOn generateQueryDSL
}
error: duplicate class: com.persistence.domain.model.QOrganizationBasedModel
and likewise for all generated classes

When you use the annotationProcessor configuration, the default compileJava task adds the processor to the compiler, and it will generate classes in build/generated/sources/annotationProcessor/java/main.
In your case, you also declare an additional JavaCompile task, which you give the same annotationProcessor configuration, which will then generate the same classes again.
To solve this, I would simply delete generateQueryDSL task entirely as compileJava most likely does everything you need already. And if you like the generated sources in a different folder, you can do that through CompileOptions, but I would recommend having them under the build folder for most cases.

Related

In gradle, how to copy a subset of compiled test classes

I tried taking a portion of the compiled test classes of a Gradle project, and put them in a jar file (to create a test case). What happened was, only those classes got compiled out of all test classes. Any idea how to do it right?
Here's my build.gradle:
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
task testSampleJar(type: Zip) {
archiveName "sample.jar"
from compileTestJava {
include "org/example/samples/**"
}
}
test {
dependsOn(testSampleJar)
}
So what seems to be happening is that by just defining the testSampleJar task, the compileTestJava task gets modified to only compile under org.example.samples package. My intent was to use the outputs of compileTestJava and pick something out of them them.
Thanks,
Uri
OK, figured it out, so the two possible solutions are:
//a global filter
task testSampleJar(type: Zip) {
archiveName "sample.jar"
from compileTestJava
include "org/example/samples/**"
}
Or
//Child specification - notice the parentheses around compileTestJava
task testSampleJar(type: Zip) {
archiveName "sample.jar"
from (compileTestJava) {
include "org/example/samples/**"
}
}
I guess the original code was defining compileTestJava instead of using its output, but I don't have a full grasp of Groovy/Gradle DSL to be certain.

How to create a custom task in gradle to pack java and kotlin code to a jar?

We have a multi modular setup and we are sharing some tests classes between the modules (mainly Fakes implementations). Our current solution (that you can find below) works just for classes written in Java, but we are looking at supporting also shared kotlin classes.
if (isAndroidLibrary()) {
task compileTestCommonJar(type: JavaCompile) {
classpath = compileDebugUnitTestJavaWithJavac.classpath
source sourceSets.testShared.java.srcDirs
destinationDir = file('build/testCommon')
}
taskToDependOn = compileDebugUnitTestSources
} else {
task compileTestCommonJar(type: JavaCompile) {
classpath = compileTestJava.classpath
source sourceSets.testShared.java.srcDirs
destinationDir = file('build/testCommon')
}
taskToDependOn = testClasses
}
task testJar(type: Jar, dependsOn: taskToDependOn) {
classifier = 'tests'
from compileTestCommonJar.outputs
}
How can I modify the compileTestCommonJar so it supports kotlin?
Here is what we do:
In the module with shared test classes, pack the test source set output into a jar
configurations { tests }
...
task testJar(type: Jar, dependsOn: testClasses) {
baseName = "test-${project.archivesBaseName}"
from sourceSets.test.output
}
artifacts { tests testJar }
In a module that depends on the shared classes
dependencies {
testCompile project(path: ":my-project-with-shared-test-classes", configuration: "tests")
}
PS: Honestly, I would prefer to have a separate Gradle module with common test classes as it's more explicit solution.
The task compileTestCommonJar(type: JavaCompile) compiles .java files only because its the task of JavaCompile type.
There's KotlinCompile task aswell, so you would need to merge it, it basically works similary to JavaCompile but compiles .kt files only.
Said that i wouldn't use task system to share the dependencies across, i would use separate module and work with default compileTestKotlin and compileTestJava task's outputs

What are .kotlin_builtins files and can I omit them from my uberjars?

I'm working on integrating proguard to my gradle build for an application written in Kotlin. I'm finding that proguard is stripping out the Kotlin standard library (as it should in my simple Hello World program) but it's leaving a bunch of files in my jar that have the file extension .kotlin_builtins. When I configure my gradle task to exclude those files, the program still appears to work fine. What are those files and must they ship with my executable uberjar?
Here's my build.gradle file's contents for reference:
buildscript {
ext.kotlin_version = '1.0.5'
ext.shadow_version = '1.2.4'
repositories {
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
flatDir dirs: "gradle/proguard"
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.github.jengelman.gradle.plugins:shadow:$shadow_version"
classpath ":proguard:"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
mainClassName = 'namespace.MainKt'
defaultTasks 'run'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
testCompile "junit:junit:4.12"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
}
shadowJar {
exclude 'kotlin/**/*.kotlin_builtins'
exclude '.keep'
}
task minify(type: proguard.gradle.ProGuardTask, dependsOn: 'shadowJar') {
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
injars 'build/libs/artful-all.jar'
outjars 'build/libs/artful-all.out.jar'
printmapping 'build/libs/out.map'
keepclasseswithmembers 'public class * { \
public static void main(java.lang.String[]); \
}'
assumenosideeffects 'class kotlin.jvm.internal.Intrinsics { \
static void checkParameterIsNotNull(java.lang.Object, java.lang.String); \
}'
}
These files contain data for declarations of standard ("built-in") Kotlin classes which are not compiled to .class files, but rather are mapped to the existing types on the platform (in this case, JVM). For example, kotlin/kotlin.kotlin_builtins contains the information for non-physical classes in package kotlin: Int, String, Enum, Annotation, Collection, etc.
There are two main scenarios when these files are used:
The compiler looks them up from kotlin-stdlib on the classpath to determine which built-in declarations are available.
The reflection library (kotlin-reflect) loads these files as resources to provide reflection capabilities for built-in declarations. For example, String::class.members returns all members of the class kotlin.String exactly in the same way as the Kotlin compiler sees those members (despite the fact that there's no kotlin/String.class file and it's erased to java.lang.String in bytecode).
The first point is clearly not applicable in your case. And if you don't use reflection on built-in classes, I think it's safe to exclude .kotlin_builtins files completely from the resulting jar.
You can optimize/omit these from yours JARs/APKs:
packagingOptions {
exclude "/META-INF/*.kotlin_module"
exclude "**/kotlin/**"
}
Even better:
packagingOptions {
exclude "/META-INF/*.kotlin_module"
exclude "**/kotlin/**"
exclude "**/*.txt"
exclude "**/*.xml"
exclude "**/*.properties"
}
Source: https://github.com/jaredsburrows/android-gif-example/blob/master/build.gradle.kts#L127

Gradle war plugin pulls in javadoc and sources

I have a strange problem. I have a project which creates a war file with some custom inclusions like images etc. So far it looks good. The only problem left is that gradle pulls in source jars/zips and javadoc jars/zip into my WEB-INF/lib/ folder of my war.
I thought it might be a problem with Idea but same results with the command line. I guess it has something to do with the dependency configuration?
I use compile and runtime scopes and my artifacts are resolved from Artifactory.
Can anyone point me to a direction where to fix that?
Update:
When i create a task:
task copyAllDependencies(type: Copy) {
from configurations.runtime
into 'allRuntime'
}
or
task copyAllDependencies(type: Copy) {
from configurations.compile
into 'allCompile'
}
I'll get the sources as well. So it seems that it has something to do with the compile/runtime configuration. They're pulling the sources and javadoc. But why?!
Dependencies are declared like this:
dependencies {
compile group: 'org.drools', name: 'drools-core', version: DROOLS_VERSION
compile group: 'org.drools', name: 'drools-compiler', version: DROOLS_VERSION
...
runtime group: 'net.sourceforge.barbecue', name: 'barbecue', version: '1.5-beta1', ext: 'jar'
...
testCompile group: 'org.fitnesse', name: 'fitnesse', version: '20130531'
...
}
Here's another attempt... a bit hacky but might work
configurations {
tempCompile
tempRuntime
tempTestCompile
}
dependencies {
tempCompile "org.drools:drools-core:${DROOLS_VERSION}"
tempRuntime "net.sourceforge.barbecue:barbecue:1.5-beta1#jar"
tempTestCompile "org.fitnesse:fitnesse:20130531"
...
compile configurations.tempCompile.asFileTree.matching {
exclude '**/*-sources.jar'
exclude '**/*-javadoc.jar'
}
runtime configurations.tempRuntime.asFileTree.matching {
exclude '**/*-sources.jar'
exclude '**/*-javadoc.jar'
}
testCompile configurations.tempTestCompile.asFileTree.matching {
exclude '**/*-sources.jar'
exclude '**/*-javadoc.jar'
}
}
As we discovered in the comments, your dependencies are bringing in javadoc and sources as transitive dependencies. You can possibly exclude these by
configurations.all { Configuration config ->
['com.group1', 'com.group2', ..., 'com.groupN'].each { groupId ->
config.exclude [group: groupId, classifier: 'javadoc']
config.exclude [group: groupId, classifier: 'sources']
}
}
Note: I'm not an ivy user so the selector (classifier: 'javadoc' etc) may need tweaking

Gradle task execution order doesn't seem to be garuanteed order

I have written a tool OwnerFinder that does some annotation processing on some jars of an application. I need to expose this tool on TeamCity so have written a gradle script which performs following tasks
Extract the application zip file
Copy the application jars to a location build/appJars
compile tool OwnerFinder (keep the appJars in the classpath)
create jar of OwnerFinder
Run OwnerFinder(keep the appJars in the classpath)
(I need to keep the app jars in the class path because the annotation for which processing needs to be done is in those jars)
But somehow the order of the task is not guaranteed even after using dependsOn and mustRunAfter. The script fails either at
compilation task (where its not able to find the annotation in the dependencies)
or
run task where its not able to find the class OwnerFinder
but after 2nd or 3rd try it runs sucessfully. This makes me think that the gradle tasks are not executing as per order.
Following is my gradle script:-
apply from: 'http://some-gradle-util-script'
apply plugin: 'java'
def confs = ["someApplicationConf"]
confs.each { configurations.create it }
configurations { sources }
configureDownload('ivy', 'ivy-integrated')
dependencies {
def someApplicationVersion = '1.12.0.+'
someApplicationConf "com.soft:someApplication-sync:${someApplicationVersion}#zip"
compile 'com.google.guava:guava:16.0.1',
'com.google.code.gson:gson:2.2.2'
testCompile group: 'junit', name: 'junit', version: '4.11'
}
task unzip(type: Copy, dependsOn: clean) {
from zipTree(configurations.someApplicationConf.singleFile)
into "$buildDir/unzipped"
}
task copyJar(type: Copy, dependsOn: unzip) {
from "$buildDir/unzipped/modules"
into "$buildDir/op"
}
copyJar.mustRunAfter unzip
task compileOwnerFinder(type: JavaCompile, dependsOn: copyJar) {
FileCollection f = files(fileTree(dir: 'build/op', include: '*.jar').files, configurations.compile.files)
source = fileTree(dir: 'src', include: '**/*.java')
classpath = f
destinationDir = new File("$buildDir/classes/main")
}
compileOwnerFinder.mustRunAfter copyJar
task jarOwnerFinder(type: Jar, dependsOn: compileOwnerFinder) {
from files(sourceSets.main.output.classesDir)
}
task runOwnerFinder(type: Exec, dependsOn: jarR) {
def classpath = fileTree(dir: 'build/op', include: '*.jar').files + configurations.compile.files +
fileTree(dir: 'build/libs', include: '*.jar').files
commandLine "java", "-classpath", classpath.join(File.pathSeparator), "OwnerFinder"
}
runOwnerFinder.mustRunAfter jarOwnerFinder

Resources