Building the Spring Boot Application
Creating a Spring Boot Application
আপনি একটি free preview lesson দেখছেন।
এখন পর্যন্ত আমরা intentionally code লেখা শুরু করিনি।
আমরা প্রথমে বুঝেছি:
Product Requirement
↓
Acceptance Criteria
↓
Engineering Context
↓
Backlog
↓
Technical Design
↓
RFC
↓
ADR
↓
Design Review
এখন design sufficiently clear।
তাই এবার implementation শুরু করার সময়।
আমাদের প্রথম ticket:
BACKEND-101
Bootstrap Order Management Backend
এই lesson-এ আমরা একটি minimal কিন্তু production-oriented Spring Boot application তৈরি করব।
Goal হলো যত দ্রুত সম্ভব অনেক dependencies বা folders তৈরি করা নয়।
Goal:
একটি clean, reproducible Java application foundation তৈরি করা যার উপর পুরো Order Management Backend evolve করবে।
Ticket: BACKEND-101
আমাদের initial backlog অনুযায়ী:
# BACKEND-101 — Bootstrap Order Management Backend
## Context
আমাদের backend implementation-এর জন্য initial Spring Boot application প্রয়োজন।
## Scope
- Create the Gradle project.
- Configure Spring Boot.
- Establish the application entry point.
- Add baseline project configuration.
- Verify the application can build and start locally.
## Acceptance Criteria
- The project builds successfully with Gradle.
- The Spring Boot application starts successfully.
- The repository contains the agreed baseline project structure.
- A clean checkout can be built without IDE-specific setup.
## Out of Scope
- Product APIs
- Database schema
- Authentication
- Order logic
- Payment integration
- Production Docker setup
এই scope আমাদের implementation guide করবে।
Start With the Ticket, Not Spring Initializr
Spring Boot project তৈরি করতে technically কয়েক মিনিটই লাগে।
কিন্তু একজন backend engineer-এর প্রশ্ন হওয়া উচিত না:
কোন checkbox select করব?
প্রথম প্রশ্ন:
এই ticket complete করার জন্য minimum কী দরকার?
বর্তমানে দরকার:
Java project
Gradle build
Spring Boot runtime
application entry point
basic configuration
repeatable build
এই মুহূর্তে দরকার নেই:
PostgreSQL
JPA
Flyway
Spring Security
WebClient
Testcontainers
Payment SDK
সেগুলো later tickets/modules-এ আসবে যখন requirement থাকবে।
Avoid Dependency Shopping
নতুন Spring Boot project শুরু করার সময় common mistake:
Spring Web
Spring Data JPA
PostgreSQL
Security
Redis
Kafka
Actuator
Validation
WebFlux
Lombok
...
সব একসাথে add করা।
Reason:
"Eventually লাগবে।"
এই approach-এর problem:
larger dependency surface
more configuration
more startup behaviour
more things to understand
more accidental architecture
আমাদের principle:
Add a dependency when a current engineering requirement needs it.
Initial Technology Choices
Engineering context already established:
Language:
Java
Framework:
Spring Boot
Build Tool:
Gradle
তাই এগুলো নিয়ে নতুন comparison দরকার নেই।
আমরা project foundation তৈরি করব এই assumptions-এর উপর।
Repository Name
আমাদের project:
order-management
Repository root conceptually:
order-management/
├── build.gradle
├── settings.gradle
├── gradlew
├── gradlew.bat
├── gradle/
└── src/
Later repository evolve হবে:
order-management/
├── src/
├── docs/
│ ├── rfcs/
│ ├── adr/
│ └── incidents/
├── docker/
├── compose.yaml
├── Dockerfile
└── README.md
কিন্তু সব file এখনই দরকার নেই।
Why Use the Gradle Wrapper?
একটি Gradle project-এ আমরা সাধারণত run করি:
./gradlew build
instead of requiring every engineer to install a particular Gradle version globally।
Wrapper files:
gradlew
gradlew.bat
gradle/wrapper/
project-এর সঙ্গে থাকে।
Benefit:
developer machine
CI
another engineer
সবাই project-defined Gradle version ব্যবহার করতে পারে।
This supports our acceptance criterion:
A clean checkout can be built without IDE-specific setup.
Build Reproducibility Matters
Weak setup:
Works from IntelliJ on my machine.
Strong setup:
git clone
./gradlew build
works।
IDE convenience useful।
কিন্তু IDE project-এর build system নয়।
Our source repository must remain the source of truth।
Initial Gradle Project
A minimal settings.gradle:
rootProject.name = 'order-management'
এর কাজ simple:
Gradle project name define করা
এখানে application architecture configure করার দরকার নেই।
Initial build.gradle
A minimal Spring Boot Gradle build conceptually:
plugins {
id 'java'
id 'org.springframework.boot' version '<spring-boot-version>'
id 'io.spring.dependency-management' version '<dependency-management-version>'
}
group = 'io.liveklass'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
এখানে version placeholder intentionally দেখানো হয়েছে।
Actual project bootstrap-এর সময় team-supported current versions project build-এর মধ্যে pin করা হবে।
Important হলো structure বুঝতে পারা।
Why Java Toolchains?
এই block:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
build-এর expected Java language/runtime toolchain clearly declare করে।
এর benefit:
developer environment consistency
CI consistency
explicit project requirement
Without this, build accidentally developer machine-এর default Java version-এর উপর depend করতে পারে।
Why Not "Whatever Java Is Installed"?
Imagine:
Engineer A → Java 21
Engineer B → Java 25
CI → another version
Then subtle differences appear।
A production project should state its supported Java baseline explicitly।
Why Only spring-boot-starter?
At this exact stage, আমাদের requirement শুধু Spring Boot application start করা।
Therefore:
implementation 'org.springframework.boot:spring-boot-starter'
is enough conceptually।
We are not yet exposing REST endpoints।
Later REST module needs:
Spring Web
Persistence module needs:
Spring Data JPA
PostgreSQL driver
Flyway
Security module needs:
Spring Security
Each dependency should arrive with a reason।
Test Dependency
We include:
testImplementation 'org.springframework.boot:spring-boot-starter-test'
because testing is already part of our Definition of Done।
Even bootstrap work should be buildable and testable।
We are not postponing testing until Module 10।
Module 10 will deepen testing strategy।
Project Source Structure
Standard Java structure:
src/
├── main/
│ ├── java/
│ └── resources/
└── test/
└── java/
Meaning:
src/main/java
→ application source code
src/main/resources
→ application resources/configuration
src/test/java
→ automated tests
Spring Boot works naturally with this structure।
Base Package
Suppose our package root is:
io.liveklass.ordermanagement
Then:
src/main/java/io/liveklass/ordermanagement/
contains the application।
Why use a proper package root?
Because Java package names provide:
namespace
code organization
component scanning boundary
Later capabilities can live below it:
io.liveklass.ordermanagement.product
io.liveklass.ordermanagement.inventory
io.liveklass.ordermanagement.order
io.liveklass.ordermanagement.payment
io.liveklass.ordermanagement.security
We don't need to create all those packages yet।
Why the Main Class Belongs at the Root
Our application entry point can live at:
io.liveklass.ordermanagement.OrderManagementApplication
This is useful because Spring Boot's default component scanning starts from the package containing the main application class and includes subpackages।
Conceptually:
io.liveklass.ordermanagement
├── OrderManagementApplication
├── product
├── inventory
└── order
is a natural structure।
Application Entry Point
Our main class:
package io.liveklass.ordermanagement;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderManagementApplication {
public static void main(String[] args) {
SpringApplication.run(
OrderManagementApplication.class,
args
);
}
}
This is the entry point for the application।
What Does main Do?
Normal Java program starts from:
public static void main(String[] args)
Spring Boot does not change that fundamental Java rule।
We still have a normal Java entry point।
Inside it:
SpringApplication.run(...)
bootstraps Spring Boot।
Conceptually:
JVM starts
↓
main(...)
↓
SpringApplication.run(...)
↓
Spring Application Context created
↓
configured application starts
@SpringBootApplication
This annotation:
@SpringBootApplication
is central to Spring Boot startup।
For now think of it as the annotation that marks our primary Spring Boot application configuration।
It enables Spring Boot's core startup conventions, including configuration and component discovery behaviour।
We will unpack Beans এবং Application Context properly in upcoming lessons।
For this lesson, important point:
It tells Spring Boot where our application starts.
Don't Memorize the Annotation Yet
A beginner often sees:
@SpringBootApplication
and thinks:
I need to memorize this annotation.
Better question:
What responsibility is it fulfilling?
Answer:
bootstrap/configuration entry point
Later যখন আমরা application context বুঝব, annotation-এর behaviour much clearer হবে।
Application Configuration File
Inside:
src/main/resources/
we can create:
application.yml
Initial file can remain minimal:
spring:
application:
name: order-management
This gives the Spring application an explicit name।
We do not need to fill configuration with future database/payment/security properties yet।
Why YAML?
Spring Boot supports multiple property formats।
Our project can choose:
application.yml
for readable structured configuration।
This is a project convention, not a deep architecture decision।
Consistency matters more than arguing YAML vs .properties for every project।
Don't Put Secrets Here
Even at bootstrap stage, establish the correct habit:
Bad:
payment:
api-key: super-secret-key
committed into Git।
Later external credentials should come from appropriate external configuration/environment mechanisms।
We'll cover this properly in production-readiness lessons।
Initial Project Structure
After bootstrap:
order-management/
├── build.gradle
├── settings.gradle
├── gradlew
├── gradlew.bat
├── gradle/
│ └── wrapper/
│
└── src/
├── main/
│ ├── java/
│ │ └── io/
│ │ └── liveklass/
│ │ └── ordermanagement/
│ │ └── OrderManagementApplication.java
│ │
│ └── resources/
│ └── application.yml
│
└── test/
└── java/
└── io/
└── liveklass/
└── ordermanagement/
এটাই যথেষ্ট initial foundation।
Where Are Product and Order Packages?
এখনও নেই।
Why?
Because:
BACKEND-101
does not implement Product or Order।
Architecture design says those capabilities will exist।
But empty folders/classes create করলে কোনো meaningful implementation হয় না।
We'll create them when the corresponding work begins।
Avoid Architecture by Empty Folder
Bad bootstrap:
product/
controller/
service/
repository/
entity/
dto/
mapper/
order/
controller/
service/
repository/
entity/
dto/
mapper/
সব empty।
এটি architecture নয়।
এটি speculative folder generation।
Good architecture becomes visible as actual responsibilities arrive।
First Build
Now run:
./gradlew build
What should happen conceptually?
Gradle:
reads build.gradle
↓
resolves dependencies
↓
compiles main source
↓
compiles test source
↓
runs tests
↓
packages application
If successful:
BUILD SUCCESSFUL
This satisfies an important part of BACKEND-101।
Why Build Before Running?
Because application running from IDE can hide build problems।
Running:
./gradlew build
first verifies:
project definition
dependency resolution
compilation
tests
packaging
We want the repository build to be healthy before development continues।
Running the Application
Run:
./gradlew bootRun
Spring Boot starts the application।
Conceptually you'll see startup logs indicating application initialization।
At this stage we don't necessarily have an HTTP server because we haven't added the web starter yet।
That is okay।
Our current acceptance criterion says:
Spring Boot application starts successfully.
It does not say:
GET /products works.
That is future scope।
Another Way to Run the Application
After:
./gradlew build
Spring Boot produces an executable application artifact under:
build/libs/
It can be run using Java:
java -jar build/libs/<application-jar>.jar
This is valuable because it verifies the application runs outside IDE tooling।
IDE Is Optional to the Build
You can use:
IntelliJ IDEA
VS Code
another Java IDE
for development।
But our workflow should remain:
Repository
+
Gradle
=
authoritative build
not:
IDE project configuration
=
authoritative build
This matters enormously in CI later।
First Test
A standard Spring Boot bootstrap test may look like:
package io.liveklass.ordermanagement;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class OrderManagementApplicationTests {
@Test
void contextLoads() {
}
}
The test appears almost empty।
But its purpose is specific:
Can Spring create the application context successfully?
What Does contextLoads() Actually Protect?
Suppose later configuration becomes invalid:
missing required bean
invalid configuration
broken dependency wiring
A context startup test may catch some classes of application bootstrap failure।
At the bootstrap stage, this is reasonable coverage।
But Don't Overvalue contextLoads()
Passing:
contextLoads()
does not mean:
business logic correct
database correct
API correct
security correct
It only provides startup-level confidence।
Testing should always correspond to behaviour being protected।
Testing Starts With the Work
For BACKEND-101, relevant behaviours are:
project compiles
Spring context can start
build succeeds
Therefore bootstrap test is appropriate।
Later Product behaviour gets Product tests।
Order behaviour gets Order tests।
We do not write fake business tests before those features exist।
Build Artifact
After a successful build:
build/
contains generated outputs।
This directory should not be committed into Git।
Why?
Because it is reproducible build output।
Source repository should contain:
source
build definition
configuration
migrations
documentation
not generated build artifacts।
.gitignore
A basic .gitignore should account for generated/local files।
For example:
.gradle/
build/
.idea/
*.iml
.vscode/
.DS_Store
Exact IDE entries depend on team conventions।
Important principle:
Don't commit machine-generated local state unless the repository intentionally owns it.
Gradle Wrapper Is Different
Do not ignore:
gradlew
gradlew.bat
gradle/wrapper/
These are intentionally committed because they are part of reproducible project tooling।
Distinguish:
generated build output
from:
versioned build tooling
README at Bootstrap Stage
A lightweight README.md can help another engineer start the project।
Example:
# Order Management Backend
Backend service for the Commerce Order Management project.
## Requirements
- Supported Java version
- Docker later when local infrastructure is introduced
## Build
```bash
./gradlew build
Run
./gradlew bootRun
README should describe what actually works now।
Don't document fictional future commands।
---
# Clean Checkout Test
One of our acceptance criteria:
> A clean checkout can be built without IDE-specific setup.
How do we validate this?
Conceptually:
```text
fresh repository checkout
↓
supported Java available
↓
./gradlew build
should succeed।
This is a powerful test of project bootstrap quality।
Hidden Local Dependencies
Imagine build works only because your machine has:
manually installed library
IDE-specific generated source
custom local environment variable
uncommitted configuration
Then project is not reproducible।
BACKEND-101 exists partly to prevent this problem before the codebase grows।
Should We Add PostgreSQL Now?
No।
That's:
BACKEND-102
Configure PostgreSQL and Flyway
If we add PostgreSQL here:
- BACKEND-101 scope expands
- first application startup now depends on database
- we mix two separate engineering concerns
We intentionally keep tickets bounded।
Should We Add Spring Web Now?
Our immediate project eventually exposes REST APIs।
Could we add Spring Web early?
Technically yes।
But current ticket doesn't need HTTP behaviour yet।
The course plan will introduce Spring Boot structure, DI, Beans, configuration, and later REST APIs deliberately।
We can introduce web dependency when we begin the HTTP application boundary rather than treating dependencies as future placeholders।
Should We Add Actuator Now?
Not yet।
Actuator belongs to production readiness later।
Adding it now without using or explaining it gives the learner a dependency without context।
We'll add it when health checks and metrics become actual requirements।
Should We Add Lombok?
No current requirement demands it।
Java records, constructors, IDE generation, and normal language features already give us options।
Introducing Lombok would add an additional compile-time dependency and learning surface।
We don't need it for bootstrap।
This is not a statement that Lombok is universally bad।
It simply has no current justification।
Should We Add MapStruct?
No।
We don't even have DTO/domain mapping complexity yet।
Don't install a solution before we have the problem।
Build Configuration Is Production Code
Developers sometimes think:
src/main/java
=
real code
build.gradle
=
boring setup
But broken build configuration can stop the entire engineering team।
build.gradle determines:
dependencies
Java version
test execution
packaging
plugins
It is part of the product's engineering system।
Treat changes to it carefully।
Dependency Versions Must Be Controlled
One developer should not randomly update framework versions because:
newer is available
Dependency changes can affect:
runtime behaviour
security fixes
compatibility
build behaviour
In a real team, significant upgrades are explicit engineering changes।
For this course, dependencies will evolve only when required by the roadmap।
Package Naming Matters, but Don't Overthink It
Our base package should be:
io.liveklass.ordermanagement
or another agreed organization-specific namespace।
We need consistency।
We don't need architecture meetings about:
ordermanagement
vs
order_management
vs
orderservice
once a clear convention is chosen।
Spend design effort on important decisions।
Application Name
Configuration:
spring:
application:
name: order-management
is useful because application identity later appears in operational contexts such as:
logs
metrics
configuration
deployment
Naming consistently from the start avoids unnecessary drift।
0.0.1-SNAPSHOT
A Gradle version like:
version = '0.0.1-SNAPSHOT'
simply indicates an early development artifact version।
We are not designing a full release-versioning policy in this lesson।
Version strategy belongs to delivery/release process later।
What Have We Actually Built?
At this point, very little business functionality exists।
That is intentional।
We have:
a valid Java project
a Gradle build
a Spring Boot runtime
an application entry point
baseline configuration
a bootstrap test
reproducible commands
This is foundation, not feature delivery।
Why This Is Still Meaningful Engineering Work
Every future ticket depends on a healthy application foundation।
If bootstrap is chaotic:
different Java versions
IDE-only builds
uncontrolled dependencies
random package structure
every feature pays that cost।
BACKEND-101 creates a stable starting point।
Definition of Done Review
Now apply our project Definition of Done।
Scope
Did we implement agreed scope?
[✓] Gradle project exists
[✓] Spring Boot configured
[✓] Application entry point exists
[✓] Baseline configuration exists
[✓] Application builds and starts
Acceptance Criteria
[✓] ./gradlew build succeeds
[✓] Spring Boot application starts
[✓] Baseline project structure exists
[✓] Build does not depend on IDE-specific setup
Testing
Relevant automated test:
[✓] Spring application context startup test
Existing tests:
[✓] pass
Build
[✓] clean Gradle build succeeds
Scope Discipline
Did we add:
Product API?
Database?
Security?
Payment?
Docker production setup?
No।
Good।
Example Pull Request
Our team workflow says implementation should eventually go through a Pull Request।
A reasonable PR description:
## What
Bootstraps the Order Management Backend as a Spring Boot Gradle application.
## Why
Provides the application foundation required for subsequent backend capabilities.
## Changes
- Added Gradle project and wrapper
- Added Spring Boot application entry point
- Added baseline application configuration
- Added application-context bootstrap test
- Added basic project documentation
## Testing
- `./gradlew build`
- Application started with `./gradlew bootRun`
## Risks
Low. This change introduces the initial application foundation and no business functionality.
This is a good example of a small, reviewable first PR।
What Should the Reviewer Check?
Reviewer should not spend most of the review debating whitespace।
Important questions:
Does clean build work?
Is the Java baseline explicit?
Are unnecessary dependencies included?
Is the package root reasonable?
Can the application start outside the IDE?
Is configuration minimal and safe?
Does the change stay within BACKEND-101 scope?
This keeps review aligned with the ticket।
Example Review Feedback
Reviewer:
PostgreSQL dependency is included, but this ticket does not configure or use a database. Can we add it with BACKEND-102 instead?
Good feedback।
Response:
Yes.
Remove the unused dependency.
This improves dependency discipline।
Another Review Comment
Reviewer:
There are empty
product,inventory,order, andpaymentpackage hierarchies. Nothing uses them yet.
Again useful।
Response:
Remove them.
Create capability structure as implementation reaches each capability.
Architecture exists in our design docs।
Empty folders are not required to prove it।
Keep the Main Branch Buildable
After BACKEND-101 merges, main branch should be in a state where:
./gradlew build
passes।
This will become an ongoing expectation।
Every future change starts from a healthy baseline and should leave one behind।
Small PR, Important Foundation
Our first implementation PR is intentionally small।
That gives us:
easy review
clear ownership
simple rollback
clean project history
Future Git history may look like:
BACKEND-101 Bootstrap Order Management Backend
BACKEND-102 Configure PostgreSQL and Flyway
BACKEND-103 Model Product Domain
...
This tells a coherent engineering story।
Spring Boot Is Now a Tool, Not the Course Goal
Notice how Spring Boot entered the course।
We did not begin with:
Today we will learn @SpringBootApplication.
We began with:
We need to bootstrap the agreed backend application.
Then Spring Boot solved that need।
This is exactly the mindset we want throughout the course:
Problem first. Technology second.
What We Have Not Learned Yet
There are important Spring concepts we have only touched lightly:
project structure
dependency injection
beans
application context
configuration
These are upcoming lessons।
We don't need to fully explain every Spring mechanism in the first implementation lesson।
Learning will follow the system as it evolves।
Where We Are Now
Module 3:
Creating a Spring Boot Application
↓
Understanding Spring Boot Project Structure
↓
Dependency Injection
↓
Beans and the Application Context
↓
Configuration and Application Properties
↓
Environment-Specific Configuration
↓
Structuring a Backend Codebase
↓
Running the Application Locally
BACKEND-101 will evolve through these lessons।
This lesson established the executable foundation।
Engineering Principle
The core principle:
A project bootstrap should establish the minimum reproducible foundation required for the next piece of meaningful work.
Another:
Dependencies, packages, and infrastructure should be added because the current system needs them—not because we expect every backend might eventually use them.
And:
If the project only works through one developer's IDE, the project is not properly bootstrapped.
Summary
In this lesson, we established that:
- BACKEND-101 is the first implementation ticket.
- The initial application is a Gradle-based Spring Boot project.
- The repository build, not the IDE, is the source of truth.
- Gradle Wrapper makes the project build reproducibly across environments.
- The Java baseline should be explicit.
- The Spring Boot main class provides the application entry point.
@SpringBootApplicationmarks the primary application bootstrap configuration.SpringApplication.run(...)starts the Spring application.- Initial configuration should remain minimal.
- Secrets must not be committed into application configuration.
- We should not pre-install PostgreSQL, Security, Redis, Kafka, Actuator, or other dependencies before their requirements arrive.
- Empty package hierarchies do not make an architecture.
./gradlew buildshould succeed from a clean checkout../gradlew bootRunprovides a build-system-driven way to start the application.- A basic application-context test is appropriate for the bootstrap ticket.
- Testing begins with implementation rather than being postponed to a later module.
- Build configuration is part of production engineering, not incidental setup.
- BACKEND-101 should result in a small, focused, reviewable Pull Request.
- The main branch should remain buildable after the bootstrap change.
Next lesson:
Understanding Spring Boot Project Structure
There we will examine the project we just created and understand what each part of the repository actually does, how Java package placement affects Spring Boot behaviour, where configuration/resources/tests belong, and how to avoid turning a growing backend into an unstructured collection of files.