Buildship - Having other Eclipse projects as dependencies - eclipse

I have three eclipse projects (Project A, Project B, and Project C) in my workspace. Project B and C depend on Project A.
In my build.gradle file, I've set up the dependencies in B and C to refer to A:
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
compile('com.example:projectA:1.0')
}
However, when I right click and select Gradle->Refresh Gradle Project on Project B or C, it states that it is unable to resolve the projectA dependency.
I'm using Mars 4.5.2 and Buildship version 1.0.20. I understand that Buildship 2.0 once released will provide support such that it can refer to other eclipse projects as dependencies. In the interim though, how do I install project A into the repo and refer to it in project B and C? I do not see an install option for project A in the Buildship Gradle Tasks.

You've added a dependency using a GAV (group-artifact-version): com.example:projectA:1.0.
When you declare a dependency in gradle using a GAV, gradle assumes that it should go look for that dependency in all the available Maven or Ivy repositories that it knows about. I presume that the reason it can't resolve the GAV, is that you never published project A to any repository where your build is searching.
You have two ways out:
Publish project A's output (jar files) to a Maven repo. You would need to apply the Maven publishing plugin. For example, you could publish to your local repo using "gradle publishToMavenLocal".
Declare the dependency as a Project dependency, and keep your projects as sub-project of the same parent project.
You'd declare the dependency as compile project(':projectA')
The latter is probably a lot easier to work with.
BTW, Buildship itself probably has little to do with this issue, rather it's a general problem of using dependency tracking build systems like Gradle or Maven. I remember seeing some reference to how Gradle would solve this problem better in 3.0 and up, but I can't seem to find the link at the moment.

Related

With the gradle plugin in Eclipse, how can I get project dependencies like maven?

I'm looking into migrating some of our ancient maven projects over to gradle (so shiny). Things are looking pretty good however I'm unable to get Eclipse/Gradle to adjust the project dependencies appropriately when I have 2 projects checked out. I'm hoping to use a repo for standard jar dependencies but be able to depend directly on a project if it is checked out.
Let's say ProjectB depends on ProjectA. As far as I understand the Eclipse/Maven plugin, it is able to a:
Interrogate the maven dependency for ProjectA and understand its group/artifact/version tuple.
Look through ProjectA eclipse project (if imported) to see if has the same group/artifact/version.
Replace the jar dependency with a project dependency.
This is a powerful feature because it means that a developer does not need to import ProjectA when they are working on ProjectB -- they just get it from the repo. But if they do have it imported, they can make a refactor to ProjectA in Eclipse and it will automagically refactor the dependent code in ProjectB.
How can I get eclipse/gradle to adjust the build-path so that there is a project dependency when available otherwise use the jar?
Things I've looked into:
Gradle "multi-projects" but our code isn't in a hierarchy like that.
Gradle includeFlat but this isn't some simple single directory structure.
resolutionStrategy.dependencySubstitution but I couldn't seem to get it to work. I doubt that findProject(...) is able to find a project that is loaded into Eclipse to it can link the 2 projects together in the classpath.
composite builds seem to use some of the language I'm looking for but it is about importing a build into another build.
Anyone else figured this out? Thanks much in advance.

Do dependencies need to be added through both the Eclipse GUI and the Gradle configuration files?

Two Gradle Git projects need to be created, within the same repository, using the Eclipse IDE. Project A depends upon a third-party library (a JAR, source code, Javadoc and natives) and project B depends upon project A.
Without Gradle, both projects would be created and Git would be enabled with Project Explorer > [Project Name] > Team > Share Project. Then, dependencies would be added via Project Explorer > [Project Name] > Build Path > Configure Build Path, followed by Projects > Add and Libraries > Add External JARs (which would also allow the specification of the locations of related source code, Javadoc and natives). This would enable automatic code completion of Project A from Project B as well as source code and Javadoc integration, within Eclipse.
With Gradle, should the settings.gradle or build.gradle files be manually edited, without adding dependencies through the Eclipse GUI, or must both be used simultaneously? Additionally,how does this effect which hidden files should be indexed by Git (.project, .classpath, .settings, .gradle)?
How is this setup through Eclipse and Gradle?
When you use a build-tool like Gradle (or maven), it is kind of assumed that the build-tool is in charge of configuring stuff like project dependencies and classpaths.
This kind of conflicts with the Eclipse UI which is kind of built to allow you to manage classpath / dependencies via its own ui.
But the Eclipse UI only controls what eclipse uses as the classpath when the Eclipse JDT compiler compiles your code... inside Eclipse.
So if you change things that way, then Gradle will not know about these dependencies and the build won't work.
Yep, this is definitely confusing :-)
The proper thing to do is manage your dependencies and project configuration entirely through gradle. So that means editing the build.gradle and settings.gradle.
The tools (BuildShip or STS Gradle Tools) provide a 'bridge' to try and configure Eclipse projects in conformance with your build.
E.g they may offer a 'Update Project' or 'Refresh Dependencies' command in project context menu.
Even if you don't use Gradle tooling, this kind of holds true. You then would use Gradle's 'ecplise' plugin and run a command like
gradle cleanEclipse eclipse
To generate the eclipse project config from the build config. Then import the project into Eclipse as configured by gradle. Also in this case, it would be a bad idea to use Eclipse UI to make changes to the buildpath since ultimately it has the same issue, changes you make to those generated files may make things compile inside Eclipse, but Gradle doesn't know you changed anything. And the next time you run gradle cleanEclipse eclipse your changes are also blown away.
As to your specific questions:
should the settings.gradle or build.gradle files be manually edited ...
Yes.
... without adding dependencies through the Eclipse GUI ...
Yes.
... or must both be used simultaneously?
No, only configure things in gradle. Then 'synch it up' to eclipse with some tool (BuildShip / STS Gradle / gradle cleanEclipse eclipse)
How does this effect which hidden files should be indexed by Git (.project, .classpath, .settings, .gradle)?
General rule of thumb. Only index the stuff that defines gradle's behaviour (there may be some exceptions, but in general try to minimize them only violate this rule if you have a good reason).
So specifically don't put in git these 'eclipse metadata'
.settings
.project
.classpath
Do put in git: the gradle wrapper and its properties file.
Gradle also has a .gradle folder. It belongs to gradle, not eclipse, buts is caches and things which are 'transient'. You don't want those in git either.

Gradle + Buildship - Switch dependency between JAR and projects

I'm having some trouble configuring Buildship for Eclipse the way I want. I currently have > 50 projects always open in Eclipse, but I want to move to having only the projects I am actively working on in Eclipse, and the other projects would use a Maven repository to resolve their dependency.
Lets say ProjectA (which contains a main) depends on ProjectB (a library project). If ProjectB is opened in Eclipse, I would like ProjectA to use ProjectB directly. A change in the code in ProjectB would be noticeable when running ProjectA. However, if ProjectB is closed, I would like ProjectA to use the ProjectB's JAR located in the Maven repository mentioned in the build.gradle file.
The behavior that I am talking about is detailed here.
Is there a way to do that using Buildship? Or should I use another Gradle Eclipse plugin?
There's a new composite build support feature added in Gradle 3.1. This feature is a game changer and makes it simple to work on more than one project at once.
You can use dependency substitution rules to swap out repository dependencies with local project dependencies.
If each project is within it's own separate git/subversion repository you can use prezi pride to manage the 'pride' of projects. You could import the (dynamically generated) multi module build into buildship.
If you wanted to use the eclipse plugin instead of buildship you use the whenMerged or withXml hooks to tweak the generated .classpath files to point to the projects within your workspace (note eclipse will now build differently to gradle command line).
For the sake of completion, I ended up going with the dependency substitution as suggested by Lance Java. This approach has the following advantages:
Does not require a third party software.
Is IDE independent. We're not tinkering with the .classpath file directly, we let the Eclipse plugin (or any other IDE plugin) handle this.
Other plugins can access the actual dependency we want to use.
However, there are some gotchas with that approach:
Dependency substitution cannot be done inside a task. It needs to be done either in the build.gradle file or in a method that is called from the build.gradle file.
You need to refresh the workspace.

How do I use a local gradle project as a dependency for another local gradle project in Eclipse?

This worked fine using Maven. Project A would depend on Project B and when I loaded up both Project A and Project B then Project A would use the locally built jar for Project B instead of depending on the jar pulled from Nexus.
All my projects use Gradle now and I can't figure out how to get them to see each other.
If it is just a simple Eclipse Project A depends on Project B, then this simple solution is what worked for me (I had to read for so long to figure this out! Why wasn't it obvious?)
Project B is its own Gradle project and is not necessarily aware of other projects - you don't have to do anything special for Project B
Project A:
settings.gradle
include 'Project B'
project (':Project B').projectDir = new File(settingsDir, "../Project B")
build.gradle
dependencies {
compile project (':Project B')
}
Save the two, and do an Eclipse -> Gradle -> Refresh Dependencies, and you will now see Project B as an actual Project Dependency in the Gradle Dependencies of Project A (I had to use dashes instead of spaces since Eclipse wouldn't let me have spaces in my Gradle projects' names).
Note: if building these projects on a remote server, make sure that you are either checking these two projects into the same source control repository or make sure that they end up in the same place relative to each other the way they are in Eclipse.
Look in the Gradle User Guide, at Chapter 51, "Dependency Management". See if section 51.4.3, "Project dependencies" does what you need.

Eclipse can't resolve transitive dependency projects?

In a Java project in Eclipse, I am trying to debug project A.
Project A has a dependency on B.jar, normally B.jar comes from my .m2/repository.
but now I want to make some temp changes to B's code, and have it reflected in A,
so I directly edit the source code in B project in eclipse, and set B as a dependency project in A's build path. Additionally, both A and B refer to C.jar as their dependencies.
This builds A fine, but when it is run, A's classpath contains 2 copies of all the classes and resources in C.jar. this creates a problem for those hibernate hbm.xml mapping files in C.jar and I got errors saying duplicate mapping for...
This looks to be a defect in eclipse, in that it lacks the resolution ability as maven posseses. is there a way to work around this? (apart from building B and installing to .m2 instead of having it as a dependency project)
Thanks
You mentioned "[setting] B as a dependency project in A's build path" - do you mean editing eclipse's build path or editing the project's POM? I'm guessing the former, in which case make sure that you have the latest version of the m2eclipse plugin installed and that both projects A & B are Maven eclipse projects. If it is set up correctly then your projects should look have an 'M' on their project icons, and the icons of any workspace dependencies should look like folders.