For several months we've been using Buildship 1.X plus some manual .launch/tasks to build our Eclipse/WTP config files per development environment. I am currently attempting to migrate to using Buildship 2 (which I'm hoping will rid us of the need for the manual bits.)
However, when I import the projects (which have 0 eclipse config files at this point) via the buildship/gradle import, the subprojects are included via 'Libraries' rather than as 'Projects' (see image below.) In contrast, if I use gradle's eclipse task to generate the eclipse config files (i.e. .classpath) then the configuration ends up as I would expect it to be. Is this a current limitation of Buildship, or do I need to do something differently in my gradle files to coerce Buildship to bring them in as Projects?
Ultimately I don't know that I should care about this difference, but I do know that I'm getting compiler errors saying classes from the subprojects are missing from the classpath. As long as I can fix that issue, I'm perfectly happy.
Potentially helpful info
settings.gradle:
rootProject.name = 'projectroot'
include 'Project2.0'
project(':Project2.0').name = 'projectx'
include 'the-platform'
include 'the-platform:central-repo:central-repo-common'
include 'the-platform:central-repo:central-repo-model'
include 'the-platform:central-repo:central-repo-persist'
include 'the-platform:central-repo:central-repo-service'
Project2.0/build.gradle (snippet):
dependencies {
...
compile project(':the-platform:central-repo:central-repo-common')
compile project(':the-platform:central-repo:central-repo-model')
compile project(':the-platform:central-repo:central-repo-persist')
compile project(':the-platform:central-repo:central-repo-service')
...
}
Hmmm, nevermind. My intuition about the difference between the behavior of buildship vs the eclipse plugin to gradle being responsible for my classpath issues was incorrect. Something else (as yet unexplained) must've been the issue as it is working correctly now.
Related
I use both Intellij IDEA (2018.3.5) & Eclipse IDEs, but I prefer Intellij. I have a maven based Java project with multiple poms. I added some dependencies to one of the pom files. I need to find out if there are any dependency conflicts which could prevent the build from running when its deployed, and then exclude them. I tried the steps given below to find conflicts which could cause problems. Are they enough or do I need to do more ?
Check if there are any compile time dependency conflicts with mvn clean install -DskipTests. Build was successful with no errors.
Check if Intellij shows no problems under File > Project Structure > Problems. There are no problems.
I also saw the dependency tree with mvn dependency:tree -Dverbose. It has a lot of "omitted for duplicate" and "omitted for conflict with" items, but the build was successful. I don't see any errors though. Does this mean that everything is okay or do I have to do something more about these conflicts ?
The best way to tell if everything is fine with your application is to have good tests.
However normally one doesn't exclude transitive dependencies from project's <dependency> libraries. Doing it can potentially break the dependency in a subtle and hard to notice way. It's usually safer to remove the whole <dependency>.
There are few scenario when one should use <exclude>:
Dealing with incompatible transitive dependencies between different libraries e.g. A requires library C-1.0 but library B requires library C-2.0 while C-1.0 and C-2.0 can't coexist on the classpath.
Having transitive dependencies already provided by system e.g. deploying to Tomcat with additional JARs in the TOMCAT_HOME/lib directory.
If you decide to exclude a dependency it's important that you check the final artifact because sometimes plugins do weird things e.g. there were versions of maven-assembly-plugin affected by a bug that resulted in different dependencies being resolved during shaded JAR creation than maven-dependency-plugin used for compilation.
I have this small set of libraries and app:
forge-base - java project (Intellij IDEA project)
forge-android - android library project, depends on forge-base (AS project)
forge-android-skeleton - sample android app, depends on forge-android (AS project)
During the initial development I used structure with project dependencies like:
settings.gradle:
...
include ':forge-base'
project(':forge-base').projectDir=new File("$settingsDir/../forge/base")
...
and then in build.gradle:
compile project(':forge-base')
This worked like a charm but later I needed to publish the libs on maven repo and dependencies had to be changed like:
build.gradle:
compile 'com.bolyartech.forge:forge-base:2.0-SNAPSHOT'
The problem that I am facing now is that I am trying to do some major refactoring in all the 3 projects and I need the old deps structure in order easily to confirm the consistency of the projects, e.g. to build just the skeleton app and all the recursive recompile/building to take place automatically (as it does when a lib project is referenced with compile project(':forge-base')). If I use the 'new' structure with publishing to the (local) maven I have to publish the lib each time (with incremented version) I change something in it in order changes to be visible by the other two projects.
What (is there) is the usual/canonical why to handle situations like this?
Is there an easy way to switch between the two 'modes', e.g. 'internal' / 'external' dependencies?
It turns out it is pretty easy to do it. You can use different dependencies for the different build types, i.e. debug/release so for example for my forge-android-skeleton project now I have the following:
in settings.gradle:
include ':app'
include ':forge-base' project(':forge-base').projectDir=new
File("$settingsDir/../../../forge/base")
include ':forge-android' project(':forge-android').projectDir=new
File("$settingsDir/../../../forge-android/forge-android")
in app/build.gradle:
...
releaseCompile ('com.bolyartech.forge:forge-android:2.7-SNAPSHOT')
debugCompile project(':forge-android')
...
Please note that in the settings.gradle you need to have all the dependencies back to the bottom otherwise it will not work (that is the reason forge-base is defined there even not excplicitly used).
You can also define yet another build type like direct-deps and use it in case you don't like to mess with debug/release types.
Please note that in case you are using different IDEs for some of the projects (like in my case IDEA and AS) probably it will be good idea to ensure that both are using same (version of) gradle otherwise unexpected problems may occur.
I have several gradle projects in my eclipse workspace. For the sake of simplicity I'm only really interested in 2 of them, let's just use A and B for this.
So the problem I'm having is that Project A has an included dependency on JBoss, which pulls in javax validation-api 1.0.0.GA, and Project B has a dependency on javax validation-api 1.1.0.Final. Since Gradle itself resolves the conflict by using the newer library first, B is happy when built by gradle. But Eclipse itself includes errors which are very distracting while editing.
The correct version of the validation-api jar ends up in B's class path but the problem is that the Gradle IDE plugin changes the project(':A') dependency to a project reference, and Eclipse seems to give the project reference precedence over the external jar. So the old jar is preferred by extension.
I tried adding { exclude module: 'validation-api' } in B's build.gradle for the dependency on A which works according to the output of 'gradle dependencies', however since Eclipse just gets as far as making it a project reference, it won't exclude the jar and the problem remains.
Also per this question I tried adding { transitive = false } and the same thing happens. I don't think even the hack posed there would work for me since the .classpath contains a single reference to the Gradle container so there's nothing to remove.
I've managed to get around this by explicitly including a reference to the correct version of the jar from my gradle cache and then moving it above the Gradle Classpath Container so that eclipse sees that version first.
My question is: Is there a better/more generic way to do this? Preferably one that I can commit to source control without breaking other people's builds or requiring them to manually modify paths or properties somewhere? There is another project with what appears to be a similar issue so something I can fix in the build.gradle file would be awesome.
Worst case scenario, I could probably switch to IntelliJ if that behaves itself better than the Eclipse-Gradle integration?
These kind of transitive dependency issues are long-standing problem with Gradle Eclipse integration (both in STS tooling and also commandline generated .classpath metadata from Gradle's Eclipse plugin. The problem is the way that Eclipse computes transitive classpaths.
Only recently we found a reasonable solution to this problem. Actually there are now two solutions, one better than the other but depending on your situation you might want to use either of them.
The first solution is a bug fix that changes the classpath order of project dependencies so that they are no longer 'preferred' over jar dependencies PR-74. To get this fix you may need to install gradle tooling from a snapshot update site because the fix went in after 3.6.3.
This solution doesn't fix the real problem (you still have the 'wrong' stuff on the classpath) but just makes it less likely to cause real problem in your projects.
The second solution is to enable use of the 'Custom Tooling API model' PR-55 introduced in STS 3.6.3. This is a bit experimental and only works for recent version of Gradle, at least 1.12 but probably better to use 2.x. It also only works for projects that have 'Dependency management' enabled (if not enabled you are using the .classpath generated by Gradle's eclipse plugin which has the same 'broken' classpath issues as the STS tooling).
The 'custom tooling model' is really the better solution in principle as it fixes the way gradle classpath get mapped to eclipse projects so that project dependencies are no longer exported and each project gets its own classpath considering dependencies conflict resolution.
To enable this go to "Window >> Preferences >> Gradle" and enable checkbox "Use Custom Tooling Model".
Is there a way to configure Gradle to shorten the folder names of its cached dependencies?
From the Gradle user guide it does not appear its possible, but figured to check with others.
My use case is because using the 'idea' Gradle plugin it helps with settings up Module dependencies. A problem arises when the Module classpath becomes 'too long' for cmd.exe (I'm not trying to discuss these limitations). Idea loads the project just fine, but its unable to run my program since it states the classpath is too long.
Since this is not an Idea problem, I figured it would be lovely if there was a way Gradle could cache deps using shorter folder names.
Example
from: C:\.gradle\caches\modules-2\files-2\com.google.application\application\2.0\SVABNSAVSASAMNVSMAVSASN\application.jar
Options 1 To: C:\.gradle\caches\modules-2\files-2\c.g.a\a\2.0\SVABNSAVSASAMNVSMAVSASN\application.jar
Options 2 To: C:\.gradle\caches\modules-2\files-2\co.go.ap\ap\2.0\[tinyurl-equivalent]\application.jar
Options 3 To: C:\.g\c\m-2\f-2\c.g.a\a\2.0\[tinyurl-equivalent]\application.jar
Options 4 To: C:\.g\[tinyurl-equivalent]\application.jar
I do know that Idea does recognize the long classpath and prompts to enabled Dynamic Classpaths, but this has been known to cause other problems (some invoked apps cannot see the full classpath) and therefore I'd like to avoid this Idea option.
As of Gradle 2.1, shortening dependency cache paths isn't supported. There are ideas around symlinking or copying dependencies into the project, but nothing concrete has materialized.
We are looking to revamp our Java build process on Eclipse. Currently we use Gradle! As a part of that effort we are looking at whether we are using Gradle in the best possible way. We use the Eclipse plugin for Gradle and declare our dependencies with compile. Unfortunately this adds a ton of transient dependencies with our generated Eclipse projects which is not desirable. These extra dependencies are only valid at runtime.
So, is there a way to declare a dependency ONCE in Gradle and have its compile dependency set to the first level of dependency and its runtime dependency set to the first level plus transient dependencies?
Currently we use the #jar syntax with compile which gives us the first level dependency for compile, but we still have to declare that dependency again for runtime. Not ideal because we have two places to go in order to update a dependency.
Is there a better way?
I assume you mean transitive dependencies.
If you only want direct dependencies to appear on Gradle's compile class path, your current solution seems reasonable. (In the future we want to have a more accurate compile class path out-of-the-box.) Potential improvements are to make the compile configuration non-transitive (rather than using #jar) or to write a plugin that provides a custom dependency syntax, thereby making the duplication between compile and runtime dependencies go away.
However, this won't help you with Eclipse, as Eclipse has no notion of separate compile and runtime class paths. The only way out is to make run configurations responsible for providing the runtime class path, but this might be difficult to set up (e.g. run configurations are often created on-the-fly), and Gradle doesn't have any out-of-the-box support for this. You could use the generic XML hooks of Gradle's Eclipse plugin to generate run configurations, but I'm not sure if the Eclipse Gradle integration would pick them up.
Due to these difficulties, most Eclipse developers put all runtime dependencies on the Eclipse project class path (regardless of whether they are using Gradle or not), despite the obvious disadvantages.
Our vision is that Gradle can one day act as the build engine for Eclipse. Once this happens, discrepancies between IDE and build tool (class paths, code generation, integration testing, etc.) will be a thing of the past. Gradle can already act as the build engine for NetBeans today, and soon also for IntelliJ IDEA (driven by the requirements for Android Studio).
While I certainly agree with #Peter that an overhaul of the Eclipse build process is a long-term goal, in the short term you may be able to accomplish what you want using Maven and m2eclipse. Whether the tradeoffs of moving to Maven are worth that extra control are entirely up to you.