Introduction
In this example we will see how to work with spring boot multi-module project and deploy them together in embedded Tomcat server. The Tomcat Server comes with the Spring Boot API, so we don’t need to include extra jar or library for it. The individual module is also deployable. You may also want to use other server like Jetty instead of Tomcat server in Spring Boot application.
In this example we have three modules email-service – responsible for sending email to the specific email address, user-service – responsible for handling user related activities and web-service – responsible for handling client request/response.
Why we need multi modules project?
Splitting the project into multiple modules is useful, for example, if the module needs to be deployed separately.
The idea of a multi-module build is if you have modules which belong together like an ear project which usually consists of several others like client, server, ejb, war, etc. Your modules share the same dependencies, in this case you will specify all the dependencies in the main pom, and all other modules can enjoy it and no need to specify for each module the same dependencies.
If you need to perform operations on multiple projects all together. You create a package from all projects, and ship it to a customer, so build them using the main pom, and package them as zip file using other maven plugin.
It makes the code easier to keep in order with big project, even if the code could technically be all in the same module.
Prerequisites
How to create multi-module maven project in Eclipse
Spring Boot 2.1.8.RELEASE
Creating Project
The name of the project is spring-boot-multi-module-project. But you need to refer to the prerequisites section for the link how to create multi module project in Eclipse.
The project structure could be shown as similar to the following image:

Creating Multi-Modules
The parent pom.xml file of spring boot multi-module project contains three modules email-service, user-service and web-service and of course these sub-modules or sub-projects must exist in the parent pom file under <modules>
tag, otherwise you would get exceptions.
We have also added spring boot dependencies and maven compiler plugin.
Related Posts:
Notice also we have packaging type as pom
for parent’s pom file because it is basically a container of submodules and each submodule is represented by a subdirectory in the same directory as we have parent project’s pom.xml with pom packaging.
<?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.roytuts</groupId>
<artifactId>spring-boot-multi-module-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>12</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<modules>
<module>email-service</module>
<module>user-service</module>
<module>web-service</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
The following three individual modules are explained step by step for spring boot multi-module project.
Submodule: email-service
For email-service submodule notice that we have not added any spring boot dependencies or plugin because these dependencies will be inherited from parent’s pom file.
If we need any dependency that is required for email-service then we have to add it to email-service‘s pom.xml file.
Notice for this module we have specified packaging type as jar.
Build File – pom.xml
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.roytuts</groupId>
<artifactId>spring-boot-multi-module-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>email-service</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
</dependencies>
</project>
Service Class
Create below service layer code to send the email to a specific email address.
This method will not really send an email until you configure with email API.
package com.roytuts.email.service;
import org.springframework.stereotype.Service;
@Service
public class EmailService {
public void sendEmail(final String toAddress) {
// send email to toAddress
System.out.println("Email successfully sent");
}
}
Main Class
As we have already said that in multi-module project, individual module is independently deployable so we are creating below main class in order to deploy the spring boot project – email-service.
package com.roytuts.email.service.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.roytuts.email.service")
public class EmailServiceApp {
public static void main(String[] args) {
SpringApplication.run(EmailServiceApp.class, args);
}
}
Submodule: user-service
For user-service module notice that we have not added any spring boot dependencies or plugin because these dependencies will be inherited from parent’s pom file and if we need any dependency that is required for user-service then we have to add it to user-service‘s pom.xml file.
Notice for this module we have specified packaging type as jar.
There is another thing in this pom file, i.e., we have added email-service as a dependency to the user-service‘s pom file in order to use the email-service.
Build File – pom.xml
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.roytuts</groupId>
<artifactId>spring-boot-multi-module-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>user-service</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.roytuts</groupId>
<artifactId>email-service</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
DTO Class
The DTO class represents a blue print of the user to hold some user details or information.
The User
class contains four attributes – id, firstName, lastname and email address.
package com.roytuts.user.service.model;
public class User {
private int id;
private String firstName;
private String lastName;
private String email;
public User(int id, String firstName, String lastName, String email) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Service Class
Create below service layer code to retrieve a user information and to send an email to user’s email address.
We have created some dummy data with some users and initialize these dummy data using spring’s @PostConstruct
annotation so that after construction of the userService
object the list – users
– will automatically be populated with user
objects.
package com.roytuts.user.service;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.roytuts.email.service.EmailService;
import com.roytuts.user.service.model.User;
@Service
public class UserService {
@Autowired
private EmailService emailService;
private final List<User> users = new ArrayList<>();
@PostConstruct
public void init() {
users.add(new User(1000, "Soumitra", "Roy", "contact@roytuts.com"));
users.add(new User(1001, "Sudipto", "Bhowmick", "sudipto.bhowmick@email.com"));
users.add(new User(1002, "Gautam", "Roy", "gautam.roy@email.com"));
users.add(new User(1003, "Soumitra", "Sarkar", "contact@roytuts.com"));
}
public User getUserById(final int id) {
return users.stream().filter(user -> user.getId() == id).findFirst().get();
}
public void sendEmail(User user) {
emailService.sendEmail(user.getEmail());
}
}
Main Class
As we have already said previously that in multi-modules project, individual module is independently deployable so we are creating below main class in order to deploy the spring boot project – user-service.
package com.roytuts.user.service.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.roytuts")
public class UserServiceApp {
public static void main(String[] args) {
SpringApplication.run(UserServiceApp.class, args);
}
}
Submodule: web-service
For web-service module also, notice that we have not added any spring boot dependencies or plugin because these dependencies will be inherited from parent’s pom file and if we need any dependency that is required for web-service then we have to add it to web-service‘s pom.xml file.
Notice for this module we have specified packaging type as jar. If you want you may also put packaging type as war but as this is a Spring Boot application so this does not make difference from application deployment.
In this pom file we have added email-service and user-service as dependencies to the web-service’s pom file in order to use email-service and user-service.
Build File: pom.xml
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.roytuts</groupId>
<artifactId>spring-boot-multi-module-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>web-service</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.roytuts</groupId>
<artifactId>user-service</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.roytuts</groupId>
<artifactId>email-service</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
REST Controller Class
Create below REST Controller class to handle client’s request/response.
Here we have published some REST endpoints to use email-service and user-service.
package com.roytuts.web.service.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.roytuts.email.service.EmailService;
import com.roytuts.user.service.UserService;
import com.roytuts.user.service.model.User;
@RestController
public class WebRestController {
@Autowired
private EmailService emailService;
@Autowired
private UserService userService;
@GetMapping("user/{id}")
public User getUser(@PathVariable int id) {
return userService.getUserById(id);
}
@PostMapping("user/")
public ResponseEntity<String> sendEmail(@RequestBody User user) {
userService.sendEmail(user);
return new ResponseEntity<>("Email Successfully sent", HttpStatus.OK);
}
@PostMapping("email/{toAddress}")
public ResponseEntity<Void> sendEmail(@PathVariable String toAddress) {
emailService.sendEmail(toAddress);
return new ResponseEntity<Void>(HttpStatus.OK);
}
}
Main Class
Create below main class to deploy spring boot multi-module project as a whole.
package com.roytuts.web.service.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.roytuts")
public class WebServiceApp {
public static void main(String[] args) {
SpringApplication.run(WebServiceApp.class, args);
}
}
Testing the Application
Now run the above main class in web-service module, the email-service and user-service module will be deployed also.
You can now hit below URLs in REST client or Postman to test the services:
Request Method: GET
URL: http://localhost:8080/user/1000
Response
{
"id": 1000,
"firstName": "Soumitra",
"lastName": "Roy",
"email": "contact@roytuts.com"
}
Request Method: POST
URL: http://localhost:8080/user/
Headers: Content-Type : application/json
Body
{"id":1000,"firstName":"Soumitra","lastName":"Roy","email":"contact@roytuts.com"}
Response: Email Successfully sent
Request Method: POST
URL: http://localhost:8080/email/contact@roytuts.com
Response Headers: Status : 200
That’s all. You have successfully built the spring boot multi-module project.
Source Code
Thanks for reading.
Can i add my email-service jar & user-service jar in another spring starter project . If yes please help with the process.
Very neatly explained the multi module spring boot configuration. If we have a angular as a dependency we just add one more module. But we want this module to be compiled based on profile as its time consuming to build angular everytime. Is this possible in maven ?