Spring Boot Multi-module Project

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:

spring boot multi-module project

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

download source code

Thanks for reading.

2 thoughts on “Spring Boot Multi-module Project

  1. Can i add my email-service jar & user-service jar in another spring starter project . If yes please help with the process.

  2. 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 ?

Leave a Reply

Your email address will not be published. Required fields are marked *