This content originally appeared on DEV Community and was authored by Jack Pritom Soren
Welcome — this is Chapter 1 of a beginner-friendly, deep-dive mini-course on Spring Boot. We’ll cover everything you need to get started: what Spring Boot is, how to install Java/IntelliJ/Maven on Windows/Ubuntu/macOS, creating a project (Spring Initializr + IntelliJ), Maven basics, the standard project structure, how @SpringBootApplication
works (IOC / DI), and a step-by-step REST API CRUD example using Spring Boot + H2. I’ll keep explanations concrete and show small, copy-pasteable code examples.
What is Spring Boot? (short deep dive)
Spring Boot is an opinionated framework built on top of the Spring ecosystem that makes it fast and straightforward to build production-ready applications. It:
- Auto-configures components for common use-cases so you don’t write boilerplate configuration.
- Provides starters (e.g.,
spring-boot-starter-web
) that bring together common dependencies. - Runs with an embedded server (Tomcat by default) so you can run apps as standalone JARs.
- Includes developer conveniences (DevTools), metrics and health checks (Actuator), and easy packaging via Maven/Gradle plugins.
Why use Spring Boot? it lets you focus on business logic instead of wiring up servers, servlet containers, or complicated XML configs.
Prerequisites for this chapter
- Basic familiarity with Java (classes, annotations).
- A computer (Windows / Ubuntu / macOS).
- Terminal/command-line comfort.
- We’ll use Java 17+ (LTS) or newer. Spring Boot 3+ requires Java 17+.
1. Install Java & IntelliJ (Windows / Ubuntu / macOS)
Below are practical, stable options. After each install, verify with java -version
.
Windows (recommended)
- Download JDK
- Go to Eclipse Temurin / Adoptium / Oracle and download the Windows x64 installer for Java 17+ (Temurin is free and commonly used).
- Run the installer and follow steps.
- Set JAVA_HOME (if installer didn’t)
- Open System Properties → Advanced → Environment Variables.
- Add
JAVA_HOME
=C:\Program Files\...temurin-17...
(path where JDK installed). - Add
%JAVA_HOME%\bin
toPath
.
- Install IntelliJ IDEA
- Download IntelliJ Community (free) or Ultimate (paid) from JetBrains and run the installer.
- Alternatively use Windows package managers:
winget
orchoco
(if you use them).
- Verify
java -version
Ubuntu / Debian (recommended commands)
- Install OpenJDK 17 (example)
sudo apt update
sudo apt install openjdk-17-jdk -y
Or use SDKMAN to manage versions (recommended if you try many versions):
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install java 17.0.8-tem
- Install IntelliJ
-
Snap:
sudo snap install intellij-idea-community --classic
Or use JetBrains Toolbox app.
- Verify
java -version
macOS
- Install JDK (Homebrew or SDKMAN)
-
Homebrew (Temurin):
brew install --cask temurin
-
SDKMAN:
curl -s "https://get.sdkman.io" | bash sdk install java 17.0.8-tem
- Install IntelliJ
-
Homebrew:
brew install --cask intellij-idea-ce
Or download from JetBrains site / Toolbox.
- Verify
java -version
2. Install Maven (Windows / Ubuntu / macOS)
Maven builds Java projects and is the most common build tool for Spring Boot (Maven or Gradle both supported).
Ubuntu
sudo apt update
sudo apt install maven -y
mvn -v
macOS
brew install maven
mvn -v
Windows
- Download binary from Apache Maven site, extract, set
MAVEN_HOME
, and add%MAVEN_HOME%\bin
toPath
. - Or use package managers:
choco install maven
orwinget
.
Verify
mvn -v
3. Download a Spring Boot project from Spring Initializr
Option A — Web UI (easy)
- Open https://start.spring.io
- Choose:
- Project: Maven Project
- Language: Java
- Spring Boot: choose a stable 3.x version.
- Project Metadata: Group (e.g.
com.example
), Artifact (e.g.student-api
) - Packaging: Jar (default)
-
Java: 17 or later
- Add dependencies, e.g.:
Spring Web (for REST)
Spring Data JPA (for DB)
H2 Database (in-memory for quick testing)
-
optional: Lombok, Spring Boot DevTools, Validation
- Click Generate → download a ZIP.
Option B — IntelliJ New Project (Spring Initializr integration)
- File → New → Project → choose Spring Initializr → fill details → pick dependencies → Finish. IntelliJ will generate the project and open it.
4. Create / Import the Spring Boot project in IntelliJ
From ZIP:
- File → Open → select extracted folder containing
pom.xml
. - IntelliJ will import Maven project and download dependencies.
New Project (built-in):
- File → New → Project → Spring Initializr.
- Fill Group/Artifact, pick Java version and dependencies.
- Finish → project created and ready.
IntelliJ has a Run green triangle next to the main class. Use it to run the app.
5. What is Maven and how it works with Java & Spring Boot? (deep dive)
Maven is a build automation and dependency management tool.
-
POM (pom.xml): Project Object Model — defines project coordinates (
groupId
,artifactId
,version
), dependencies, build plugins, and configuration. -
Lifecycle:
validate
→compile
→test
→package
→install
→deploy
.mvn package
creates the JAR,mvn install
installs it in the local Maven repo (~/.m2/repository
). - Repositories: Maven resolves dependencies from remote repositories (Maven Central) into your local repo. Transitive dependency resolution means a dependency’s dependencies are fetched automatically.
-
Plugins: e.g.,
spring-boot-maven-plugin
builds executable JAR/WAR and handles repackage steps.
How Spring Boot uses Maven:
- Spring Boot projects typically use the
spring-boot-starter-parent
in the POM or the Spring Boot dependency management plugin. This parent sets sensible defaults (dependency versions, plugin config). - The
spring-boot-starter-*
dependencies are meta-dependencies — they pull in the libraries you need (e.g.,spring-boot-starter-web
brings Spring MVC + Tomcat). -
spring-boot-maven-plugin
providesmvn spring-boot:run
and the mechanism to create an executable jar with the embedded server.
Minimal pom.xml
snippet (illustrative)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version> <!-- example -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
6. Structure of a Spring Boot application (what’s inside)
Typical file/directory layout:
student-api/
├─ pom.xml
└─ src/
├─ main/
│ ├─ java/
│ │ └─ com/example/studentapi/
│ │ ├─ StudentApiApplication.java <-- main class
│ │ ├─ controller/
│ │ ├─ service/
│ │ └─ repository/
│ └─ resources/
│ ├─ application.properties
│ ├─ static/
│ └─ templates/
└─ test/
└─ java/
Important files:
-
pom.xml
: build & deps. -
src/main/java/...Application.java
:main()
bootstraps Spring. -
application.properties
orapplication.yml
: runtime config (datasource, server port, logging). -
src/main/resources/static
andtemplates
: for web assets / server-side templates. -
src/test/java
: tests.
Note: Place the main
application class in a root package so component scanning picks up controllers/services in subpackages. For example, com.example.studentapi.StudentApiApplication
will @ComponentScan
under com.example.studentapi.*
.
7. @SpringBootApplication
— internal working (IOC container & dependency injection)
@SpringBootApplication
is a meta-annotation that expands to:
@Configuration
@EnableAutoConfiguration
@ComponentScan
What that means:
-
@Configuration
— marks the class as a source of bean definitions. -
@EnableAutoConfiguration
— asks Spring Boot to automatically configure beans based on the classpath (e.g., if Spring MVC is on the classpath, it configures aDispatcherServlet
). Spring Boot provides many auto-configuration classes; it tries to configure what you need. -
@ComponentScan
— tells Spring to scan the package where the main class resides and its subpackages for Spring components:@Controller
,@Service
,@Repository
,@Component
, etc.
SpringApplication.run()
:
- Creates an ApplicationContext (the IOC container).
- Scans components and registers beans.
- Applies auto-configurations based on
@Conditional
rules and available classes. - Starts the embedded servlet container (for web apps).
- Calls lifecycle callbacks (e.g.,
@PostConstruct
).
IOC container & Dependency Injection (DI):
The ApplicationContext holds bean definitions and manages lifecycle (creation, dependency injection, destruction).
-
Injection styles:
- Constructor injection (recommended):
@Service public class StudentService { private final StudentRepository repo; public StudentService(StudentRepository repo) { this.repo = repo; } }
- Field injection (not recommended):
@Autowired private StudentRepository repo;
-
Setter injection: setter methods annotated with
@Autowired
.
-
Bean Scopes:
-
singleton
(default): one instance per ApplicationContext. -
prototype
: new instance each request. - others exist for web contexts (
request
,session
).
-
Important: Prefer constructor injection — it makes code easier to test and avoids nulls.
8. Create a REST API using Spring Boot — CRUD example (step-by-step)
We’ll build a simple Student CRUD API with H2 (in-memory) and Spring Data JPA.
1) Project setup
Create project with dependencies:
spring-boot-starter-web
spring-boot-starter-data-jpa
com.h2database:h2
- (optional)
spring-boot-devtools
,lombok
Example pom.xml
(core parts only):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2) application.properties (simple)
src/main/resources/application.properties
spring.datasource.url=jdbc:h2:mem:studentsdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
-
ddl-auto=update
creates tables automatically (good for dev). - H2 console available at
/h2-console
when app runs.
3) Main application class
StudentApiApplication.java
package com.example.studentapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StudentApiApplication {
public static void main(String[] args) {
SpringApplication.run(StudentApiApplication.class, args);
}
}
-
@SpringBootApplication
triggers component scanning and auto-configuration.
4) Entity
Student.java
package com.example.studentapi.model;
import jakarta.persistence.*;
@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
private String address;
private String phone;
// Constructors
public Student() {}
public Student(String name, String address, String phone) {
this.name = name;
this.address = address;
this.phone = phone;
}
// Getters and setters...
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
}
Note: I used
jakarta.persistence.*
as modern Spring Boot uses Jakarta packages.
5) Repository
StudentRepository.java
package com.example.studentapi.repository;
import com.example.studentapi.model.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
// Spring Data JPA provides CRUD methods automatically
}
6) Service (optional but good practice)
StudentService.java
package com.example.studentapi.service;
import com.example.studentapi.model.Student;
import com.example.studentapi.repository.StudentRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class StudentService {
private final StudentRepository repo;
public StudentService(StudentRepository repo) { this.repo = repo; }
public Student create(Student s) { return repo.save(s); }
public List<Student> findAll() { return repo.findAll(); }
public Optional<Student> findById(Long id) { return repo.findById(id); }
public Student update(Long id, Student s) {
s.setId(id);
return repo.save(s);
}
public void delete(Long id) { repo.deleteById(id); }
}
7) Controller (REST endpoints)
StudentController.java
package com.example.studentapi.controller;
import com.example.studentapi.model.Student;
import com.example.studentapi.service.StudentService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.net.URI;
import java.util.List;
@RestController
@RequestMapping("/api/students")
public class StudentController {
private final StudentService service;
public StudentController(StudentService service) { this.service = service; }
@PostMapping
public ResponseEntity<Student> create(@RequestBody Student s) {
Student created = service.create(s);
return ResponseEntity.created(URI.create("/api/students/" + created.getId())).body(created);
}
@GetMapping
public List<Student> all() { return service.findAll(); }
@GetMapping("/{id}")
public ResponseEntity<Student> getById(@PathVariable Long id) {
return service.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PutMapping("/{id}")
public ResponseEntity<Student> update(@PathVariable Long id, @RequestBody Student s) {
// simple approach: set id and save
Student updated = service.update(id, s);
return ResponseEntity.ok(updated);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
service.delete(id);
return ResponseEntity.noContent().build();
}
}
8) Run the app
From IntelliJ: click the Run icon on StudentApiApplication
.
Or from terminal:
mvn spring-boot:run
Application will start (default http://localhost:8080
).
9) Test with curl
(examples)
- Create:
curl -X POST http://localhost:8080/api/students \
-H "Content-Type: application/json" \
-d '{"name":"Aisha","address":"Dhaka","phone":"+8801..."}'
- Get all:
curl http://localhost:8080/api/students
- Get by id:
curl http://localhost:8080/api/students/1
- Update:
curl -X PUT http://localhost:8080/api/students/1 \
-H "Content-Type: application/json" \
-d '{"name":"Aisha Updated","address":"Dhaka","phone":"0123"}'
- Delete:
curl -X DELETE http://localhost:8080/api/students/1
You can also use Postman / Insomnia / HTTPie.
9. Explanation: each key file and why it matters (quick line-by-line highlights)
-
StudentApiApplication.java
— launches Spring, triggers auto-configuration and component scanning. -
pom.xml
— defines dependencies andspring-boot-maven-plugin
somvn spring-boot:run
andmvn package
produce runnable JAR. -
application.properties
— runtime settings (DB URL, logging, port). Changingspring.jpa.hibernate.ddl-auto
impacts schema generation. -
@Entity
Student — JPA entity mapping.@Id
+@GeneratedValue
controls primary key generation. -
StudentRepository
— Spring Data JPA gives yousave()
,findAll()
,findById()
,deleteById()
— no boilerplate SQL. -
StudentService
— encapsulates business logic and interacts with repository (keeps controller thin). -
StudentController
— exposes REST endpoints and maps HTTP verbs to CRUD operations.
10. Common pitfalls & debugging tips
-
Java version mismatch: If runtime complains about class file version, ensure
java -version
matches JDK used to compile. -
Port in use:
server.port=8080
can be changed inapplication.properties
. -
Dependency issues: Run
mvn clean package
and check for conflicting versions. Spring Boot parent usually manages versions for you. -
H2 console not accessible: verify
spring.h2.console.enabled=true
and use correct JDBC URLjdbc:h2:mem:studentsdb
. - Lombok problems: If using Lombok, enable annotation processing in IntelliJ (Preferences → Build, Execution, Deployment → Compiler).
Short checklist to run the example right now
- Java 17+ installed and
java -version
OK. - Maven installed and
mvn -v
OK. - Create Spring Boot project from start.spring.io or IntelliJ with dependencies: Web, JPA, H2.
- Paste entity/repository/service/controller code shown above.
-
application.properties
as provided. - Run
mvn spring-boot:run
and test withcurl
.
Follow me on : Github Linkedin Threads Youtube Channel
This content originally appeared on DEV Community and was authored by Jack Pritom Soren