IntelliJ / Gradle - composite build project - how to import from different module? - java

I'm new to Java and am currently trying to build a cucumber / selenium project in IntelliJ that contains two modules: A library project containing page definitions, and a test project that contains the cucumber features and step definitions that talk to those page definitions. The idea is that the page definitions are a shared resource, and the tests are specific to different projects / groups. Both modules are at the same level underneath the parent project. The build is using Gradle, and the settings.gradle file for the parent looks as follows:
rootProject.name = 'composite-builds'
includeBuild 'libraryproject'
includeBuild 'testproject'
Using Gradle includeBuild on the parent project works fine and the whole project imports. However I am having no luck using the library project in my import statements in the test project. It consistently returns me these kinds of error: java: package libraryproject.pageFactory.examplePages does not exist and is clearly not seeing the library module.
What do I need to do / add in order for the test project to recognise the library project? I did try to also add the includeBuild statement in the settings.gradle for the test project but this made no difference.
The library can be found here
Update: the real reason that I cannot see the modules from the library project is that they were held in the test folder, not main.

Go to your build.gradle file
Instead of includeBuild use dependencies{compile{project(':libraryproject')}}
Inside the Root Project of libraryproject which is in your case the composite-builds. Change includeBuild to include in the settings.gradle
rootProject.name = 'composite-builds'
include ':libraryproject'
include ':testproject'
If it is in the same root:
dependencies {
compile(
project(':libraryproject')
)
}
Subfolder:
dependencies {
compile(
project(':myFolder1:myFolder2:libraryproject')
)
}

Related

Gradle nested projects setup

How do I set up such a project structure where I have the root project called "app", "frontend" and "backend" project inside and a count of library projects inside each. Then run a build task that would give me one backend jar and a swing (for example) jar application.
Like this:
root (App)
frontend
library
main
backend
library
main
then run: gradle build and have build/.../frontend.jar and build/.../backend.jar
I did try using include inside settings.gradle but that doesn't seem to work (at least gradle projects and intellij idea do not recognise the projects inside frontend and backend). I had:
root/settings.gradle with: include 'frontend', 'backend'
root/backend/settings.gradle with: include 'library', 'main'
and the same for frontend
There are multiple ways. one way at the root settings.gradle (gradle v7.1)
rootProject.name = 'test-prj-tree'
include 'backend'
include 'frontend'
include 'library'
include 'backend:library'
findProject(':backend:library')?.name = 'backend-lib'
include 'backend:main'
findProject(':backend:main')?.name = 'backend-main'
include 'frontend:library'
findProject(':frontend:library')?.name = 'frontend-lib'
include 'frontend:main'
findProject(':frontend:main')?.name = 'frontend-main'
In modern Gradle it's possible to includeBuild, which solves the problem perfeclty:
// root/settings.gradle.kts
rootProject.name = "root"
includeBuild("backend")
includeBuild("frontend")
// root/backend/settings.gradle.kts and root/frontend/settings.gradle.kts
include(":library")
include(":main")

How is the classpath setup in a multimodule gradle project during runtime?

I'm quite new to gradle and especially multimodule gradle projects, so I have a small example project created with the following project structure
Main
*src
*tests
*build.gradle
*settings.gradle
*Subproject1
+src
+tests
+build.gradle
So when I tried to load the classes in Subproject1 from a class in the main (root) project, it can not find the class, I would have thought the root project classpath contains the subprojects classes as well.
What am I doing wrong here or any material I should go through to understand this?
current settings.gradle file,
rootProject.name = 'main'
include 'Subproject1'
You should take some time to read documentation HERE which explains the concept of multiproject builds and provides some examples on how to create dependencies between sub-projects.
The root project will not inherit classpath from the subprojects, you will have to declare explicitelly these dependencies as follows
build.gradle (root project)
dependencies {
implementation project(':Subproject1')
}

Gradle composite builds - can you have a dependency to a java sub-project from an included multi-project build?

Let's say you have 2 gradle projects. The first is a multi project with 2 java sub-projects:
rootProject
:my:subProject1
:myother:subProject2
The second gradle project is a single project that includeBuild's the root project:
secondProject
includeBuild '../rootProject'
I want to make a compile dependency of :my:subProject1 into secondProject.
So basically I want to add the following to secondProject's build.gradle file:
dependency {
compile(project(':my:subProject1'))
}
When I try to do that, it returns error: Project with path ':my:subProject1' could not be found in root project 'secondProject'
I seems like I can only resolve the dependency when I do the dependency as group:artifact:version. For example: my.root.project:subProject1:1.0.0. But why would it make me do that? Why not let me access the composite build's project hierarchy?
Only one settings.gradle should exist on the root, remove all setting.gradle files in any subfolders
Define the projects on the settings.gradle file of the root folder
include ':sub1', ':sub2', ':sub3'
Add compile project(":sub1") to your build.gradle under dependencies block:
dependencies{
compile project(":sub1")
}
This is just how these composite builds work. They basically act as if you published the other project to maven local prior to including it. so this means you need to depend on the version number of the split project.

Gradle multi project, how to deal with different rootDirs

My company is currently switching from Ant to Gradle for its Java projects, but I am stuck with a nice clean setup. Let's say I work for a company that builds websites for clients which generally use the same root libraries (core project), but have some specific code, which is put in the sub-project. Per client, we build a new sub-project, that depends on the core project. Number of clients will increase in the future.
Currently we have three projects:
A core project. This should run individually, as we want to be able to do the unit testing seperately for this.
Two sub-projects that depend on the core project, but have some own projects that are specific to the project.
I was sucessful in converting the whole ant build into a gradle build for the core project. My idea is to have all functionality and project structure in the core, and only the extra for what is actually needed in the sub-projects.
Here is a short sample of our folder structure:
-- core
- build.gradle
- settings.gradle
-- repository (our external jars used)
-- Implementation
-- source_code
-- all the core project folders
-- Projects
-- Client A
- build.gradle
- settings.gradle
-- more project specific folders
-- Client B
- build.gradle
- settings.gradle
-- more project specific folders
I use the $rootDir variable a lot. A fraction of the core's settings.gradle looks as such:
project(':CoreProjectA').projectDir = new File(rootDir, 'Implementation/Source_code/Core/coreA')
project(':CoreProjectB').projectDir = new File(rootDir, 'Implementation/Source_code/Core/CoreB')
But with many more. Also, in the core build.gradle, I refer to our repository as such:
repositories {
//All sub-projects will now refer to the same 'libs' directory
flatDir {
dirs "$rootDir/repository/lib/jaxb"
//many more dirs here
}
}
Now this all works great when I do a gradle build from the core project.
I was planning to put the next piece of code in every client's subproject build.gradle:
apply from: '../../../build.gradle'
When I run a gradle build from Client A folder, my rootDir obviously has changed, and now, all my paths cannot be found anywhere.
Is there any way to set this up in a nice clean way? So that every future sub project added can always use the same structure? Or will I have to give each sub-project its own build.gradle and settings.gradle entirely?
I know the last option could work, but it is a lot of overhead, and just doesn't seem nice and clean to me at all..
Thanks in advance!
I recently worked on a similar configuration, so let me explain me how I build the Gradle infrastructure. Since you mentioned a lot of requirements, I hope that I'll miss any of them and you can apply my scheme to your problem.
General
We actually use build systems (like Gradle) to let them take care of any dependencies (projects, modules, tasks). So why should we define a depedency in something like a filesystem hierarchy, if we can simply define it in Gradle?
I would avoid using paths as much as possible (convention over configuration) and try to stick to Gradle projects for both the build scripts and the dependencies.
Also, if you define dependencies in your core gradle.build, you should just call this gradle file, even if you only want to build a subproject. Your apply from: '../../../build.gradle' destroys the whole Gradle logic. Instead you should use something like gradle :sub1:build to only build the first subproject.
First approach (with core as root project)
Filesystem structure:
core/
build.gradle
settings.gradle
src/
...
sub1/
src/
...
build.gradle [optional]
sub2/
src/
...
build.gradle [optional]
Core settings.gradle:
include 'sub1'
include 'sub2'
Core build.gradle:
allprojects {
apply plugin: 'java'
repositories {
// define repos for all projects
}
}
subprojects {
dependencies {
// let subprojects depend on core
compile rootProject
}
}
project(':sub1') {
// define anything you want (e.g. dependencies) just for this subproject
// alternative: use build.gradle in subproject folder
}
Second approach (all projects independent)
Filesystem structure:
core/
src/
...
build.gradle [optional]
sub1/
src/
...
build.gradle [optional]
sub2/
src/
...
build.gradle [optional]
build.gradle
settings.gradle
Root settings.gradle:
include 'core'
include 'sub1'
include 'sub2'
Root 'build.gradle'
subprojects {
apply plugin: 'java'
repositories {
// define repos for all projects
}
}
configure(subprojects.findAll {it.name != 'core'}) {
dependencies {
// Add dependency on core for sub1 and sub2
compile project(':core')
}
}
project(':sub1') {
// define anything you want (e.g. dependencies) just for this subproject
// alternative: use build.gradle in subproject folder
}
This approach provides great flexibility, since every dependency logic is handled by Gradle and you'll never have to copy anything to another position. Simply change the dependency and you are fine.
Sources
Gradle Tutorial on Multi-project Builds
Question in Gradle Forum
It looks like you have extra settings.gradle inside subprojects. That makes Gradle think the sub-project is a standalone one. If you remove settings.gradle from subprojects, Gradle will look for it up the filesystem hierarchy, will find one in core project, will create correct multimodule project and all the paths should work properly.
So, just remove extra settings.gradle files and your build will work fine. Having build.gradle in subprojects is perfectly fine.
I want to thank Nikita and especially lukegv for his detailed answer, but I went with a different approach ultimately.
I didn't want to have one main gradle build and extend it each time we have a new project. Also, I wanted to keep it simple and logical for my colleagues if they want to create a build for one of the projects.
Therefor, I kept the structure I had as described above. In the root gradle.settings but changed the
project(':CoreProjectA').projectDir = new File(rootDir, 'Implementation/Source_code/Core/coreA')
project(':CoreProjectB').projectDir = new File(rootDir, 'Implementation/Source_code/Core/CoreB')
into:
project(':CoreProjectA').projectDir = new File(customRootDir, 'Implementation/Source_code/Core/coreA')
project(':CoreProjectB').projectDir = new File(customRootDir, 'Implementation/Source_code/Core/CoreB')
In each project I have a properties.gradle with the customRootDir filled in (relatively to the projects directory).
It all works like a charm. I can go into any project folder and produce builds, while using the functionality of the root's build.gradle.

SonarQube not apply analyzing to the root project

I need to make analyzing only root project, and ignore nested sub module, but it d
So I have this hierarchy:
ProjectMain
-src
-subProjectAngular
settings.gradle
My configuration settings.gradle
rootProject.name="ProjectMain"
include 'subProjectAngular'
I need to make analyzing only root project, and ignore nested sub module, but I got:
A multi-module project can't have source folders, so 'C:\Users\vagrant\develop-2\site\Source\Site\Vessels\src\main\java' won't be used for the analysis. If you want to analyse files of this folder, y
ou should create another sub-module and move them inside it.
Then I tried to add multi module configuration:
systemProp.sonar.projectKey=site
systemProp.sonar.projectName=vessels-test
systemProp.sonar.projectBaseDir=.
systemProp.sonar.sources=src
systemProp.sonar.modules=javamodule, angularmodule
systemProp.javamodule.sonar.projectName=vessels
systemProp.javamodule.sonar.sources=src
systemProp.javamodule.sonar.projectBaseDir=.
systemProp.javamodule.sonar.language=java
systemProp.angularmodule.sonar.projectName=angular
systemProp.angularmodule.sonar.projectBaseDir=.
systemProp.angularmodule
but got message at UI: no analysis has been performed
It's only works when I remove definishion of subproject from settings.gradle, and remove all submodule confguration
This configuration is not support yet in SonarQube.
But the good news is that this will change with SonarQube 6.4 (expect in early May 2017). See the following tickets:
SONAR-6724
SONARGRADL-5

Categories

Resources