NoClassDefFoundError - Generated classes

Hello I have a gradle project that used to work correctly in eclipse (neon 3) with an older version of buildship, recently I updated to version 2.2.1 and cannot run my unit tests anymore.
The problem lies in the fact that, using querydsl, there are a bunch of generated classes (that are correctly added to the project classpath) that now are not found anymore when trying to run the tests.
Running the tests just using gradlew is ok.
I have read something concerning the fact that the now the classpath used by eclipse and that used by buildship have totally diverged so I see the classes in eclipse’s classpath but are not available for buildship’s. The problem is that I have no idea on how to solve this… :slight_smile:

Buildship 2.2 introduced runtime classpath separation which probably causes your problem. The works the following way: it checks what Gradle source sets the executed main() method or test class belong to and filters the unrelated entries from the runtime classpath. It’s a bit tricky to debug, so I’d suggest you create minimal example exhibiting the problem and we’ll have a look.

Another idea would be to disable the classpath separation. You can do that by removing the gradle_scope and the gradle_used_by_scope attributes from the classpath entries. You can customize the classpath entries in the eclipse.classpath.file.whenMerged block:

apply plugin: 'java'
apply plugin: 'eclipse'

eclipse {
    classpath {
        file {
            whenMerged {
                entries.each { entry ->
                    if (entry instanceof org.gradle.plugins.ide.eclipse.model.AbstractClasspathEntry) {
                        entry.entryAttributes.remove('gradle_scopes')
                        entry.entryAttributes.remove('gradle_used_by_scope')
                    }
                }
            }
        }
    }
}
1 Like

I’ll try to create an example project asap. In the meanwhile, the solution of disabling class separation works, thank you!

1 Like

Hello,
I experienced the same problem with Buildship 2.2.1 and Eclipse 2018-09.
I was able to create a sample project, which reproduces the bug: Generated sources from Query DSL plugin can not be accessed if buildship classpath separation is active.

Steps:

  • import project into eclipse
  • run “./gradlew queryDsl” or “./gradlew install” in library folder
  • Run “Refresh Gradle Project” in eclipse
  • execute test QMyEntityTest in subproject library-server

If you comment in lines 37-46 in library-server build.gradle, then it works.

Git Repo: https://github.com/jmeierhofer/buildship-bug-querydsl

Regards & many thanks in advance
Jochen

It seems that the com.ewerk.gradle.plugins.querydsl plugin defines a new source set that is independent from the main and test source sets. Would it make sense to make the generated types part of the main source set?

Hi donat,

thanks for your reply. Ok, good to know that the ewerk querydsl plugin causes the problem. I will try to find another solution. Perhaps it works with another plugin.

I will write another post if I managed to get it running.

I managed to get queryDsl running with eclipse 2018-09, buildship 2.2.1 and gradle 4.10.2. I attached my gradle build file if anybody finds this thread in the future.

Eclipse detects changed entities automatically and runs the JPA annotation processor in the background.

  • Import the project with buildship
  • Run the following gradle commands in a bash or commandline: ./gradlew eclipseJdtApt eclipseFactoryPath eclipseJdt
  • Refresh the gradle project in eclipse (right click - gradle - refresh gradle project)
build.gradle

buildscript {
repositories {
mavenCentral()
}
}

plugins {
id ‘java’
id “net.ltgt.apt” version “0.20”
id ‘net.ltgt.apt-eclipse’ version ‘0.19’
}

repositories {
mavenCentral()
}

// query DSL annotation processor config
dependencies {
def queryDslVersion = ‘4.2.1’

compile("com.querydsl:querydsl-core:${queryDslVersion}")
compile("com.querydsl:querydsl-jpa:${queryDslVersion}")

annotationProcessor (
    "com.querydsl:querydsl-apt:${queryDslVersion}:jpa",
    "org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final",
    "javax.annotation:javax.annotation-api:1.3.2",
)

}

dependencies {
compile(“org.hibernate:hibernate-java8:5.2.12.Final”)

testCompile "junit:junit:4.12"
testCompile "org.hamcrest:hamcrest-all:1.3"
testCompile "org.mockito:mockito-core:1.10.19" 

}

// eclipse annotation processor config for query DSL - see https://github.com/tbroyer/gradle-apt-plugin
eclipse {
jdt {
apt {
aptEnabled = compileJava.aptOptions.annotationProcessing
reconcileEnabled = true
processorOptions = compileJava.aptOptions.processorArgs
// where eclipse will output the generated sources
genSrcDir = file(‘bin/.apt_generated’)
}
}

factorypath {
    plusConfigurations = [ configurations.annotationProcessor, configurations.testAnnotationProcessor ]
    minusConfigurations = []
}

}

The approach from Jochen is the one I am taking right now as well.
And it works fine. The issue is just the manual steps needed to run the tasks “eclipseJdtApt eclipseFactoryPath eclipseJdt” and the manual refresh of the project.
Is there any way to somehow automate this so buildship just does this when I import the project in Eclipse or do a “Gradle Refresh” at least?

I was wondering if Buildship of Eclipse is executing any actual gradle task? like the eclipse task? It does not seem to be the case. At least when i try something along this lines, it dont see this beeing executed when i run “Gradle Refresh”…

tasks["eclipse"].dependsOn("testit")

task testit {
    doLast {
        def file1 = new File('c:/junk/log.txt')
        file1.write 'Executed from Eclipse.\n'
    }
}

That’s because buildship does not execute the eclipse task as far as I know.
I am also interested in an automatic approach. I was postponing this manual issue for now…

Hello,

I’m facing the same problem when using Gradle plugin that adds generated sources to the classpath.
All is good when building the project in command line. But in Eclipse, while launching JUnit tests, I have a java.lang.NoClassDefFoundError for the classes located in generated source folder…

Is there a way to solve this properly, without removing Gradle classpath separation?

Please advise

Not at this moment. Frankly, the whole classpath separation implementation was proven faulty and hard to understand. I’m planning to replace it with Eclipse’s own “test sources” feature as my next task.

Ok thank you for replying

Hi Simone,
don’t know if you’re still facing the problem.
We also use querydsl in one of our projects and faced the same issue.
We have reconfigured our generator task to generate to src/main/generated and added this sourcedir to the existing main sourceset like

sourceSets {
main {
java {
srcDir file(‘src/main/generated’)
}
}
}

which works for us even in eclipse because the generated classes are compiled to bin itself
Hope that helps
Markus