Spring Boot Multi-Module Project Setup | බහුවිධ මොඩියුල ව්‍යාපෘති සාදමු | SC Guide

Spring Boot Multi-Module Project Setup | බහුවිධ මොඩියුල ව්‍යාපෘති සාදමු | SC Guide

Spring Boot Multi-Module Magic SC Guide

ආයුබෝවන්! කොහොමද යාලුවනේ? ඔයාලා හැමෝම Spring Boot එක්ක වැඩ කරනවා ඇති කියලා මම හිතනවා. ඒ වගේම පොඩි පොඩි Project එකක ඉඳලා ලොකු Application Develop කරන අයත් ඇති. අද අපි කතා කරන්න යන්නේ හරිම වැදගත්, ඒ වගේම ඔයාලගේ Software Engineering Journey එකේදී ගොඩක් ප්‍රයෝජනවත් වෙන මාතෘකාවක් ගැන – ඒ තමයි Spring Boot Multi-Module Projects ගැන. සරලවම කිව්වොත්, අපේ Application එක එකම ගොඩේ නැතුව, කෑලි කෑලි වලට කඩලා, ඒ හැම කෑල්ලක්ම එකට එකතු කරලා ලොකු Application එකක් හදන හැටි තමයි අපි අද මේ විස්තර කරන්නේ.

ගොඩක් වෙලාවට අපි පොඩි Project එකක් පටන් ගනිද්දී Single Module Application එකක් විදියට පටන් ගන්නවා. ඒ කියන්නේ, අපේ කෝඩ් එක, Database Layer එක, API Layer එක, Business Logic එක හැමදේම තියෙන්නේ එකම Module එක ඇතුළේ. ඒක පොඩි Project වලට කමක් නෑ. ඒත්, Project එක ටිකෙන් ටික ලොකු වෙද්දී, අලුත් Features එකතු වෙද්දී, තව Developers ලා ටීම් එකට එකතු වෙද්දී, මේ Single Module Application එක පාලනය කරගන්න අමාරු වෙනවා. ඒක හරියට පොල් කටු කඩේ වගේ හැමදේම ගොඩ ගැහිලා තියෙනවා වගේ වැඩක්. හරිම අවුල්. ඒත්, Multi-Module approach එකෙන් අපිට පුළුවන් මේක පිළිවෙලකට, ලස්සනට හදාගන්න. නේද?

ඉතින්, ඔයාලා මේ Spring Boot Multi-Module Projects ගැන දැනගන්න කැමති නම්, අදම මේ Guide එක කියවලා බලන්න. අපි මේක පටන් ගන්නේ මුල ඉඳලම, හරිම සරලව ඔයාලට තේරෙන විදියට. අපි බලමු මේක කොහොමද Set up කරගන්නේ, අපේ Application එක core, API, සහ data කියන modules වලට කොහොමද වෙන් කරන්නේ වගේ දේවල්.

ඇයි මේ Multi-Module කලබල? (Why Multi-Module?)

ගොඩක් වෙලාවට අපි දකින දෙයක් තමයි, Application එක ලොකු වෙද්දී Codebase එක Manage කරගන්න එක අමාරු වෙන එක. Single Module Project එකක මේ ප්‍රශ්න ගොඩක් එනවා. ඒකට තියෙන හොඳම විසඳුම තමයි මේ Multi-Module Architecture එක. අපි බලමු ඇයි මේක මෙච්චර වැදගත් වෙන්නේ කියලා:

  • Code Reusability (කෝඩ් එක ආයෙ ආයෙ පාවිච්චි කරන්න පුළුවන්): ඔයාට ඕන නම් එකම කෝඩ් කොටසක් Project එකේ වෙන වෙන තැන් වල, නැත්නම් වෙන Project වල පාවිච්චි කරන්න, Multi-Module වලින් ඒක හරිම ලේසියි. Core Logic එක වගේ දේවල් වෙනම Module එකක දාලා, ඕන තැනකට Import කරගන්න පුළුවන්.
  • Clear Separation of Concerns (වැඩේ පිළිවෙලට බෙදා ගන්න පුළුවන්): අපේ Application එකේ Data Layer එක, Business Logic එක, Web Layer එක වගේ දේවල් වෙන වෙනම Modules වලට බෙදලා දාන්න පුළුවන්. මේකෙන් එක Module එකක වෙනස්කමක් කරද්දී, අනිකට බලපාන එක අඩු වෙනවා. වැඩේ හරිම පිළිවෙලයි.
  • Faster Builds (ඕන කොටස විතරක් Build කරන්න පුළුවන්): මොනොලිතික් (Monolithic) Project එකක නම් පොඩි වෙනස්කමක් කරත් මුළු Project එකම Build කරන්න වෙනවා. ඒක වෙලාව නාස්ති කරන වැඩක්. Multi-Module එකකදී ඔයාට පුළුවන් වෙනස් වෙච්ච Module එක විතරක් Build කරන්න. ඒකෙන් Build Process එක ගොඩක් වේගවත් වෙනවා.
  • Easier Team Collaboration (එකම වෙලාවේ ගොඩ දෙනෙකුට වැඩ කරන්න පුළුවන්): ලොකු Team එකක වැඩ කරද්දී, Developers ලා කීප දෙනෙකුට එකම වෙලාවේ Project එකේ වෙන වෙන Modules වල වැඩ කරන්න පුළුවන්. ඒකෙන් Conflicts එන එක අඩු වෙනවා වගේම, Productively වැඩ කරන්නත් පුළුවන්.
  • Scalability (ව්‍යාපෘතිය ලොකු වෙනකොට ලේසියි): Microservices Architecture වලට යන්න ඕන නම්, මේ Multi-Module Project Structure එක හොඳ පදනමක් දෙනවා. මොකද, හැම Module එකක්ම වෙනම සේවාවක් විදියට වර්ධනය කරන්න පහසුයි.

දැන් ඔයාලට තේරෙනවා ඇති ඇයි මේ Multi-Module Projects මේ තරම් වැදගත් වෙන්නේ කියලා. එහෙනම් අපි බලමු කොහොමද මේක Set up කරගන්නේ කියලා.

Maven එක්ක වැඩේට බහිමු! (Setting Up with Maven)

Spring Boot Project එකක් Multi-Module විදියට හදද්දී, Build Automation Tool එකක් විදියට අපි Maven පාවිච්චි කරනවා නම්, මේක කරන්නේ `pom.xml` කියන File එක හරහා. අපි මුලින්ම Parent Project එකක් හදලා, ඊට පස්සේ Child Modules ටික එකතු කරනවා.

1. Parent Project එක හදමු:

මුලින්ම ඔයාලා කැමති Directory එකක Project එකට නමක් දෙන්න. උදාහරණයක් විදියට multi-module-parent කියලා. ඒක ඇතුළේ pom.xml File එකක් හදන්න. මේ Parent Project එකේ `packaging` Type එක `pom` විදියට තියෙන්න ඕනේ. ඒ වගේම ඔයාලගේ Child Modules ටික මේ Parent Project එකේ `modules` Tag එක ඇතුළේ List කරන්න ඕනේ.

<!-- multi-module-parent/pom.xml -->
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sc.multimodule</groupId>
    <artifactId>multi-module-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging> <!-- මේක තමයි ප්‍රධානම දේ -->

    <modules>
        <module>core</module>
        <module>api</module>
        <module>data</module>
    </modules>

    <!-- Common properties and dependencyManagement for all sub-modules -->
    <properties>
        <java.version>17</java.version>
        <spring-boot.version>3.2.5</spring-boot.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <!-- Spring Boot Maven Plugin for executable JAR -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <!-- Executable JAR is usually built in the 'api' module, so skip in parent -->
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2. Child Modules හදමු:

දැන් අපි Parent Project එක ඇතුළේ core, api, data කියන Modules ටික හදමු. හැම Module එකකම තමන්ගේම pom.xml File එකක් තියෙන්න ඕනේ. මේ හැම pom.xml File එකක්ම Parent Project එකට අයිතියි කියලා `parent` Tag එක ඇතුළේ සඳහන් කරන්න ඕනේ.

core Module:

මේක තමයි අපේ Project එකේ පදනම. Business Logic, Domain Classes (POJOs), Common Utilities වගේ දේවල් මේක ඇතුළේ තියෙනවා.

<!-- core/pom.xml -->
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.sc.multimodule</groupId>
        <artifactId>multi-module-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <artifactId>core</artifactId>
    <packaging>jar</packaging> <!-- මේක jar එකක් විදියට build වෙනවා -->

    <dependencies>
        <!-- Spring Boot Starter for basic Spring features -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- Add any other core dependencies -->
    </dependencies>
</project>

api Module:

මේ Module එකේ තමයි අපේ REST Controllers, DTOs (Data Transfer Objects) වගේ දේවල් තියෙන්නේ. මේක core Module එක මත රඳා පවතිනවා (depends).

<!-- api/pom.xml -->
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.sc.multimodule</groupId>
        <artifactId>multi-module-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <artifactId>api</artifactId>
    <packaging>jar</packaging> <!-- මේකත් jar එකක් -->

    <dependencies>
        <!-- Depend on the core module -->
        <dependency>
            <groupId>com.sc.multimodule</groupId>
            <artifactId>core</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- Spring Boot Starter for Web (REST APIs) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- For making this an executable Spring Boot application -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- The Spring Boot Maven plugin is specifically configured here to create an executable JAR for the main application -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <!-- version is inherited from parent -->
            </plugin>
        </plugins>
    </build>
</project>

data Module:

Database අදාල වැඩ ටික (JPA Entities, Repositories, Database Configurations) මේ Module එක ඇතුළේ තියෙනවා. මේකත් core Module එක මත රඳා පවතිනවා.

<!-- data/pom.xml -->
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.sc.multimodule</groupId>
        <artifactId>multi-module-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <artifactId>data</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <!-- Depend on the core module -->
        <dependency>
            <groupId>com.sc.multimodule</groupId>
            <artifactId>core</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- Spring Data JPA for database interactions -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- H2 Database for in-memory database example -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- Add actual database driver if needed -->
    </dependencies>
</project>

දැන් ඔයාලට පුළුවන් Parent Directory එකේ Command Line එක Open කරලා mvn clean install Command එක Run කරන්න. එතකොට හැම Module එකක්ම Build වෙලා, Local Maven Repository එකට Install වෙනවා.

Gradle එක්කත් බලමුකෝ! (Setting Up with Gradle)

Maven වගේම Gradle වලින් Multi-Module Project එකක් හදාගන්නත් පුළුවන්. Gradle, Maven වලට වඩා Flexible කියලා ගොඩක් අය කියනවා. අපි බලමු කොහොමද Gradle වලින් මේ වැඩේ ගොඩ දාගන්නේ කියලා.

1. settings.gradle File එක:

Gradle වලට Modules ටික හඳුන්වා දෙන්නේ settings.gradle කියන File එක හරහා. මේක Root Project එකේ තියෙන්න ඕනේ.

// settings.gradle
rootProject.name = 'multi-module-project'

// Include sub-modules
include 'core', 'api', 'data'

2. Root build.gradle File එක:

මේක තමයි Main `build.gradle` File එක. මේකේදී අපි හැම Module එකකටම පොදු වෙන Configurations, Dependencies වගේ දේවල් දානවා.

// build.gradle (root)
plugins {
    id 'java'
}

// Configurations common to all sub-modules
subprojects {
    apply plugin: 'java'
    // Apply Spring Boot and Dependency Management plugins to subprojects
    // 'apply false' means the plugin is defined, but not immediately applied to the root project
    apply plugin: 'org.springframework.boot' version '3.2.5' apply false
    apply plugin: 'io.spring.dependency-management' version '1.1.4' apply false

    group = 'com.sc.multimodule'
    version = '1.0.0-SNAPSHOT'

    repositories {
        mavenCentral()
    }

    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
    }

    dependencies {
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
    }

    java {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }
}

3. Child Modules වල build.gradle Files:

දැන් අපි හැම Child Module එකකම තමන්ගේම build.gradle File එක හදමු.

core Module:

// core/build.gradle
dependencies {
    // Use Spring Boot BOM for consistent dependency versions
    implementation platform('org.springframework.boot:spring-boot-dependencies:3.2.5')
    implementation 'org.springframework.boot:spring-boot-starter'
}

api Module:

// api/build.gradle
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

dependencies {
    // Depend on the core module using project reference
    implementation project(':core')
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

// Spring Boot executable JAR configuration for the API module
bootJar {
    enabled = true
}

data Module:

// data/build.gradle
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

dependencies {
    // Depend on the core module
    implementation project(':core')
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'com.h2database:h2'
}

දැන් Root Project එකේ Command Line එක Open කරලා ./gradlew clean build Command එක Run කරන්න. එතකොට හැම Module එකක්ම Build වෙලා අවුලක් නැතුව වැඩේ ගොඩ දාගන්න පුළුවන්.

අපේ App එක මොඩියුලවලට කඩමු! (Splitting Your Application into Modules)

දැන් අපි බලමු අපේ Application එක core, api, data කියන ප්‍රධාන Modules තුනට කොහොමද කඩලා දාන්නේ කියලා. මේක තමයි මේකේ තියෙන ප්‍රධානම කොටස. මේකෙන් තමයි Codebase එකේ Cleanliness එකයි, Maintainability එකයි තීරණය වෙන්නේ.

1. core Module (පදනම)

මේ Module එක තමයි අපේ Application එකේ හදවත. මේකේ තියෙන්න ඕනේ:

  • Domain Models/POJOs: Product, User, Order වගේ Business Objects. මේවාට කිසිම Spring JPA Annotations, Web Annotations වගේ දේවල් අදාල නැහැ. මේවා Plain Old Java Objects.
  • Service Interfaces: Business Logic එක ක්‍රියාත්මක කරන Services වල Interfaces (e.g., ProductService, UserService). මේවා Implement කරන්නේ api හෝ data Modules වල.
  • Common Utilities: Project එකටම අදාල පොදු Utility Classes (e.g., DateUtils, ValidationUtils).
  • Exceptions: Custom Exceptions වගේ දේවල්.

මතක තියාගන්න: core Module එකට වෙන කිසිම Module එකක් Depend වෙන්න බෑ. මේක ස්වාධීනයි. මේක තමයි හැම Module එකකටම අවශ්‍ය පොදු දේවල් තියෙන තැන.

2. data Module (දත්ත ගබඩාව)

මේ Module එකේදී අපි Database අදාල වැඩ ටික කරනවා. මේකේ තියෙන්න ඕනේ:

  • JPA Entities: core Module එකේ තියෙන Domain Models ටිකට `@Entity` වගේ JPA Annotations එකතු කරලා Database Tables එක්ක Map කරන Class.
  • Repositories: Spring Data JPA `JpaRepository` Interfaces. මේවා Database එක්ක Interact වෙන්න අවශ්‍ය ක්‍රම සපයනවා.
  • Database Configurations: `DataSource`, `EntityManagerFactory` වගේ දේවල් Configure කරන Classes.
  • Service Implementations: core Module එකේ තියෙන Service Interfaces වල Database Interaction කොටස Implement කරන Classes.

Dependency: data Module එක core Module එක මත රඳා පවතිනවා.

3. api Module (සන්නිවේදන අතුරු මුහුණත)

මේ Module එක තමයි අපේ Application එකේ External World එකත් එක්ක Interact වෙන්නේ කොහොමද කියලා තීරණය කරන්නේ. මේකේ තියෙන්න ඕනේ:

  • REST Controllers: `@RestController` Annotations එක්ක Web Requests Handle කරන Classes.
  • DTOs (Data Transfer Objects): Requests සහ Responses වලට පාවිච්චි කරන Classes. මේවා Domain Models වලට වඩා වෙනස් වෙන්න පුළුවන්, External API එකට අවශ්‍ය විදියට.
  • Service Implementations: core Module එකේ තියෙන Service Interfaces වල Business Logic ක්‍රියාත්මක කරන Classes. මේවා Database Layers (data Module) එක්ක Interact වෙන්න පුළුවන්.
  • Main Application Class: Spring Boot Application එක Run කරන්න අවශ්‍ය `main` method එක තියෙන Class එක (@SpringBootApplication).

Dependency: api Module එක core Module එක මත රඳා පවතිනවා. ඒ වගේම අවශ්‍ය නම් data Module එක මතත් රඳා පවතින්න පුළුවන් (හැබැයි මේක ටිකක් හිතලා කරන්න ඕනේ, api එක කෙලින්ම data එක්ක කතා කරන්නේ නැතුව core services හරහා කතා කරන එක හොඳයි).

සරලවම කිව්වොත්:
api Module එක core Module එකෙන් Service Interfaces ගන්නවා. data Module එක core Module එකෙන් Domain Models ගන්නවා. api Module එක data Module එකේ Service Implementations පාවිච්චි කරනවා. මේක තමයි සාමාන්‍යයෙන් තියෙන Flow එක.

වැදගත් Tips ටිකක්! (Best Practices & Tips)

මේ Multi-Module වැඩේ පටන් ගනිද්දී මතක තියාගන්න ඕනේ වැදගත් Tips ටිකක් තියෙනවා:

  • Version Management: Maven වල dependencyManagement Tag එකයි, Gradle වල platform එකයි පාවිච්චි කරලා හැම Module එකකම Dependencies වල Versions එක තැනකින් Manage කරන්න. එතකොට හැම Module එකකම එකම Version එක Use වෙනවා.
  • Separate Concerns Strictly: හැම Module එකකටම පැහැදිලි වගකීමක් දෙන්න. එක Module එකක තියෙන්න ඕනේ කෝඩ් එක, අනිකට දාන්න යන්න එපා. උදාහරණයක් විදියට, core Module එකේ Database Annotations දාන්න එපා.
  • Avoid Circular Dependencies: Modules දෙකක් එකිනෙකාට Depend වෙන්න දෙන්න එපා (A -> B, B -> A වගේ). මේකෙන් Build Issues එන්න පුළුවන් වගේම, Code Maintain කරන්න අමාරු වෙනවා.
  • Testing Strategy: හැම Module එකකටම තමන්ගේම Unit Tests තියෙන්න ඕනේ. ඒ වගේම, api Module එක ඇතුළේ End-to-End Tests නැත්නම් Integration Tests දාන්න පුළුවන්, මුළු Application එකම එකට වැඩ කරනවද කියලා බලන්න.
  • Naming Conventions: Modules වලට තේරුමක් තියෙන නම් දෙන්න. (e.g., my-app-core, my-app-api, my-app-data).
  • CI/CD Optimization: Multi-Module Project එකක් CI/CD Pipeline එකකට හරිම පහසුයි. ඔයාට පුළුවන් වෙනස් වෙච්ච Modules විතරක් Build කරලා Deploy කරන්න. මේකෙන් Build Time එක අඩු කරගන්න පුළුවන්.

අවසන් වදන

ඉතින් යාලුවනේ, ඔයාලා දැන් Spring Boot Multi-Module Projects ගැන හොඳ අවබෝධයක් ලැබුවා කියලා මම හිතනවා. මුලදී මේක ටිකක් සංකීර්ණ වගේ පෙනුනත්, ඇත්තටම මේක හරිම බලවත් concept එකක්. විශේෂයෙන්ම ලොකු Projects වලදී මේකෙන් Code Quality එක, Maintainability එක, Scalability එක ගොඩක් වැඩි දියුණු වෙනවා. මේක චන්ඩි වැඩක්!

මේ Guide එකේ තියෙන විදියට ඔයාලගේම Multi-Module Project එකක් හදලා බලන්න. Maven නැත්නම් Gradle, ඔයාලට පහසු Build Tool එකක් පාවිච්චි කරන්න. ඒ වගේම core, api, data Modules වලට ඔයාලගේ Project එක බෙදලා දාන්න උත්සාහ කරන්න. මේක ඔයාලට Software Architecture ගැන හොඳ අවබෝධයක් ලබාගන්න ගොඩක් උදව් වෙයි.

ඔයාලට මේ Guide එක ගැන මොනවද හිතෙන්නේ? ඔයාලා කලින් Multi-Module Projects එක්ක වැඩ කරලා තියෙනවද? එහෙමනම් ඔයාලගේ අත්දැකීම් මොනවද? නැත්නම් මේක ගැන මොනවා හරි ප්‍රශ්න තියෙනවා නම්, පහළින් Comments එකේ කියන්න. අපි කතා කරමු.

එහෙනම් තවත් අලුත් Technical Guide එකකින් හමුවෙමු! Happy Coding!