The Splittable Monolith with Spring Boot and Gradle multi module project – Part 1

Motivation and Idea

Nowadays a lot of new projects tend to apply the microservice-architecture right away. Sometimes it’s the right way, especially if the analysis is done, the domain is broken-down on pieces and all technical aspects are clear. But what if we deal with prototyping and this step is not done yet. Usually, in this case, available resources are limited as well as time.

There are a lot of teams, which started to develop a bunch of microservices at the very beginning, but as infrastructure growth as well as codebase, they spent more and more time fixing infrastructure issues instead of concentrating on business.

In this tutorial, we’ll try to come up with an approach, how to start a project from the monolith, which can be easily broken into separate services as infrastructure and load growth. We will also build a sample project based on Spring Boot using Gradle multimodule project.

In the tutorial, a very simplified gaming domain will be used. As, an example, “game of dice” will be implemented.

We are going to split all modules by business responsibility or domain. And another module we will add is Launcher. It’s a separate, not a business module, which doesn’t cover any part of a domain but is responsible for bootstrapping of infrastructure. The launcher will also keep all common components. In case, if an application needs to be split into separate services, the Launcher gets “copied” to each service if needed. Although some changes could be still required there, the process can be done with minimal effort (figure below).

As a use case for this tutorial, we will be using an extremely simplified version of the online game service.

The Monolith to separate web-services

The rules we should follow

Probably, the most important rule says that all modules should be decoupled and isolated from each other as much as possible.

And since all parts of the application are running in the same runtime, we should pay attention to the configuration and define it carefully. Configuration (Spring java configuration in our case) of each module should configure only its own module, not overlap with other modules.

All interactions between modules should be defined by contract and restricted within agreed-upon boundaries.

We should avoid the application from keeping a state. In other words, the application should be stateless.

Bootstrapping new Gradle multi-module project

For project we are going to user:

  1. Java 11
  2. Gradle 5.2.1
  3. Spring boot 2.2.6.RELEASE

Now, lets create a new Gradle multi-module project. Its structure looks like (gradle-specific files are omited):

File (1) settings.gradle contains set of modules to be included into the root project as well as name of root project:

rootProject.name = 'multimodule'
include 'launcher'
include 'user-registry'
include 'user-account'
include 'game-service'

File (2) build.gradle of root project contains definition of dependency-management plugin and configuration of subprojects:

plugins {
	id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}

subprojects {
	group = 'com.dicelogics.demo'
	version = '0.0.1-SNAPSHOT'

	apply plugin: 'java'
	apply plugin: 'io.spring.dependency-management'
	apply plugin: 'java-library'

	repositories {
		jcenter()
	}

	dependencyManagement {
		imports {
			mavenBom('org.springframework.boot:spring-boot-dependencies:2.2.6.RELEASE')
		}
	}

	compileJava {
		sourceCompatibility = 1.8
		targetCompatibility = 1.8
	}
}

Notice, that we are going to use Maven BOM for dependency management of version 2.2.6.RELEASE.

File (4) build.gradle of the Launcher looks like:

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.2.6.RELEASE'
}

group 'com.dicelogics.demo'
version '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'

    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

test {
    useJUnitPlatform()
}

For now, we’ve added only org.springframework.boot:spring-boot-starter-web, so now we have a basic configuration of web-application

Files (3), (5) and (6) are “empty” and looks pretty the same for now:

plugins {
    id 'java'
}

group 'com.dicelogics.demo'
version '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

Let’s add a ping controller just for demonstration purposes. ./launcher/controller/PingController.java into launcher:

package com.dicelogics.demo.multimodule.launcher.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserRegistryRestController {

    @GetMapping(path = "/api/ping")
    public String ping() {
        return "OK";
    }
}

Now we can run the project:

./gradlew bootRun

The project skeleton is done. And we have basic project configuration, which consists of 4 Gradle-modules – 3 business modules and 1 launcher.

Next step – Configuration of isolated persistent units.

457
Leave a Reply

avatar
  Subscribe  
newest oldest most voted
Notify of
Kiashoox
Guest
Amyshoox
Guest
Lisashoox
Guest
Lisashoox
Guest
Kiashoox
Guest
Amyshoox
Guest
Amyshoox
Guest
Amyshoox
Guest
Carlshoox
Guest
Kiashoox
Guest
Eyeshoox
Guest
Paulshoox
Guest
Lisashoox
Guest
Jasonshoox
Guest
Kiashoox
Guest
Carlshoox
Guest
Alanshoox
Guest
Judyshoox
Guest
Judyshoox
Guest
Maryshoox
Guest
Markshoox
Guest
Markshoox
Guest
Amyshoox
Guest
Paulshoox
Guest
Eyeshoox
Guest
Jasonshoox
Guest
Lisashoox
Guest
Maryshoox
Guest
Eyeshoox
Guest
Denshoox
Guest
Kiashoox
Guest
Alanshoox
Guest
Markshoox
Guest
Carlshoox
Guest
Maryshoox
Guest
Paulshoox
Guest
Denshoox
Guest
Lisashoox
Guest
Judyshoox
Guest
Alanshoox
Guest
Jasonshoox
Guest
Carlshoox
Guest
Kiashoox
Guest
Alanshoox
Guest
Paulshoox
Guest
Maryshoox
Guest
Amyshoox
Guest
Denshoox
Guest
Jasonshoox
Guest
Lisashoox
Guest