Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 311
bajermi2 Avatar asked Dec 01 '17 17:12

bajermi2


3 Answers

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 } 
like image 80
Prime Avatar answered Sep 18 '22 17:09

Prime


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.

like image 35
jihor Avatar answered Sep 19 '22 17:09

jihor


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!

like image 44
dariovmartine Avatar answered Sep 17 '22 17:09

dariovmartine