How to setup multi-project IntelliJ workspace with Gradle? - gradle

Hello I am working on using Gradle to build a few services. I tend to have seperate repositories for each "code package" i.e. library or service.
In IntelliJ, my setup tends to be the following:
- IntelliJ Workspace
-- Service A
--- pom.xml
-- Service B
--- pom.xml
-- Library A
--- pom.xml
-- Library B
--- pom.xml
Service A & B both depend on Library A & B. This works great, within a single IntelliJ Workspace I can modify Library A and B and startup the services and all is well.
I know you can do composite builds and multi-module builds with Gradle but like I said all the 4 modules above are seperate repositories so this won't work well.
Will IntelliJ support a similar setup as above with Gradle where it recongizes that Library A & B is the library that Service A & B depend on? Or does everyone do a manual publish to Maven local for this consistently?
Thanks!

Rephrasing your question -
there are 3 separate gradle projects service1, lib1, lib2
service1 depends on lib1 and lib2
what is expected is
for local development - where source for all 3 projects locally exists - use the local code build
refer to the repository artifacts if local source does not exist
Assuming a simple folder structure like this.
app-code
- service1
- lib1
- lib2
service1 - settings.gradle
rootProject.name = 'service1'
include ':lib1'
project(':lib1').projectDir = new File('../lib1')
include ':lib2'
project(':lib2').projectDir = new File('../lib2')
service1 - build.gradle
dependencies {
implementation (project(':lib1').projectDir.exists() ? project(':lib1') : 'com.lib1:lib1:1.0.0')
implementation (project(':lib2').projectDir.exists() ? project(':lib2') : 'com.lib2:lib2:1.0.0')
}
how intellij import looks

Related

Two modules cannot share the same content root, Handle common gradle subproject dependency on intellij IDEA

I'm trying to handle a microservice based project in Intellijn IDEA ultimate, I've imported multiple gradle projects(spring based microservices) as Intellij modules.
My projects are A, B, C, the project B and C contain project A as a common subproject dependecy.
All three project are currently imported as modules inside intellij project.
Project B setting.gradle
rootProject.name = 'B'
include ":A"
project(":A").projectDir = file("../../A")
Project B build.gradle
dependencies {
...
implementation project(':A')
...
}
Project C setting.gradle
rootProject.name = 'C'
include ":A"
project(":A").projectDir = file("../../A")
Project C build.gradle
dependencies {
...
implementation project(':A')
...
}
Every time I open the Project setting menu (File -> Project Structure) and I try to change anything(e.g. add/edit/remove a module) i get the following error:
Content root 'path/to/module/A/src/main' is defined for modules B.A.main and C.A.main. Two modules cannot share the same content root
I've tried deleteing the A module dependency for B and C inside the Modules tab inside Project strcuture tab, but all three projects are imported via gradle so it did not work
Is there a way to tell Intellij to import both B and C project without Intellij to go mad about it?

Gradle composite build throwing "Failed to get Gradle name for :module"

We've a collection of libraries developed by different teams and individually pushed to different Git repositories. To minimize the hassle of publishing to local Maven repositories or publishing snapshot versions, we've put together a root project to include all those libraries with Gradle's dependencies substitutions.
The structure is as follows:
- root (Git-root)
...
- modules
- module-a (Git-module-a)
- a-core
- build.gradle.kts
- a-data
- build.gradle.kts
- settings.gradle.kts
- module-b (Git-module-b)
- b-core
- build.gradle.kts
- b-data
- build.gradle.kts
- settings.gradle.kts
- settings.gradle.kts
- settings.gradle.kts
It's a bit confusing but module-a and module-b are included as git submodules inside a modules folder of the root project.
The Gradle files are as follow:
settings.gradle.kts
rootProject.name = "project-root"
includeBuild("modules")
modules/settings.gradle.kts
rootProject.name = "modules"
includeBuild("module-a")
includeBuild("module-b")
modules/module-a/settings.gradle.kts
rootProject.name = "module-a"
include("a-core")
include("a-data")
modules/module-b/settings.gradle.kts
rootProject.name = "module-b"
include("b-core")
include("b-data")
Just to illustrate the reason for this, lets say that the module-b:b-core depends on the module-a:a-core library.
The problem is that when I run this build it comes back with the following message:
Multiple build operations failed.
Failed to get Gradle name for :a-core
Failed to get Gradle name for :a-data
Failed to get Gradle name for :b-core
Failed to get Gradle name for :b-data
I don't know if what I'm trying to achieve is possible, but I couldn't find anything in the documentation. It looks like we're always very close to what we desire, but it's almost impossible to get there.
Do you guys know what I'm missing?
Error messsages come from AGP ModelBuilder.getBuildeName()
The reason is that most "bottom" projects in composite build ("a-core", "a-data", "b-core" and "b-data") have gradle.rootProject.parent set to "topmost" project ("project-root"), instead of their immediate parents ("module-a" and "module-b").
You can check it putting
println("${project.name} parent is ${project.gradle.parent?.rootProject?.name}")
in build.gradle.kts of all the projects and running sync
It whether Gradle or AGP problem, depending on is such a root behavior correct or a gradle bug.
I have created the issue about this case in gradle project. Will look what gradle team answer :)
As temporary solution add includeBuild("a-core") and other bottom level projects in modules/settings.gradle.kts. If still will got error, try add it to the topmost "project-root" settings.gradle.kts instead.

Gradle test library in multi module project

I want to create a library that other modules in my project can depend on, but only for tests. I've read the Gradle documentation extensively and couldn't find how to do it. This is my project structure:
gradle-example:
app:
src/main/kotlin ...
src/test/kotlin <- this is supposed to use 'com.example.SomeTestUtil'
testlib:
src/test/kotlin/com.example.SomeTestUtil
settings.gradle.kts:
rootProject.name = "gradle-example"
include("app")
include("testlib")
In the app module I tried adding
dependencies {
testImplementation(project(:testlib"))
}
But I get compilation error trying to import the SomeTestUtil in the app module test classes.
What is the correct way to declare dependency on a module in the same project that allows to use test sources in test code?
To clarify, we want to create a library that can only be used by other modules under src/test and not src/main.
Apparently this can be done by using the https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures
they can see the main source set classes
test sources can see the test fixtures classes
So changes to the example in the question are:
changing the src/test to src/testFixtures
declaring the dependency as testImplementation(testFixtures(project(":testlib")))
Adding java-test-fixtures plugin to the build.gradle.kts for the testlib module

SonarQube multi-module and multi-sub-folder project configuration

I have a multi-module sbt project with the following structure:
parent/
child1/
src/
group/
child1/
src/
child2/
src/
I need to configure SonarQube to scan all of the modules in (possibly) nested folders.
Note: I have child1 and group/child1 modules, which makes "flattening" all modules not possible.
In build.sbt I use names like:
val `group-child1` = (project in (file("group/child1")))
val `child1` = (project in (file("child1")))
With a flat multi-module structure it would be easy to configure, (but not for my case) :
sonar.modules=child1,child2,...
sonar.sources=src/main
sonar.tests=src/test
But I need a configuration for deeper nested structure.

Sonar Report + Multi module maven + Jacoco plugin

I am new to Sonar.
I have multi-module maven project.
please find the Project structure below
-Parent
| -Module A
|
-pom.xml (Module A)
| -Module B
|
-pom.xml (Module B)
| -Module C
| |
| -pom.xml (Module C)
|
--pom.xml (parent pom)
Note : (Module C is shared module in Module A/ Module B - means Internally module C will the part of into Module A , Module B library)
Based on the Project requirement we have these structure.
Module A - works for external users.
Module B - works for internalusers.
Module C -common b/w both the module.
I am trying to create single sonar report for both the module, but I am not able to integrate all the module junit report (Module A and Module B report)
into single report.I followed couple of example to combine the muti-module maven porject but nothing works.
similar issue1 similar issue2
github-example (reference given in sonar)
I had similiar problem with over 40 modules which were even nested. What you have to do is to create whole sonar configuration in parent pom.
<sonar.host.url>set url here (default is localhost)</sonar.host.url>
<sonar.login>user for host url (default admin)</sonar.login>
<sonar.password>password for host url (default is admin)</sonar.password>
<sonar.projectName>optional name for whole project in sonar view</sonar.projectName>
<sonar.projectDescription>optional project description for sonar view</sonar.projectDescription>
<sonar.projectBaseDir>like name says you can set project base dir, if you have parent pom as a separate module then you can type ".." to set main directory with all modules</sonar.projectBaseDir>
Set properly all modules which will be analysed separately for the whole project:
<sonar.modules>module1, module2, module3</sonar.modules>
Configure each one of them properly:
<module1.sonar.projectName>module1</module1.sonar.projectName>
<module1.sonar.projectBaseDir>module1/</module1.sonar.projectBaseDir>
<module1.sonar.sources>optionally set sources to proper directory for example src/main/java</module1.sonar.sources>
<!-- similiar for other 2 projects -->
That way all junit reports will be used per module but it will be listed in single project with modules. That way you will be able to see reports per module and per whole single project.
It's a good practise to check results after adding every single module. In case of failure simply check error in console and fix the problem.
I am able to achieve Integration test coverage using sonar with Jococo plugin.
To run the Sonar in local, i was facing the issue with SCM error in sonar.
Every time it was failing in the in sonar report creation.
For resolving the issue in local you need to disable the SCM configuration in sonar.
login in local sonar as Admin - admin/admin (default username/password)
Now under setting we have SCM tab - disable the SCM Senor and save the SCM Setting.
Now in Dashboard --> Configure widgets .Search "Integration Tests Coverage"
Now add widget into your Project Dashboard.
Follow the same configuration in your pom.xml as given in the link.
https://github.com/SonarSource/sonar-examples/tree/master/projects/languages/java/code-coverage/combined%20ut-it/combined-ut-it-multimodule-maven-jacoco

Resources