In this technical post, we will review how to build a multi-module project using Gradle and Maven with Spring Boot. NOTE: If you need to know what tools you need to have installed in your computer in order to create a Spring Boot basic project, please refer my previous post: Spring Boot. Let’s start creating a new Spring Boot project with Webflux as a library:
spring init --dependencies=webflux,lombok --build=gradle --language=java library
Here is the complete build.gradle
generated:
plugins {
id 'org.springframework.boot' version '2.5.5' apply false
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.jos.dem.springboot.module.library'
sourceCompatibility = 16
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webflux'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
}
dependencyManagement {
imports{
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}
test {
useJUnitPlatform()
}
Since we are creating a library here, we want Spring Boot’s dependency management to be used in this project without applying some Spring Boot’s features, therefore we will use: apply false
. SpringBootPlugin
provides a BOM_COORDINATES
to handle project’s versions and dependencies. Let’s create a service so we can use it in our application module.
package com.jos.dem.springboot.module.library.service;
import com.jos.dem.springboot.module.library.config.LibraryProperties;
import lombok.RequiredArgsConstructor;
import reactor.core.publisher.Mono;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;
@Service
@RequiredArgsConstructor
public class MessageService {
private final LibraryProperties libraryProperties;
public Mono<String> getMessage(){
return Mono.just(libraryProperties.getMessage());
}
}
Next, let’s create an application project, from the $PROJECT_HOME:
spring init --dependencies=webflux,lombok --build=gradle --language=java application
This is the build.gradle
file generated:
plugins {
id 'org.springframework.boot' version '2.5.5'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.jos.dem.springboot.module'
version = '1.0.0-SNAPSHOT'
sourceCompatibility = 16
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation project(':library')
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
}
test {
useJUnitPlatform()
}
That’s it, we are importing our library as project dependency using Gradle implementation. Now it is time to create a controller and Spring Boot Application files.
package com.jos.dem.springboot.module.controller;
import lombok.RequiredArgsConstructor;
import reactor.core.publisher.Mono;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jos.dem.springboot.module.library.service.MessageService;
@RestController
@RequiredArgsConstructor
public class ModuleController {
private final MessageService messageService;
@GetMapping("/")
public Mono<String> index(){
return messageService.getMessage();
}
}
Spring Boot application:
package com.jos.dem.springboot.module;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ModuleApplication {
public static void main(String[] args) {
SpringApplication.run(ModuleApplication.class, args);
}
}
We need to provide a message for the service in the library by using $PROJECT_HOME/application/src/main/resources/application.yml
.
app:
message: 'Hello World!'
Finally add a settings.gradle
to the root directory to drive our build at the top level.
rootProject.name = 'spring-boot-module'
include 'library'
include 'application'
To run the project from $PROJECT_HOME
:
gradle build :application:bootRun
Using Maven
You can do the same using Maven, the only difference is that you need to specify --build=maven
parameter in the spring init
command line. This is the library
pom file generated:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jos.dem.springboot.module</groupId>
<artifactId>library</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>16</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Here is the application pom file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jos.dem.springboot.module</groupId>
<artifactId>application</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>16</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>com.jos.dem.springboot.module</groupId>
<artifactId>library</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
And this is our pom.xml
in the $PROJECT_HOME
directory.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jos.dem.springboot.module</groupId>
<artifactId>spring-boot-module</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<modules>
<module>library</module>
<module>application</module>
</modules>
</project>
Build the library first with mvn install
and then run the application. From $PROJECT_HOME
:
mvn install spring-boot:run -pl application
To see the results go to this URL in your browser:
http://localhost:8080/
To browse the project go here, to download the project:
git clone git@github.com:josdem/spring-boot-modules.git