Open In App

Spring – Project Modules

Last Updated : 09 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Every Spring Boot project has several modules and each module match some application layer (service layer, repository layer, web layer, model, etc..). In this article, let us see a maven-driven project as an example for showing Project Modules.

Example

pom.xml (overall project level)

XML




<?xml version="1.0" encoding="UTF-8" standalone="no"?>
         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>
     
      <!-- Spring IO Platform is the parent of the generated application to
             be able to use Spring Boot and all its default configuration -->
    <parent>
        <groupId>io.spring.platform</groupId>
        <artifactId>platform-bom</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>
    <groupId>gfg.multimodule</groupId>
    <artifactId>gfg.multimodule</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>Parent - Pom Aggregator</name>
    <description>This pom is a maven aggregator that contains all application modules. Also, include all
    common dependencies needed by more than one module. Dependencies are defined without version because
    this project has defined Spring IO Platform as parent.</description>
 
    <properties>
      <java.version>1.6</java.version>
    </properties>
 
    <modules
      <module>model</module>
      <module>repository</module>
      <module>service-api</module>
      <module>service-impl</module>
      <module>application</module>
    </modules>
 
    <dependencies>
 
      <!-- Spring Boot dependencies -->
      <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter</artifactId>
          </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
    </dependencies>
 
</project>


This sample project is containing the below modules

application (Here the starting point of the spring boot application is kept and it will also contain rendering pages)

application project module

 

Let us see the key important files

GfgWebJspApplication.java

Java




import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class GfgWebJspApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(GfgWebJspApplication.class, args);
    }
}


WelcomeController.java

Java




import gfg.multimodule.domain.entity.SalaryAccount;
import gfg.multimodule.service.api.EmployeeAccountService;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
public class WelcomeController {
    @Value("${application.message:Hello World}")
    private String message = "Hello World";
 
    @Autowired
    protected EmployeeAccountService accountService;
 
    @RequestMapping("/")
    public String welcome(Map<String, Object> model)
    {
        // Trying to obtain for account 100
        SalaryAccount account
            = accountService.findOne("100");
        if (account == null) {
            // If there's some problem creating account,
            // return show view with error status
            model.put("message", "Error getting account!");
            model.put("account", "");
            return "welcome/show";
        }
 
        // Return show view with 100 account info
        // As a sample checking for account number 100 and
        // if available it will get redirected to show.html
        String accountInfo
            = "Your account number is ".concat(
                account.getEmployeeAccountNumber());
        model.put("message", this.message);
        model.put("account", accountInfo);
        return "welcome/show";
    }
 
    @RequestMapping("foo")
    public String foo(Map<String, Object> model)
    {
        throw new RuntimeException("Foo");
    }
}


show.html  (Once the account is available, we can see the output from show.html)

HTML




<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
   <head>
      <title>Spring Boot Multimodule</title>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <style>
         #orangerow
         {
         background:orange;
         font:17 px "Times New Roman", serif;
         color:#000000;
         }
         #yellowrow
         {
         background:yellow;
         font:17 px "Times New Roman", serif;
         color:#000000;
         }
      </style>
   </head>
   <body>
      <table border="1">
         <tr id="yellowrow">
            <td>
               Welcome Message
            </td>
            <td>
               Account Details
            </td>
         </tr>
         <tr id="orangerow">
            <td>
               <span th:text="${message}" />
            </td>
            <td>
               <span th:text="${account}" />
            </td>
         </tr>
      </table>
   </body>
</html>


For this application folder, we need to have a specific pom.xml that will show the dependencies for this module

application -> pom.xml

XML




<?xml version="1.0" encoding="UTF-8" standalone="no"?>
         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>
    <parent>
        <groupId>gfg.multimodule</groupId>
        <artifactId>gfg.multimodule</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>gfg.multimodule.application</artifactId>
    <packaging>jar</packaging>
    <name>Project Module - Application</name>
    <description>This is the main module of the project. It contains Application.java class, that contains main method,
    necessary to run Spring Boot applications. It contains all necessary application configuration properties.
    It contains all web controllers, views and web resources. It include Service Implementation module
    as dependency that contains Model Module, Repository Module and Service Api Module. </description>
 
    <dependencies>
 
      <!-- Project modules -->
      <dependency>
        <groupId>gfg.multimodule</groupId>
        <artifactId>gfg.multimodule.service.impl</artifactId>
        <version>${project.version}</version>
      </dependency>
 
      <!-- Spring Boot dependencies -->
      <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
      </dependency>
       
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
     
    </dependencies>
     
    <build>
        <plugins>
            <!-- Spring Boot plugins -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
</project>


Next module that we are going to see as a model (Here we will be having our POJO/entity classes and their related details).

 

SalaryAccount.java

Java




import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
 
@Entity
public class SalaryAccount {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    // data members. Their getter and setter
    private Long employeeAccountId;
 
    private String employeeAccountNumber;
 
    private String type;
 
    private String creditCardNumber;
 
    public SalaryAccount() {}
 
    public SalaryAccount(Long employeeAccountId,
                         String employeeAccountNumber)
    {
        this.employeeAccountNumber = employeeAccountNumber;
        this.employeeAccountId = employeeAccountId;
    }
 
    public Long getEmployeeAccountId()
    {
        return employeeAccountId;
    }
 
    public void setEmployeeAccountId(Long employeeAccountId)
    {
        this.employeeAccountId = employeeAccountId;
    }
 
    public String getEmployeeAccountNumber()
    {
        return employeeAccountNumber;
    }
 
    public void
    setEmployeeAccountNumber(String employeeAccountNumber)
    {
        this.employeeAccountNumber = employeeAccountNumber;
    }
 
    public String getType() { return type; }
 
    public void setType(String type) { this.type = type; }
 
    public String getCreditCardNumber()
    {
        return creditCardNumber;
    }
 
    public void setCreditCardNumber(String creditCardNumber)
    {
        this.creditCardNumber = creditCardNumber;
    }
}


model -> pom.xml

XML




<?xml version="1.0" encoding="UTF-8" standalone="no"?>
         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>
    <parent>
        <groupId>gfg.multimodule</groupId>
        <artifactId>gfg.multimodule</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>gfg.multimodule.model</artifactId>
    <packaging>jar</packaging>
    <name>Project Module - Model</name>
    <description>Module that contains all Entities and Visual Objects
     to be used in the project. It doesn't have any dependencies.</description>
</project>


Next, let us see the repository module. This is the module where we can have our CRUD-related operations interface can be written. Usually, it will have searching/inserting/updating/deleting

 

SalaryAccountRepository.java

Java




import gfg.multimodule.domain.entity.SalaryAccount;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
 
@Repository
// It should extends CrudRepository as we will have useful
// methods related to CRUD operations
public interface SalaryAccountRepository
    extends CrudRepository<SalaryAccount, Long> {
    SalaryAccount findByEmployeeAccountNumber(
        String employeeAccountNumber);
}


pom.xml

XML




<?xml version="1.0" encoding="UTF-8" standalone="no"?>
         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>
    <parent>
        <groupId>gfg.multimodule</groupId>
        <artifactId>gfg.multimodule</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>gfg.multimodule.repository</artifactId>
    <packaging>jar</packaging>
    <name>Project Module - Repository</name>
    <description>Module that contains all repositories to be used in the project.
     Depends of Model Module.</description>
 
    <dependencies>
       
      <!-- Project modules -->
      <dependency>
        <groupId>gfg.multimodule</groupId>
        <artifactId>gfg.multimodule.model</artifactId>
        <version>${project.version}</version>
      </dependency>
 
      <!-- Spring Boot dependencies -->
      <!-- Should specify the database that we are using -->
      <dependency>
        <groupId>org.hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <scope>runtime</scope>
      </dependency>
 
    </dependencies>
     
</project>


The next one is service-api. Business logic-related methods are introduced here

 

Important key files

EmployeeAccountService.java

Java




package gfg.multimodule.service.api;
 
import gfg.multimodule.domain.entity.SalaryAccount;
import java.util.List;
 
public interface EmployeeAccountService {
 
    SalaryAccount findOne(String number)
        throws EmployeeAccountNotFoundException;
 
    SalaryAccount
    createAccountByEmployeeAccountNumber(String number);
}


EmployeeAccountNotFoundException.java

Java




public class EmployeeAccountNotFoundException
    extends RuntimeException {
    private static final long serialVersionUID
        = -3891534644498421234L;
 
    public EmployeeAccountNotFoundException(
        String accountId)
    {
        super("No such account with id: " + accountId);
    }
}


The final one is the implementation one. The service-impl  This will implement the service methods (business logic requirements) and real implementation is getting done here

 

EmployeeAccountServiceImpl.java

Java




import gfg.multimodule.domain.entity.SalaryAccount;
import gfg.multimodule.repository.SalaryAccountRepository;
import gfg.multimodule.service.api.EmployeeAccountService;
import gfg.multimodule.service.api.EmployeeAccountNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
 
@Service
public class EmployeeAccountServiceImpl
    implements EmployeeAccountService {
 
    @Value("${dummy.type}") private String dummyType;
 
    @Autowired
    private SalaryAccountRepository accountRepository;
 
    @Override
    public SalaryAccount
    findOne(String employeeAccountNumber)
        throws EmployeeAccountNotFoundException
    {
        if (employeeAccountNumber.equals("0000")) {
            throw new EmployeeAccountNotFoundException(
                "0000");
        }
 
        SalaryAccount salaryAccount
            = accountRepository.findByEmployeeAccountNumber(
                employeeAccountNumber);
        if (salaryAccount == null) {
            salaryAccount
                = createAccountByEmployeeAccountNumber(
                    employeeAccountNumber);
        }
 
        return salaryAccount;
    }
 
    @Override
    public SalaryAccount
    createAccountByEmployeeAccountNumber(
        String employeeAccountNumber)
    {
        SalaryAccount account = new SalaryAccount();
        account.setEmployeeAccountNumber(
            employeeAccountNumber);
        return accountRepository.save(account);
    }
 
    public String getDummyType() { return dummyType; }
 
    public void setDummyType(String dummyType)
    {
        this.dummyType = dummyType;
    }
}


Now let us see how to run the whole project. “mvn clean install” has to be given where the project got hosted (parent folder where pom,xml) present

 

 

Now we need to step ahead to the application folder and execute it as mvn spring-boot:run

 

 

On successful startup (Tomcat dependency is given and it is running on port 8080)

http://localhost:8080/

We can able to see as

 

By combining different project modules, as a maven project, we need to include all the modules and all the required dependencies need to be given, then the whole project is run successfully and we will get the output as above.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads