I have a gradle based eclipse workspace which has a parent project and multiple child projects. Eclipse suddenly has problems adding a project to the classpath of another though it works fine from gradle command line.
Eclipse is showing a typical error for a package it can't find:
PROJECTS
CmbProduct
+-- build.gradle
+-- settings.gradle
+--+ MangoCommon
+-- build.gradle
+-- src/main/java/org/mangogrove/common/util/StringTool.java
+--+ Model
+-- build.gradle
+--+ Common
+-- build.gradle
+-- src/main/java/mypackage/AbstractExpander.java
View of Projects:
If I open AbstractExpander.java in eclipse it shows the import of StringTool as an error and underlins the "mango" package as the error. (See first pic).
WHAT I HAVE TRIED
Classes in Model that import classes from MangoCommon are fine.
Running "gradle compileJava" from command line works fine.
There are no errors in .metadata/.log
If I delete .metadata and rebuild/re-import the problem returns.
A similar setup on the same system for a different dev branch of the same product works fine.
I've done a restore of the dev tree from backups from last week when it worked fine. Problem returns as soon as I Gradle -> Sync in eclipse.
I removed .metadata and all .project .classpath .settings from each project (including parent) and imported via Gradle > Import Existing Gradle Project
EDIT 20221121
I tried eclipse 2021-12 before running I removed all .metadata .project .classpath .settings from each project (including parent) and imported via Gradle > Import Existing Gradle Project.
EDIT 20221122
Created a completely new workspace dir, git imported, then ran Eclipse and did Import > Gradle Existing Project. Same problem.
I restored the VM holding the broken workspace from a week before the VM rebooted. Eclipse fires up fine on the broken workspace. However after I run Gradle > Refresh Gradle Project it becomes broken in the same way.
I installed eclipse 2022-06 (4.20) and wiped my .metadata .settings .classpath .project files. After Gradle Import Existing Project the problem appears right away.
FINDINGS
In eclipse if I expand Common -> Project and External Dependencies the "MangoCommon" entry is greyed out but "Model" is normal.
My actual product has many other sub-projects most of which are like "Common" and are showing errors when importing classes from MangoCommon.
CmbProject build.gradle
buildscript {
// Always load buildinfo so project.version is set as early as possible
gradle.startParameter.taskNames = [":buildInfoLoad"] + gradle.startParameter.taskNames
// Repos needed just for the dependencies section directly below
repositories {
flatDir {
dirs 'MangoGroveGradle/repoflat'
}
maven { // aka "jcenter()"
url "https://jcenter.bintray.com"
}
}
dependencies {
classpath("org.mangogrove.gradle:MangoGroveGradle:1.0.0")
}
}
apply plugin: 'org.mangogrove.gradle'
import org.apache.tools.ant.filters.*;
allprojects {
ext {
... snip ...
generatedSrcDir = "src-gen
}
wrapper {
distributionType = Wrapper.DistributionType.BIN
}
subprojects {
/*
* Use "apply plugin" not "plugins" because the former allows each
* sub-project to add their own without overriding what is set here.
*/
apply plugin: 'java'
/*
* We use "testFixturesApi" and similar here so we must have this plugin
*/
apply plugin: 'java-test-fixtures'
// Every subproject should be configured for Eclipse
apply plugin: 'eclipse'
/*
* Some files contain non-ASCII chars like Euro symbol. We need to tell
* Java to use UTF-8 always
*/
compileJava {options.encoding = "UTF-8"}
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_1_8
javadoc.enabled = false
sourceSets {
main {
java {
// Define all source dirs - Purpose is to add "src-gen"
srcDirs = ["src/main/java", "$rootProject.generatedSrcDir" ]
}
}
}
/*
* Tell Gradle to treat src-gen like a resource so it will copy <model>.ecore files here
* and set classpath properly at runtime.
*/
sourceSets.main.resources.srcDir "$rootProject.generatedSrcDir"
repositories {
maven {
// Local repo for annovention
url uri("$rootDir/MangoCommon/repo")
}
maven {
url uri("$rootDir/logbackwela/repo")
}
mavenCentral()
maven { url "https://maven.java.net/content/groups/public" }
// Texo/EMF
maven { url "https://oss.sonatype.org/content/groups/public" }
// Eclipse
maven { url "https://oss.sonatype.org/content/repositories/public/eclipse" }
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
maven { url 'https://mvnrepository.com/artifact' }
maven { url "https://repository.jboss.org/nexus/content/groups/public-jboss" }
maven { url "https://maven.vaadin.com/vaadin-addons" }
maven { url "https://oss.sonatype.org/content/repositories/vaadin-snapshots" }
maven { url "https://maven.clapper.org" }
// Project Lombok
maven { url "https://projectlombok.org/mavenrepo" }
}
def bouncycastleVersion = "1.69" // Was 1.68
def lombokVersion = "1.18.20" // was 1.18.10
.... snip ...
ext {
springFrameworkVersion = "5.3.6" // 5.3.4
springDataVersion = "2.4.8" // 2.4.3
... snip ...
}
configurations.all {
// We use logback now but some dependencies pull in slf4j-jdk14 so we exclude here
exclude group:"org.slf4j", module: "slf4j-jdk14"
}
dependencies {
/*
* PRODUCT SPECIFIC
*/
implementation "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion"
implementation "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"
testFixturesApi "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion"
testFixturesApi "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"
/*
* Common and product
*/
implementation "org.simpleframework:simple-xml:$simpleXmlVersion"
/*
* We use logback for logging but need various slf4j packages to route other
* logger frameworks to slf4j which is handled by logback
*/
implementation "ch.qos.logback:logback-classic:$logbackVersion"
implementation "org.slf4j:slf4j-api:$slf4jVersion"
// Janino required by our logback configs
implementation "org.codehaus.janino:janino:$janinoVersion"
// Route JCL -> slf4j which forwards to logback
implementation "org.slf4j:jcl-over-slf4j:$slf4jVersion"
// Route JUL -> slf4j which forwards to logback
// This is required for c3p0 to use slf4j -> logback
implementation "org.slf4j:jul-to-slf4j:$slf4jVersion"
// Route log4j -> slf4j which forwards to logback
implementation "org.slf4j:log4j-over-slf4j:$slf4jVersion"
// Send slf4j to log4j 1.2 for those JARs which use slf4j
//implementation "org.slf4j:slf4j-log4j12:$slf4jVersion"
// Log4j itself
//implementation "log4j:log4j:$log4jVersion"
// Texo (use changing: true to enable snapshots)
implementation group: "org.eclipse.emf", name: "org.eclipse.emf.texo", version: "$texoVersion", changing: true
implementation group: "org.eclipse.emf", name: "org.eclipse.emf.texo.server", version: "$texoVersion", changing: true
implementation group: "org.eclipse.emf", name: "org.eclipse.emf.texo.xml", version: "$texoVersion", changing: true
// Texo dependencies (not automaticly added by texo)
implementation "org.eclipse.emf:org.eclipse.emf.common:$emfVersion"
implementation "org.eclipse.emf:org.eclipse.emf.ecore:$emfVersion"
implementation "org.eclipse.emf:org.eclipse.emf.ecore.xmi:$emfVersion"
implementation "org.jsoup:jsoup:$jsoupVersion"
// Apache HTTP client
implementation("org.apache.httpcomponents:httpclient:$apacheHttpClientVersion") {
// This is an older implementation deprecated by jcl-over-slf4j
exclude group: "commons-logging"
}
// EventBus and more
implementation "com.google.guava:guava:$googleGuavaVersion"
testFixturesApi "com.google.guava:guava:$googleGuavaVersion"
implementation("com.sun.mail:javax.mail:$javaxMailVersion") { // Actual implementation
// This dependency includes an older version
exclude group: "javax.activation"
}
// Make sure we use the same version for everything
implementation "jakarta.annotation:jakarta.annotation-api:1.3.5"
implementation "net.java.dev.jna:jna:$jnaVersion"
implementation "net.java.dev.jna:jna-platform:$jnaVersion"
// This package provided by Tomcat or Servlet container
compileOnly "javax.servlet:javax.servlet-api:$javaxServletVersion"
testFixturesApi "javax.servlet:javax.servlet-api:$javaxServletVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
compileOnly "org.projectlombok:lombok:$lombokVersion"
testFixturesApi "org.projectlombok:lombok:$lombokVersion"
testFixturesAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
testImplementation "org.projectlombok:lombok:$lombokVersion"
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
testImplementation "org.testng:testng:$testngVersion"
}
}
CmbProject settings.gradle
include 'CodeGen'
include 'MangoCommon'
include 'Model'
include 'Common'
Common build.gradle
plugins {
id 'java-library'
}
// Enable deprecation messages in javac
compileJava {
options.compilerArgs << '-Xlint:deprecation'
}
compileTestJava {
options.compilerArgs << '-Xlint:deprecation'
}
dependencies {
api project(":Model")
// Version does not change
api "javax.xml.soap:javax.xml.soap-api:1.4.0"
testImplementation testFixtures(project(":MangoCommon"))
testFixturesApi project(":MangoCommon")
testFixturesApi testFixtures(project(":MangoCommon"))
// Required for JAX-RS Client
api "org.glassfish.jersey.core:jersey-client:$jerseyGlassfishVersion"
// Required by client + servlet container 2.26 and later [RUNTIME REQUIREMENT]
api "org.glassfish.jersey.inject:jersey-hk2:$jerseyGlassfishVersion"
// Required by Client jersey 2.26 and later [RUNTIME REQUIREMENT]
api "org.glassfish.jersey.media:jersey-media-jaxb:$jerseyGlassfishVersion"
}
... snip out tasks ....
Model build.gradle
plugins {
id 'java-library'
}
compileJava.dependsOn copyEcore
// Enable deprecation messages in javac
compileJava {
options.compilerArgs << '-Xlint:deprecation'
}
dependencies {
api project(":MangoCommon")
// testImplementation testFixtures(project(":MangoCommon"))
api "org.flywaydb:flyway-core:$flywayVersion"
// Provide javax.persistence classes
api "org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final"
implementation "org.hibernate:hibernate-core:$hibernateVersion"
}
sourceSets.test.resources.srcDir "src/dev/resources" // for persistconfig.properties
... snip tasks ...
MangoCommon build.gradle
plugins {
id 'java-library'
}
// Enable deprecation messages in javac
compileJava {
options.compilerArgs << '-Xlint:deprecation,unchecked'
}
compileTestJava {
options.compilerArgs << '-Xlint:deprecation,unchecked'
}
compileTestFixturesJava {
options.compilerArgs << '-Xlint:deprecation'
}
dependencies {
testImplementation "org.testng:testng:$testngVersion"
api "com.impetus:annovention:$annoventionVersion"
api("org.clapper:javautil:$clapperJavaUtilVersion") {
// Exclude older asm to avoid implementation issue
exclude group: "asm", module: "asm"
exclude group: "asm", module: "asm-commons"
exclude group: "asm", module: "asm-tree"
// Exclude items provided elsewhere
exclude group: "javax.mail", module: "mail"
exclude group: "commons-logging", module: "commons-logging"
exclude group: "javax.activation"
}
api("org.freemarker:freemarker:$freemarkerVersion") {
exclude group: "freemarker", module: "freemarker" // Legacy org-less group
}
implementation "org.hibernate:hibernate-core:$hibernateVersion"
testFixturesApi "org.hibernate:hibernate-core:$hibernateVersion"
api "org.springframework:spring-core:$springFrameworkVersion"
api "org.springframework:spring-context:$springFrameworkVersion"
api "org.springframework:spring-context-support:$springFrameworkVersion"
api "org.springframework:spring-orm:$springFrameworkVersion"
api "org.springframework:spring-web:$springFrameworkVersion"
api "org.springframework:spring-webmvc:$springFrameworkVersion"
api "org.springframework.data:spring-data-jpa:$springDataVersion"
api "com.zaxxer:HikariCP:$hikariCpVersion"
}
... snip tasks ...
Here is the Common/.classpath that Eclipse -> Gradle sync created:
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/java">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src-gen">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/testFixtures" path="src/testFixtures/java">
<attributes>
<attribute name="gradle_scope" value="testFixtures"/>
<attribute name="gradle_used_by_scope" value="testFixtures"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="src" path="/Model">
<attributes>
<attribute name="without_test_code" value="false"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="/MangoCommon">
<attributes>
<attribute name="without_test_code" value="false"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin/default"/>
</classpath>
Environment
eclipse.buildId=4.25.0.I20220831-1800
java.version=17.0.4.1
java.vendor=Eclipse Adoptium
Gradle: 7.5.1
Buildship: 3.1.6
Found the problem!
Gradle 7.5.x + Buildship 3.1.6 seem to be broken. When I configured Eclipse (Preferences > Gradle > Specific version) to use 7.4.2 everything worked once again.
I normally have Eclipse Gradle configured to use gradle wrapper. I had upgraded gradle wrapper from 7.4.2 to 7.5.1 from the command line a month ago. Gradle worked fine from the command line but once my dev system rebooted I ran Gradle > Refresh Gradle Project which used 7.5.1 for the first time in eclipse.