Multiple Project Gradle Setup with Intellij - intellij-idea

I have two gradle projects. Project A includes Project B as a dependency. I have them both imported into intellij, With the same setup using maven, I could update project B and run Project A would immediately see the changes. With gradle I must run gradle build on project B and then refresh project A in intellij. Is there a trick to make this more dynamic?

If A and B were part of the same multi-project build, you could have A import B in this way:
dependencies {
compile project(':B')
}
Then, changes to B should immediately be visible to A. In other words, a change in B might cause a failed build in A as soon as IntelliJ detects that A is out of date and builds it.
However, it sounds like this is not the case, so A is actually importing B from some remote repo?
dependencies {
compile "com.stackoverflow.example:B:1.12"
}
In the later case, when Gradle (or IntelliJ) compiles project A, it actually uses the version of B which is in your local gradle cache, or towards the remote repo. Either way, Gradle won't see changes made in B until those changes are built and published to the repo.

Related

Configuring IntelliJ Platform plugin's workspace

I've been setting up the workspace for IntelliJ's plugin development. There is one issue that I'm not able to solve.
I have two plugins: A and B. The B plugin depends on A. The A plugin is provided as an install-ready zip package (I don't have the code and I don't want to add it to my project).
In the manual, I met this page. I added jars from the A plugin (extracted from the zip file) to the SDK that is use when running B plugin. Unfortunately, when the sandbox is being bootstrapped, I get the following error:
Problems found loading plugins:
Plugin "B" was not loaded: required plugin "A" not installed.
Disable B
Open plugin manager
Does it mean that plugins from the SDK are not installed automatically?
I tried to install the A plugin in the sandbox but then I got a casting exception - two different class loaders were used.
Of course, I have appropriate dependency configuration in the B.plugin.xml file:
<depends>A</depends>
My question is how should I provide the A plugin to be able to develop the B plugin? Is it possible to develop the B plugin without A's sources?
In the jars that I added to the SDK's classpath, there is a package that contains the plugin.xml file for the A plugin. This plugin is also not listed on the list of plugins.
I'm sure that both plugins are configured properly because there are no problems when I install both of them in a standalone IntelliJ instance. Additionally, I don't have any compilation errors.
After couple more hours of debugging. The A plugin is marked as not installed because in the PluginManagerCore:loadDescriptorsFromClassPath method there are no appropriate jars URLs provided. It seems that BootstrapClassLoaderUtil doesn't include all of the entries configured in the SDK.
I tried to set -Didea.additional.classpath property, but I got the class cast exception again.
Finally, I have found the solution.
The B plugin consists of other B submodules:
B.submodule-1
B.submodule-2
B.submodule-3
One of these submodules had dependencies to the A's submodule. Something like this:
B:
| B.plugin-submodule
| B.submodule-1
| A.submodule1
| A.submodule2
| B.submodule-2
| B.submodule-3
Based on the gradle setup, IntelliJ resolved all of the dependencies for all submodules. Initially, I removed Gradle dependencies and set the JDK only for the plugin submodule. It was required to do so for the others (submodule-1/2/3).

How to import a project with modules and java packages in IntelliJ?

We have a java project with several modules. We use git for versioning and want the developers to be able to chose their own IDE. So we don't push .idea and .iml files with git. This means that developers in IntelliJ needs who clones from git needs to set up the project in IntelliJ as well. However we are having some issues with setting it up. In my own project it works fine and looks like:
Proejct Module (Is this a real module?)
⤷ Module A
⤷ src
⤷ main
⤷ java
⤷ Package 1
⤷ Package 2
⤷ test
⤷ Module B
Before we added packages to the project new developers could just pull from git and open Module P in IntelliJ, then go to project structure and import module from Module A and Module B. However if they try the same thing now IntelliJ tries to make the Modules main and test from Module A.
A workaround we temporarily use for this is to open Module A and B directly as separate IntelliJ projects. If we do this IntelliJ does not try to make modules out of main and test. However this is very inconveniant for us.
How can we fix this?
It's a good approach to make your source control system "agnostic" about the IDE and not check in .idea, *.iml and equivalent things from other IDE's.
However you really need to use a build control system like maven or gradle.
In my workplace we use maven for all our java projects. It's very simple to define a pom.xml at the root level which defines your modules, and many other things.
When you import a maven project into intellij, all the relevant IntelliJ modules are automatically created for you. In essence, you only need to import the pom.xml and you're good to go.
Otherwise it will be a nightmare to import and create modules every time you check out source from git. Maven isn't perfect but I highly recommend using either maven or gradle.
To define multi-modules from the root pom.xml, make a section like this:
<modules>
<module>module-A</module>
<module>module-B</module>
</modules>
And then the pom.xml in both module A and B should define a section referring to the root pom via the <parent> tag.

How to get IntelliJ to associate Gradle sources with build.gradle?

When writing Gradle scripts for my Java project, specifically, when writing build.gradle files, IntelliJ does not recognize the Gradle API.
For instance, Gradle methods calls like apply, dependencies configure appear with a black line under them and it is not possible to navigate to method declarations, there is no auto-completion etc.
I managed to work around this by adding compile gradleApi() to the build's dependencies block. However, I don't want to have this explicit dependency in my code.
I tried editing IntelliJ's project structure and add a dependency on a Gradle library (tried gradle-core and gradle-all) to my modules, but that seems to have no effect.
Is there a way to make IntelliJ associate all build.gradle files with the Gadle sources?
I solved this problem as follows:
As mention in already posted answers, configure gradle
update gradle/wrapper/gradle-wrapper.properties file
change bin to all in distributionUrl i.e.
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
to
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
OR
[optional] If you are using old version of gradle wrapper and wanted to upgrade, then execute
./gradlew wrapper --gradle-version 6.8.3 --distribution-type all
Update gradle task (if present in build file)
wrapper {
gradleVersion = '6.8.3'
distributionType = Wrapper.DistributionType.ALL
}
Before importing the project to IntelliJ-Idea IDE, update build.gradle and add java and idea plugin to the plugins list
plugins {
id "java-library"
id "idea"
}
From a terminal, execute ./gradlew clean build idea or simply ./gradlew idea
Import project to IntelliJ idea.
Go to Preferences --> build,Execution,Deployment --> BuildTools --> Gradle
You can see
Restart IntelliJ idea IDE.
So above we have configured both of the options so choose either of them, except the specified location option. That's it.
Before
After
Autocomplete functionality as mentioned in this answer.
I had similar frustrations with Grails 3, which defines and runs a wrapper task when an app is created. Changing to the "all" zip in the wrapper properties file did not work because this kept getting changed back to the "bin" zip.
This was solved when it was understood that the "gradle-wrapper.properties" file simply stores the values from the "wrapper" task, and if this task is run after the properties are changed, they get changed right back.
This is easily fixed by setting some properties on the wrapper task:
wrapper.gradleVersion='3.2.1'
wrapper.distributionType=Wrapper.DistributionType.ALL
Now importing the project into IDEA gives you smart editing of your build.gradle.
when I choose build.gradle in IDEA and open it, IDE prompts
You can configure Gradle wrapper to use distribution with sources. It will provide IDE with Gradle API/DSL documentation.
I choose Ok, apply suggestion!
after project refreshing I am able to use code completion
before you import your project, configure it to use the customizable gradle wrapper as per the instructions here :-
https://docs.gradle.org/current/userguide/gradle_wrapper.html
add a task to your top level project like this:-
task wrapper(type: Wrapper) {
println "Wrapper gradleVersion = '2.12'"
gradleVersion = '2.12'
}
or whatever the latest version is.
make sure you can build the project from the gradle command line before you try importing into intelliJ, using the ./gradlew command, which will download and install a gradle distribution for you the first time you build.
set your java home, intelliJ home and gradle home variables in your machine and in intelliJ (mine look like this, yours may be different depending on your setup and your history of hacking around your machine...:-
(from .bashrc
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home
)
When you do import, choose the customisable gradle wrapper. if all is well, when you open the top level build.gradle for your project, you will be asked to configure sources for the gradle dsl, which will also update your gradle wrapper properties file to this:-
#Thu Mar 31 14:04:00 BST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-all.zip
.. the change being from ... bin.zip to all.zip. and that's it. This had been giving me lots of grief for a long time, but that's the way to do it. (on IntelliJ IDEA 2016.1 CE at least...)
most of this was in
Dimitry's answer too, but I couldn't get it to work using the default wrapper , it had to be the customisable wrapper.

Gradle Module Execution Order

I have a gradle project with two modules.
The first module (A) produces an archive that the second module (B) makes use of. I've defined the settings.gradle file so that A is seen before B.
At the end of A, there is an install task that is called which will make the archive available for B, however the install task won't execute until all modules build.
When I use A's build file, or set the build command -p it will still try to find dependencies for project B. I don't want to do this!
How can I set this up so that module B will wait completely for module A to finish?
I've defined the settings.gradle file so that A is seen before B.
Order doesn't matter here.
At the end of A, there is an install task that is called which will make the archive available for B
The correct way to handle this is to make the outputs of A available to B via a project dependency. In the simplest case, B's build.gradle will contain the following:
dependencies {
compile project(":A") // could be something other than 'compile'
}
When I use A's build file, or set the build command -p it will still try to find dependencies for project B.
Most likely there is a problem with one of your build scripts, namely that it does work in the configuration phase that should be done in the execution phase.
How can I set this up so that module B will wait completely for module A to finish?
There is no good way. Gradle executes a graph of tasks, not a list of projects. As long as task dependencies are correct, the former will have no drawbacks, only advantages. Often, Gradle can figure out task dependencies automatically (especially between projects).

Maven adds class files of snapshot dependencies

on my Windows machine I do have several proeject that I build with maven. At the moment they are all in SNAPSHOT-State. When I build a project that relies on one of the other projects maven always adds the class files of the other projects to the jar.
If I build the project on my CI-Server this problem does not occur. Does anyone have an idea why maven adds the class files to my jar?
I'm using maven 2.2.1
When I build a project that relies on one of the other projects maven always adds the class files of the other projects to the jar.
This is not a default behavior and, if it happens, you're somehow telling Maven to do so. If you want to hunt potential discrepancies, check the effective-pom, the effective-settings, the active-profiles using the following goals on both machines:
help:effective-pom
help:effective-settings
help:active-profiles
Also double check how Maven is invoked on the CI machine (extra command line parameter, etc).