Gradle multimodule project build in IntelliJ - relation between artifacts and wars - java

I'm facing some problems with my multimodule project gradle build in IntelliJ. My gradle build works correctly, but IntelliJ is not picking it up as it should causing my development cycle to slow down drastically.
I have this dependency setup between my projects (5 projects, 3 wars, shared has my model etc. common-web has the common web components)
TD (war) -> common-web
CP (war) -> common-web
CP (war) -> Shared
Web (war) -> common-web
Web (war) -> Shared
Shared
common-web
With the following structure:
|- TD
|- Web
|- Shared
|- common-web
|- CP
| settings.gradle
| build.gradle
I have one gradle build file and one gradle settings file.
include 'TD', 'CP', 'Web', 'Shared', 'common-web'
allprojects {
repositories {
mavenCentral()
}
sourceCompatibility = 8
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
subprojects {
apply plugin: 'java'
apply plugin: 'idea'
dependencies {
// dependencies...
}
}
project(':CP') {
apply plugin: 'war'
dependencies {
// dependencies...
compile project(':shared')
compile project(':common-web')
}
}
project(':web') {
apply plugin: 'war'
dependencies {
// dependencies...
compile project(':common-web')
compile project(':shared')
}
}
project(':shared') {
dependencies {
// dependencies...
}
}
project(':TD') {
apply plugin: 'war'
dependencies {
// dependencies...
compile project(':common-web')
}
}
project(':common-web') {
apply plugin: 'war' // needed to allow the providedComp
dependencies {
// dependencies...
}
}
Is there a way I should configure the gradle idea plugin to allow this to be build correctly? have found the make button does not work like I think it should work, ignoring the compile errors in the modules etc. I see that in the root of the project, IntelliJ creates a folder classes/artifacts and does not use the (correct) build in the module/lib folder.
The errors I'm seeing is the wrong include of the jars. For example the web project has a dependency to the TD project, which is defined nowhere.
Is this a bug in the gradle plugin of IntelliJ or am I doing something I shouldn't?

Related

Build with gradlew and make it available in ./m2 [duplicate]

I have 2 different project build on mvn. I am trying to replace to Gradle.
Project 1 is an SDK, and project 2 is using that sdk (example).
In the time of maven it creates artifact using mvn install which adds the whole project into local repository.
I like to work in gradle like that. I like project 1 build.gradle need to post it as a gradle local repository and then example project need to use it.
In maven we do mvn install which adds a project artifact into .m2 folder but how to do in gradle so what i can add a project artefact's into the local repository.
Any way that I can do so?
sdk/build.gradle:
apply plugin: "maven"
group = "foo"
version = "1.0"
example/build.gradle:
repositories {
mavenLocal()
}
dependencies {
compile "foo:sdk:1.0"
}
$sdk> gradle install
$example> gradle build
You may be looking for:
gradle publishToMavenLocal
build.gradle:
plugins {
// other plugins
id 'maven-publish'
}
publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
}
See: Maven Publish Plugin
Check out Gradle's documentation on multi-project builds.
Here's an example, with some extra dependencies. Just call gradle install in the root folder, and all will be built and put to your local repo.
Folder structure:
root
+--> build.gradle
+--> settings.gradle
+--> sdk
| +--> build.gradle
+--> example
+--> build.gradle
root/build.gradle:
allprojects {
apply plugin: 'java'
apply plugin: 'maven'
group = 'myGroup'
version = '0.1-SNAPSHOT'
}
root/settings.gradle:
include 'sdk'
include 'example'
root/sdk/build.gradle:
dependencies {
// just an example external dep.
compile group:'commons-lang', name:'commons-lang', version:'2.3'
}
root/example/build.gradle:
dependencies {
compile project(':sdk')
compile group:'log4j', name:'log4j', version:'1.2.16'
}
You need to publish your own library to your local repository. You can do that in the following way:
Add maven-publish plugin:
plugins {
// your other plugins come here...
id 'maven-publish'
}
Add the publishing section to your build file:
publishing {
publications {
myCoolLibrary(MavenPublication) {
from components.java
}
}
}
Run gradle build publishToMavenLocal
Find more details in the documentation.

Gradle task 'wrapper' not found in project ':subproject'

I have root gradle project which needs to have a small Spring Boot subproject. This subproject will be deployed in the same pod as root project, so it needs to be built whenever root project is built. I tried by creating the following structure:
subproject/
├─ src/...
├─ build.gradle
settings.gradle
with the following contents:
settings.gradle:
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = 'root'
include 'subproject'
build.gradle:
plugins {
id 'org.springframework.boot' version '2.7.0'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.demo'
version = '1.0.0-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
But when I refresh the project from within the IDEA, it shows Task 'wrapper' not found in project ':subproject'. What did miss? This subproject cannot exist by itself and shouldn't have a 'wrapper', it should be build by the root project.
$ ./gradlew -q projects
Root project 'root'
+--- Project ':subproject'
Gradle version: 6.8.3, Java version: 11
The problem actually does not exist. Everything is correct, except that IDEA added subproject as separate gradle project (I guess). So when I hit refresh, it could not be performed because IDEA was trying to find wrapper in the subproject. Simply saying, if you have such problem, check how many projects you have in your IDEA's Gradle view. In my case, there was two - root and subproject, the latter is unneeded.

How do I generate Maven POMs for multi-module builds with Gradle?

In order to not manually manage, both, Maven and Gradle build configuration files, I wanted to let Gradle generate the Maven POMs for a multi-module build.
This is working so far. Below you find the settings.gradle
rootProject.name = 'parent'
include 'module-a'
include 'module-b'
and here follows build.gradle
allprojects {
apply plugin: 'maven'
group = 'com.example.project'
version = '1.0-SNAPSHOT'
}
subprojects {
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
task createPom << {
pom {
project {
parent {
groupId project.group
artifactId rootProject.name
version project.version
}
}
}.writeTo("pom.xml")
}
}
task createPom << {
pom {
project {
packaging 'pom'
modules {
module 'module-a'
module 'modula-b'
}
}
}.writeTo("pom.xml")
}
The problem is that I have to manually declare the modules in the createPom task of the root project. Also, I need two dedicated tasks; one for the root project and and for the subprojects.
How can I let Gradle figure out what the modules are? Or is there a way to programmatically determine and add the subprojects as modules? Furthermore, is it even necessary to have two distinct tasks?

Spring Boot multi module project with Gradle doesn't build

I'm working on a Spring Boot app with multiple modules and we're using Gradle to build it. Unfortunately I can't get the Gradle configuration right.
The project structure is this:
parent
|
+ build.gradle
|
+ settings.gradle
|
+ core
| |
| + build.gradle
|
+ apis
| |
| + build.gradle
|
+ services
| |
| + build.gradle
|
+ data
| |
| + build.gradle
When I try to build the project, I get compilation errors like error: cannot find symbol saying, that the classes from data used in services aren't imported. And I assume this is true between all the modules.
My parent build.gradle looks like this:
buildscript {
ext {
springBootVersion = '2.0.0.BUILD-SNAPSHOT'
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'eclipse'
apply plugin: 'idea'
allprojects {
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
testCompile('org.springframework.boot:spring-boot-starter-test')
}
}
dependencies {
compile project(':data')
compile project(':services')
compile project(':apis')
compile project(':core')
}
jar {
baseName = 'my-jar'
version = '0.0.1-SNAPSHOT'
}
settings.gradle:
rootProject.name = 'my-app'
include ':apis'
include ':core'
include ':data'
include ':services'
one of children (core) has this in it's build.gradle:
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-quartz')
compile('org.springframework.boot:spring-boot-starter-tomcat')
runtime('com.h2database:h2')
compile project(':data')
compile project(':services')
compile project(':apis')
}
services build.gradle looks like this:
dependencies {
compile('org.springframework.boot:spring-boot-starter-quartz')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
runtime('com.h2database:h2')
compile project(':data')
}
The other ones also declare only dependencies.
The dependency structure looks like this:
core - apis, services, data
apis - services, data
services - data
data -
Example of the compilation errors:
/my-app/services/src/main/java/com/example/my-app/business/IssuedTokenService.java:3: error: package com.examples.data.dao does not exist import com.examples.data.dao.IssuedToken;
/my-app/services/src/main/java/com/example/my-app/business/IssuedTokenService.java:4: error: package com.examples.data.repository does not exist import com.examples.data.repository.IssuedTokenRepository;
/my-app/services/src/main/java/com/example/my-app/business/IssuedTokenService.java:12: error: cannot find symbol
private IssuedTokenRepository issuedTokenRepository;
symbol: class IssuedTokenRepository
location: class IssuedTokenService
/my-app/services/src/main/java/com/example/my-app/business/IssuedTokenService.java:15: error: cannot find symbol
public void saveToken(IssuedToken issuedToken) {
^
symbol: class IssuedToken
location: class IssuedTokenService
In your utility (data) projects put:
bootJar {
enabled = false
}
jar {
enabled = true
}
If kotlin dsl
tasks.getByName<BootJar>("bootJar") {
enabled = false
}
tasks.getByName<Jar>("jar") {
enabled = true
}
The answer is similar to this one.
Gradle documentation on multi-project builds states:
A “lib” dependency is a special form of an execution dependency. It
causes the other project to be built first and adds the jar with the
classes of the other project to the classpath.
A repackaged jar, thus, poses a problem.
If, say, project B depends on project A, and the project A has a org.springframework.boot plugin applied to it, a simple compile project(':A') dependency will not work because the project jar is repackaged during the bootRepackage or bootJar task. The resulting fat jar has different structure, preventing Gradle from loading its classes.
In this case, the dependencies should be written the following way:
dependencies {
compile project(':A').sourceSets.main.output
}
Using output of a source set directly is equivalent to using the "normal" resulting jar of project A before it is repackaged.
bootJar {
enabled = false
}
jar {
enabled = true
}
This works for my. In my case use spring boot with spring cloud with multi project and gradle fail to build. With this solution works!
You should exclude org.springframework.boot from all submodules (root build.gradle file, allProjects block), that are stands as dependencies for your core module, which will be build to fat-jar.
Include dependencyManagement configuration into all of your spring-boot managed submodules:
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-starter-parent:${springBootVersion}"
}
}
The reason of your problem is the absence of submodules compiled jar files inside your core module fat-jar.

Gradle eclipse using incorrect version for dependencies

I'm migrating a project to gradle to resolve dependencies, generate the eclipse project and build the project and I'm with a problem with the version of some dependencies on eclipse project. Here's the build.gradle of the project. It's an EAR with sub-projects.
apply plugin: 'ear'
def eclipseJbossName = 'org.eclipse.jst.server.core.container/org.jboss.ide.eclipse.as.core.server.runtime.runtimeTarget/JBoss 6.x Runtime'
def defaultEarConfig = rootDir.getAbsolutePath() + '/ear.gradle'
allprojects {
apply plugin: 'eclipse'
apply plugin: 'eclipse-wtp'
apply plugin: 'idea'
eclipse {
classpath {
containers eclipseJbossName
}
}
repositories {
maven {
name = "mvnrepository"
url = "http://mvnrepository.com/"
}
mavenCentral()
maven {
name = 'jboss'
url = 'http://repository.jboss.org/nexus/content/groups/public/'
}
}
}
subprojects {
configurations {
provided
}
apply plugin: 'java'
sourceCompatibility = 1.6
targetCompatibility = 1.6
sourceSets {
main {
compileClasspath += configurations.provided
compileClasspath += configurations.compile
compileClasspath += configurations.runtime
}
}
}
dependencies {
deploy (project(path: 'anEJB')) {
transitive = false
}
deploy (project(path: 'anotherEJB')) {
transitive = false
}
deploy (project(path: 'aWAR', configuration: 'archives')) {
transitive = false
}
earlib ('commons-beanutils:commons-beanutils:1.6') {
transitive = false
}
//lots of other dependencies and all with transitive=false
}
//configuration of my subprojects
When I call gradle ear it builds and generate my artifact correctly. In the lib directory inside the root of the EAR there's all my earlibs with its correct versions. When I call gradle cleanEclipse eclipse it generates my project right, but when I see the build path inside eclipse it is using an incorrect version for commons beanutils. It is using the version 1.8. This is not happening for all my dependencies, but there are others with this problem. I've put all to not resolve the transitive dependencies.
You can click the project in Eclipse with right mouse button, then click properties. And select "Java Build Path" then click "Libraries" tab. Finally remove all jars besides "Gradle Dependencies" & "JRE System Libraries".
Done. Try it.

Categories

Resources