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 library for it. The individual module is also deployable.

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 we-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 modules need 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.

You may also like to read:

how to create multi-module maven project in Eclipse

Prerequisites

Eclipse
Java 8
Spring Boot dependencies
Maven

Project Structure

spring boot multi-module project

Parent pom.xml

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 modules or sub-projects must exist otherwise you would get exceptions. We have also added spring boot dependencies and jackson dependency and spring boot maven plugin. Notice also we have packaging type as pom for parent pom file because it is basically a container of submodules, each submodule is represented by a subdirectory in the same directory as 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>jeejava</groupId>
	<artifactId>spring-microservices</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>

	<name>spring-microservices</name>
	<url>http://maven.apache.org</url>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.3.RELEASE</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<modules>
		<module>email-service</module>
		<module>user-service</module>
		<module>web-service</module>
	</modules>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
		</dependency>
	</dependencies>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-maven-plugin</artifactId>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

</project>

The following three individual modules are explained step by step for spring boot multi-module project.

email-service module

For email-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 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.

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>jeejava</groupId>
		<artifactId>spring-microservices</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<artifactId>email-service</artifactId>
	<name>email-service</name>
	<packaging>jar</packaging>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
	</dependencies>

</project>

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 service;

import java.util.logging.Logger;

import org.springframework.stereotype.Service;

@Service
public class EmailService {

	private static final Logger LOGGER = Logger.getLogger(EmailService.class.getName());

	public void sendEmail(final String toAddress) {
		// send email to toAddress
		LOGGER.info("Email successfully sent");
	}

}

As we have already said 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 – email-service.

package boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = { "service" })
public class EmailServiceApp {

	public static void main(String[] args) {
		SpringApplication.run(EmailServiceApp.class, args);
	}

}

user-service module

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.

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>jeejava</groupId>
		<artifactId>spring-microservices</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<artifactId>user-service</artifactId>
	<name>user-service</name>
	<packaging>jar</packaging>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>jeejava</groupId>
			<artifactId>email-service</artifactId>
			<version>${project.version}</version>
		</dependency>
	</dependencies>

</project>

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 users list will automatically be populated with users.

package 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 dto.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@jeejava.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@jeejava.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());
	}
}

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 boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = { "controller", "service" })
public class UserServiceApp {

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApp.class, args);
    }

}

The corresponding DTO class is given below. Here is the User class with four attributes – id, firstName, lastname and email address.

package dto;

public class User {

	private int id;
	private String firstName;
	private String lastName;
	private String email;

	public User() {

	}

	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;
	}

}

web-service module

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

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>jeejava</groupId>
		<artifactId>spring-microservices</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<artifactId>web-service</artifactId>
	<name>web-service</name>
	<packaging>jar</packaging>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>jeejava</groupId>
			<artifactId>user-service</artifactId>
			<version>${project.version}</version>
		</dependency>
		<dependency>
			<groupId>jeejava</groupId>
			<artifactId>email-service</artifactId>
			<version>${project.version}</version>
		</dependency>
	</dependencies>

</project>

Create below REST Controller to handle client’s request/response. Here we have published some REST endpoints to use email-service and user-service.

package controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import dto.User;
import service.EmailService;
import service.UserService;

@RestController
public class WebController {

    @Autowired
    private UserService userService;
    @Autowired
    private EmailService emailService;

    @RequestMapping("/user/{id}")
    public User getUser(@PathVariable int id) {
        return userService.getUserById(id);
    }

    @RequestMapping(value = "/user/", method = RequestMethod.POST)
    public ResponseEntity<String> sendEmail(@RequestBody User user) {
        userService.sendEmail(user);
        return new ResponseEntity<>("Email Successfully sent", HttpStatus.OK);
    }

    @RequestMapping(value = "/email/{toAddress}", method = RequestMethod.POST)
    public ResponseEntity<Void> sendEmail(@PathVariable String toAddress) {
        emailService.sendEmail(toAddress);
        return new ResponseEntity<Void>(HttpStatus.OK);
    }
}

Create below main class to deploy spring boot multi-module project as a whole.

package controller;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;

import boot.EmailServiceApp;
import boot.UserServiceApp;

@SpringBootApplication
@ComponentScan(basePackages = { "controller", "service" })
public class WebServiceApp {

    public static void main(String[] args) {
        new SpringApplicationBuilder(UserServiceApp.class, EmailServiceApp.class).run(args);
    }

}

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

GET http://localhost:8082/user/1000

response : {"id":1000,"firstName":"Soumitra","lastName":"Roy","email":"contact@jeejava.com"}

POST http://localhost:8082/user/

Headers: Content-Type : application/json

Body : {“id”:1000,”firstName”:”Soumitra”,”lastName”:”Roy”,”email”:”contact@jeejava.com”}

Response Body : Email Successfully sent

POST http://localhost:8082/email/contact@jeejava.com

Response Headers : Status : 200

You can download the complete project spring-microservices.

Congratulations! You have successfully built the spring boot multi-module project.

Thanks for reading.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

13 thoughts on “Spring Boot Multi-module Project

  1. Hi….

    Do you really think…”email service” and “user Service” will get called from individually deployed instance ?

    Here, you are using other 2 modules as a dependency, not as service…..

    Regards,
    Radhakanta Ghosh

  2. I tried removing the dependency of email service from user service and create a new method in email service, that gets directly called from web service. Even then I had to use to port configured in user service to call it. Why is that so? Why only port configured in user service works? Is this coded somewhere?

  3. Sorry the post is really misleading 🙁

    You had the small amount of time to create a better example…

    (Web) Service (MicroService) means an application to allow machine-to-machine communication.

    Sorry but your code and your description does not resolve the problem – just another multi module project with with app and 2 libs

    To solve the project – email and user service have to provide a transport interface like http and mq that is getting called by web service. In this case you have to define a client to provide the web service a consuming functionallity….

    Just remove email dependency from user and user dependency from web and deploy all 3 modules seprately…

    Challenge failed 🙁 pity

  4. Hi,
    First of all thank for your tutorial.
    I have questions, I haveto access to a database, and I want to deploy the three module as a one monolithic application.
    – The starter should be only in the main module, webservice ?
    – the application.properties for the database access should be in the Dao module or with the starter in the main module ?
    -should I create a configuration class in each module to declare the scanned packages, enabled configurations ? how to regroup all the class confgurations in a one class.

    thank you in advance

    1. So you want to create only one main class for webservice module then you create configuration class in that module. You don’t need to create any configuration class in other module as the other module will be used as dependent module.

Leave a Reply

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