Gradle Eclipse not working correctly for subprojects - eclipse

Gradle 2.4 and Eclipse Mars here. Here's my project directory structure:
myapp/ <-- root project
myapp-client/
src/main/groovy/*
build.gradle <-- just declares some client-specific deps
myapp-shared/
src/main/groovy/*
build.gradle <-- shared-specific deps
myapp-server/
src/main/groovy/*
build.gradle <-- server-specific deps and how to package server JAR
build.gradle
settings.gradle
Where myapp/build.gradle is:
allprojects {
apply plugin: 'groovy'
apply plugin: 'eclipse'
apply plugin: 'maven'
apply plugin: 'codenarc'
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
repositories {
// ...etc.
}
dependencies {
// ...etc.
}
task wrapper(type: Wrapper) {
gradleVersion = '2.4'
}
}
And where myapp/settings.gradle is:
include ':myapp-shared'
include ':myapp-client'
include ':myapp-server'
When I do a ./gradlew eclipse I get messages indicating that the command was successful. I then open Eclipse to import myapp as a series of individual subprojects.
Expectation based on what I'm used to seeing, historically
In previous projects that contained subprojects, I would go to Import >> Existing Projects into Workspace, where I would see this dialog:
I would then click Browse and select the project root (in this particular case, myapp). Eclipse would then auto-detect the 3 subprojects and populate them as a checked list inside the Projects component in the UI above. I would then click "Finish" and Eclipse would load the 3 subprojects into my workspace, each showing as a separate project (as it should).
What's actually happening
Instead, when I click on myapp as the root project, Eclipse just populates it as a single project, almost as if it doesn't detect that I have subprojects at all:
When I click Finish it imports a single project into my workspace, that has source folders for each of the 3 subprojects. And while that's just an annoyance, the real problem is that the classpath seems to be totally jacked up. For instance, I can add a class to myapp-shared, and then include it in a class defined inside myapp-client, and Eclipse doesn't force me to add an import statement into the client class! It's like the whole project is sharing the same package/namespace.
Can any Gradle gurus spot a defect in my Gradle setup that could be the cause of this?

This was nasty, but I figured it out. Posting the solution here in case anybody else runs into this.
Instead of a single allprojects closure, you need allprojects and subprojects closures. Not sure what is "safe" to put in either closure, but I got this working by simply declaring my repositories inside of allprojects and then putting everything else inside subprojects.
The problem was that I had previously ran gradle eclipse on the root project (before I added in the subprojects closure), and so Gradle generated the typical artifacts (e.g. .projects, .classpath, .settings/*) in the parent/root project directory. So...
Delete Gradle-Eclipse artifacts out of the root directory. Delete the project from your Eclipse workspace (but not the disk!!!). I'd even go so far as to restart Eclipse to clear out any caches if they exist.
Run gradle clean for good measure. Probably not needed.
Run gradle eclipse again.
Re-import into Eclipse, and all will be well in your kingdom once again, my friend.

Related

Gradle tasks are disabled in eclipse

I'm trying to create a .jar file for my eclipse project. Through export option, I am able to create .jar, but I want to use Gradle build task to do so. Problem is that, all tasks are disabled for this particular project only, as showing in the following image...
For another project, these Gradle tasks are working fine. See its build.gradle file...
apply plugin : 'eclipse'
apply plugin: 'java-library'
repositories {
jcenter()
mavenCentral()
}
dependencies {
compile group:"org.apache.pdfbox", name:"pdfbox", version:"2.0.6"
compile group:"org.apache.pdfbox", name:"pdfbox-tools", version:"2.0.6"
compile 'com.google.code.gson:gson:2.8.2'
compile 'org.json:json:20180130'
api 'org.apache.commons:commons-math3:3.6.1'
implementation 'com.google.guava:guava:21.0'
testImplementation 'junit:junit:4.12'
}
It's settings.gradle file contains a single line that is...
rootProject.name = 'schedule-extractor'
Can anybody suggest what I am missing here?
Have you check this buildship's issue:
https://github.com/eclipse/buildship/issues/511
The following comment resolved it for me (I was having the same problem) :
https://github.com/eclipse/buildship/issues/511#issuecomment-367392031
For those who had a similar problem in include builds - Check the file
.setting/org.eclipse.buildship.core.prefs whether the
connection.project.dir property is empty. If not, make it empty. In
my case the grayed tasks become green again.
In my case, It happened when I was using composite build concept of Gradle. According to this approach, One build could be dependent on another build. In this case, the projects may behave like this.
For example, have a look on my composite build setup in settings.gradle...
rootProject.name = 'BackendRESTServices'
includeBuild ('../Algorithms')
includeBuild ('../Utilities')
Now I won't be able to build Algorithms & Utilities projects from Gradle Tasks tab as shown in the attached image of question.

How to make Gradle add Lombok to its Project and external dependencies libraries?

I created a Java project in Eclipse Neon. I used Buildship 1.0.21 to import the project as a Gradle project and ran the wrapper and init commands to generate the build, settings and wrapper files.
The project has an empty source folder because I am trying to solve a similar problem on a more complicated project and taking the divide and conquer approach - just add Lombok dependency.
Here is my build.gradle as instructed on the lombok website:
apply plugin: 'java'
dependencies {
compileOnly "org.projectlombok:lombok:1.16.12"
}
and gradle-wrapper.properties if needed:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-bin.zip /* <--- tried other versions too */
and I ran the jar file to install it on my eclipse. If I add the jar manually via "Java Build Path" it works but I want Gradle to handle this for me. When I refresh the project nothing happens - there is no lombok jar under "Projects and External Dependencies" and code relying on lombok will give errors.
There is another project I have which does have it there and I don't know what I did differently but I know it's possible.
I managed to solve this after trial and error. The build.gradle file must add the jcenter repository:
repositories {
jcenter()
}
Why this is the case and why this is not mentioned anywhere I don't know. But for now this is what works.

Refresh (Eclipse-)Project before compileJava in Gradle

I am currently try to build my Eclipse projects using Gradle.
My build.gradle looks like:
apply plugin: 'java'
dependencies{ // some libs }
task a{ // do stuff with .classpath file }
compileJava.dependsOn a
Because I change some folders in the .classpath it can't find them when the compiler works.
If I try to do:
gradle a
(and refresh project in eclipse manually after the task is executed)
gradle build [in this case without the compileJava.dependsOn a]
everything work fine.
Is there an option to refresh to project manually in the build script?
Thanks!

Gradle dependency sources not appearing in Eclipse for the War Plugin

I am working on a Java web project that uses Gradle (version 2.1) as the build dependency tool. I use Eclipse Luna as my IDE. My OS is Mac 10.9 (Mavericks).
This is my build.gradle file (very basic and stripped down for ease of illustration):
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
sourceCompatibility = 1.8
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
compile group: 'com.google.inject', name: 'guice', version: '3.0'
}
So just one dependency, Guice. I will generate my Eclipse classpath and project files using gradle cleanEclipse eclipse. Then I will import an existing project into my workspace. I like being able to view the source code of my dependencies in my Eclipse projects, so I will open a Guice class, such as com.google.inject.Injector, using CMD-SHIFT-T. And voila, the source code of that file will appear.
But I working on a web project, so I need to be able to build a WAR file instead of a JAR file. Therefore, I am going to apply the Gradle War Plugin by replacing apply plugin: 'java' with apply plugin: 'war'. Then I rerun gradle cleanEclipse eclipse and reopen my project.
Now, instead of seeing the source code when I open up Injector, I will see the bytecode viewer with the Attach Source button. Anyone have any ideas whether it's something I'm forgetting in my build.gradle file or if it could be a bug in Gradle/Eclipse?
Note that I am not using the Gradle Integration for Eclipse Plugin because I wish to pinpoint the root cause of this issue without adding an extra layer of complexity to it. I have also checked other SOF questions about Attach Source issue with Gradle and Eclispe, such as how to tell gradle to download all the source jars and Why is Eclipse not attaching 3rd party libs source files to a WTP-faceted Gradle project?, but to no avail.

Writing a buildSrc Gradle plugin that can be published

I'm writing a custom Gradle plugin for my company to assist with integration tests of our product. My team wants to have the plugin be built with and used in the main product build (like a 'buildSrc' plugin would), but also need the plugin to be published as an artifact for other teams to use in integration with our product.
If I try and include it as a standalone plugin in the settings.gradle file and then also include it in the buildscript as a dependency, it obviously does not work because the buildscript block is interpreted first.
I also tried running another build from within the buildscript like so:
buildscript {
def connection = GradleConnector.newConnector()
.forProjectDirectory(file("${project.projectDir}/theplugin"))
.connect()
try {
connection.newBuild()
.forTasks('clean', 'build', 'install')
.run()
} finally {
connection.close()
}
repositories {
mavenLocal()
...
}
dependencies {
classpath 'com.company.product.gradle.theplugin'
}
}
This causes the plugin to be built and placed in the local Maven repo, but then the initial Gradle build fails directly afterward because it can't resolve the newly built archive. If I run it again, it works. I don't understand this behavior.
I'm probably going down a rabbit hole with this approach. Is there a way to make this work and in a less 'hacky' way?
I discovered a hacky way to accomplish this: symlink the plugins to the buildSrc (on *nix at least).
project directory
project/
buildSrc/ -> gradle_plugins/
gradle_plugins/
pluginA/
pluginB/
...
build.gradle
settings.gradle
...
build.gradle
settings.gradle
project/settings.gradle
include 'gradle_plugins:pluginA'
include 'gradle_plugins:pluginB'
...
project/gradle_plugins/settings.gradle
include 'pluginA'
include 'pluginB'
...
project/gradle_plugins/build.gradle
...
rootProject.dependencies {
runtime project(path)
}
...
The way I'm solving this is the following:
Regular multi project build with buildSrc/myPlugin/.. Within my build process I call ./gradlew -b buildSrc/myPlugin/build.gradle uploadArchives (or whichever task you use to publish your maven artifact).
Due to the "official" hack of having to add the gradle plugin to the runtime dependencies of the root project this step would fail. So I surround it with a try catch. I feel that is not perfect but it seems to work.