Introduction
This cheatsheet is a clear, concise reference for the SWE - Spring Boot - Up and Running and Introduction course, designed for web developers with no Java or Spring framework experience but familiar with JavaScript, REST APIs, JSON, and frontend testing (e.g., Jest). It introduces Spring Boot setup, REST API development, data persistence with JPA, security, logging, and testing, using analogies to frontend concepts for easy understanding. Each section includes key concepts, heavily commented code examples adhering to the Code Commenting Guideline for Software Engineering Course with output comments, commands to run the code with explanations, Mermaid diagrams for visual clarity, practical tips, and common pitfalls.
1. Spring Boot Foundation
Overview
Learn the basics of Spring Boot, including beans and dependency injection, which simplify backend development like Express does for Node.js.
Key Concepts
- Spring Boot Overview: A framework that streamlines web app development with automated setup, like Express simplifies Node.js apps.
- Spring Beans: Objects managed by Spring’s container, like JavaScript modules or React components, created and connected automatically.
- Characteristics:
- Managed Lifecycle: Spring creates, initializes, and destroys beans, like React’s component lifecycle (
componentDidMount). - Singleton Scope: One instance per app by default, like a shared JavaScript module.
- Dependency Injection (DI): Beans are injected into other classes, like React context passing data.
- Annotations: Use
ComponentBean,ServiceBean,RestControllerBean, orConfigurationBeanto define roles.
- Managed Lifecycle: Spring creates, initializes, and destroys beans, like React’s component lifecycle (
- Characteristics:
- Dependency Injection (DI): Spring provides dependencies automatically, like React context, reducing manual setup.
- Spring Boot Components:
- ComponentBean: General-purpose bean, like a JavaScript utility module.
- ServiceBean: Handles business logic, like a JavaScript service module.
- RestControllerBean: Processes HTTP requests, like Express routes.
- ConfigurationBean: Defines custom settings, like a JavaScript config file.
Mermaid Diagram: Spring Boot Architecture
graph TD
A[Spring Boot Application] --> B[Main Class]
B --> C[SpringBootApplication]
C --> D[Spring Container]
D --> E[Auto-Configuration]
D --> F[Component Scanning]
F --> G[Beans]
G --> H[ComponentBean]
G --> I[ServiceBean]
G --> J[RestControllerBean]
G --> K[ConfigurationBean]
E --> L[Embedded Tomcat Server]
J --> M[REST APIs]
Diagram Explanation:
- This diagram shows how a Spring Boot app starts with a main class, uses the Spring container to manage beans (e.g.,
ComponentBean,ServiceBean), and runs an embedded Tomcat server for REST APIs, similar to a Node.js app with Express.
Syntax Examples
// File: PaymentService.java
// Description: Defines a service bean for payment processing.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.stereotype.Component;
// Marks this class as a Spring component bean, like a JavaScript module
@Component
public class PaymentService {
// Processes a payment, returns confirmation
// Returns: confirmation message (String)
public String processPayment() {
return "Payment processed"; // Simple logic
// Output: Payment processed
}
}
// File: OrderService.java
// Description: Uses PaymentService via dependency injection.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
// Marks this class as a Spring service bean for business logic
@Service
public class OrderService {
private final PaymentService paymentService; // Injected dependency
// Constructor to inject PaymentService, like React context
// Inputs: paymentService (PaymentService)
@Autowired
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService; // Store dependency
}
// Creates an order using payment service
// Returns: payment confirmation (String)
public String createOrder() {
return paymentService.processPayment(); // Call injected service
// Output: Payment processed
}
}
// File: Main.java
// Description: Demonstrates dependency injection with OrderService.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
// Create Spring container, like a JavaScript module loader
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.scan("com.example"); // Scan for beans
context.refresh(); // Initialize container
// Get OrderService bean
OrderService orderService = context.getBean(OrderService.class);
// Call createOrder
System.out.println(orderService.createOrder()); // Output: Payment processed
}
}Run Command:
mvn exec:java -Dexec.mainClass="Main"Why This Command:
- The
mvn exec:javacommand runs themainmethod ofMain, demonstrating dependency injection withOrderService, similar to running a JavaScript script withnode.
Quick Reference Table
| Concept | Java Syntax | JavaScript Equivalent | Characteristics |
|---|---|---|---|
| Bean | ComponentBean class PaymentService | export class PaymentService | Managed by Spring, singleton |
| DI | @Autowired Constructor | React.useContext | Automatic dependency wiring |
| ServiceBean | ServiceBean class OrderService | Service module | Business logic handling |
Analogy
- Spring Boot beans are like JavaScript modules, managed by Spring’s container for easy reuse, similar to React context.
Common Pitfalls
- Missing
@Autowired: Causes null dependencies; use on constructors. - Bean Not Found: Ensure
context.scanincludes the correct package. - Container Setup: Call
context.refresh()to initialize beans.
2. Introduction to Spring Boot
Overview
Set up a Spring Boot application with starters and an embedded server, like configuring an Express app in Node.js.
Key Concepts
- Auto-Configuration: Spring Boot sets up components (e.g., web server) automatically, like npm packages with defaults.
- Spring Boot Starters: Pre-configured dependencies, like
expressin Node.js. - Embedded Server: Runs Tomcat within the app, unlike external Node.js servers.
- Main Application: Entry point with
SpringBootApplication, likeapp.jsin Express.
Syntax Examples
<!-- File: pom.xml -->
<!-- Description: Configures Maven project with Spring Boot web starter -->
<!-- Author: wkf -->
<!-- Date: 2025-07-07 -->
<!-- Course: SWE - Spring Boot - Introduction -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myapp</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version>
</parent>
<dependencies>
<!-- Spring Boot starter for web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>// File: BlogApplication.java
// Description: Main entry point for Spring Boot app with embedded server.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Combines ConfigurationBean, ComponentScan, EnableAutoConfiguration
@SpringBootApplication
public class BlogApplication {
public static void main(String[] args) {
// Starts Spring Boot app with Tomcat server
SpringApplication.run(BlogApplication.class, args);
// Output: Application starts, server runs on port 8080
}
}Run Command:
mvn spring-boot:runWhy This Command:
- The
mvn spring-boot:runcommand launches theBlogApplication, starting the embedded Tomcat server, similar tonode app.jsin Express, making the app accessible athttp://localhost:8080.
Quick Reference Table
| Concept | Java Syntax | JavaScript Equivalent | Characteristics |
|---|---|---|---|
| Starter | spring-boot-starter-web | npm install express | Pre-configured dependencies |
| Auto-Config | SpringBootApplication | Express middleware setup | Automatic component setup |
| Embedded Server | Tomcat (included) | Node.js http.createServer | Runs within app |
Analogy
- Spring Boot starters are like
npm install express, simplifying backend setup.
Common Pitfalls
- Missing Starter: Add
spring-boot-starter-webtopom.xmlfor web support. - Version Mismatch: Use consistent Spring Boot version (e.g., 3.3.1).
- Main Class: Place
SpringBootApplicationin root package for scanning.
3. First Spring Boot Application
Overview
Create a Spring Boot project with basic configuration, similar to initializing a Node.js project with npm.
Key Concepts
- Spring Initializr: Generates project structure, like
create-react-app. - Project Structure: Includes
src/main/java(code),pom.xml(dependencies),application.yml(settings). - Application Properties: Configure settings via
application.yml, like.envfiles. - Maven Commands: Build and run apps, like
npm runscripts.
Syntax Examples
# Command to generate Spring Boot project
# Description: Creates project with web dependency
curl https://start.spring.io/starter.zip -d dependencies=web -d javaVersion=17 -o project.zip# File: application.yml
# Description: Configures app settings, like .env in JavaScript
# Author: wkf
# Date: 2025-07-07
# Course: SWE - Spring Boot - Introduction
server:
port: 8080 # Sets server port, like PORT=8080
spring:
application:
name: MyBlog # Names the application// File: BlogApplication.java
// Description: Main entry point for Spring Boot app.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Combines ConfigurationBean, ComponentScan, EnableAutoConfiguration
@SpringBootApplication
public class BlogApplication {
public static void main(String[] args) {
// Starts Spring Boot app with Tomcat
SpringApplication.run(BlogApplication.class, args);
// Output: Application starts, server runs on port 8080
}
}Run Command:
mvn spring-boot:runWhy This Command:
- The
mvn spring-boot:runcommand launchesBlogApplication, starting the Tomcat server, similar tonode app.js, making the app accessible athttp://localhost:8080.
Quick Reference Table
| Component | Location | JavaScript Equivalent | Characteristics |
|---|---|---|---|
| Main Class | src/main/java/BlogApplication.java | app.js | App entry point |
| Config | application.yml | .env or package.json | Configures settings |
| Dependencies | pom.xml | package.json | Manages libraries |
Analogy
- Spring Initializr is like
create-react-app, setting up a project quickly.
Common Pitfalls
- Port Conflicts: Change
server.portif 8080 is in use. - YAML Errors: Ensure correct indentation in
application.yml. - Maven Issues: Verify internet for
mvn clean install.
4. REST API Development
Overview
Build REST APIs with Spring Boot, like Express routes, to handle HTTP requests.
Key Concepts
- RestControllerBean: Handles HTTP requests, like Express routes.
- HTTP Methods:
@GetMapping,@PostMappingfor GET/POST, likeapp.get,app.post. - Exception Handling:
@ExceptionHandlerfor errors, like Express error middleware. - Request/Response:
@RequestBodyfor input,ResponseEntityfor output, like JSON in Express.
Mermaid Diagram: REST API Flow
sequenceDiagram
participant Client
participant Controller
participant Service
Client->>Controller: GET /posts
Controller->>Service: getAllPosts()
Service-->>Controller: List of posts
Controller-->>Client: JSON response
Client->>Controller: POST /posts
Controller->>Service: addPost(post)
Service-->>Controller: Confirmation
Controller-->>Client: 201 Created
Diagram Explanation:
- This sequence diagram shows a client interacting with a
RestControllerBeanandServiceBean, like a frontend app calling an Express API.
Syntax Examples
// File: PostService.java
// Description: Service bean for managing posts, like a JavaScript service.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.stereotype.Service;
import java.util.*;
// Marks this class as a Spring service bean
@Service
public class PostService {
// In-memory post storage, like a JavaScript array
private List<String> posts = new ArrayList<>();
// Returns all posts
// Returns: List of posts (String)
public List<String> getAllPosts() {
return new ArrayList<>(posts); // Defensive copy
}
// Adds a post with validation
// Inputs: post (String)
// Throws: IllegalArgumentException if empty
public void addPost(String post) {
if (post == null || post.isEmpty()) {
throw new IllegalArgumentException("Post cannot be empty");
}
posts.add(post); // Store post
}
}
// File: PostController.java
// Description: REST controller for post endpoints, like Express routes.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
// Marks this class as a Spring REST controller bean
@RestController
@RequestMapping("/posts") // Base path for endpoints
public class PostController {
private final PostService postService; // Service bean
// Constructor to inject PostService
// Inputs: postService (PostService)
@Autowired
public PostController(PostService postService) {
this.postService = postService;
}
// Handles GET requests to retrieve posts
// Returns: List of posts
@GetMapping
public List<String> getPosts() {
return postService.getAllPosts(); // Call service
// Output: JSON array, e.g., ["Post 1", "Post 2"]
}
// Handles POST requests to create a post
// Inputs: post (String)
// Returns: Confirmation message
@PostMapping
public ResponseEntity<String> createPost(@RequestBody String post) {
postService.addPost(post); // Call service
return new ResponseEntity<>("Created: " + post, HttpStatus.CREATED);
// Output: HTTP 201 with "Created: [post content]"
}
// Handles errors
// Inputs: e (IllegalArgumentException)
// Returns: Error message
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleError(IllegalArgumentException e) {
return new ResponseEntity<>("Error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
// Output: HTTP 400 with "Error: Post cannot be empty"
}
}Run Command:
mvn spring-boot:runWhy This Command:
- The
mvn spring-boot:runcommand starts the Spring Boot app, enabling/postsendpoints for testing withcurl, similar tonode app.jsfor Express.
Test Commands:
# Test GET endpoint
curl http://localhost:8080/posts
# Output: ["Post 1", "Post 2"] (if posts exist)
# Test POST endpoint
curl -X POST -H "Content-Type: application/json" -d '"New Post"' http://localhost:8080/posts
# Output: Created: New PostQuick Reference Table
| HTTP Method | Annotation | JavaScript Equivalent | Characteristics |
|---|---|---|---|
| GET | @GetMapping | app.get('/route', ...) | Retrieves data |
| POST | @PostMapping | app.post('/route', ...) | Creates data |
| Exception | @ExceptionHandler | try { ... } catch (e) { ... } | Handles errors |
Analogy
RestControllerBeanis like Express routes, defining API endpoints.
Common Pitfalls
- Missing
RestControllerBean: Causes non-JSON responses. - Invalid JSON: Ensure
@RequestBodymatches input format. - HTTP Status: Use
HttpStatus.CREATEDfor POST responses.
5. Intermediate Capstone: Basic Blog API
Overview
Build a Spring Boot app with GET/POST/PUT endpoints for posts, like a minimal Express API.
Key Concepts
- CRUD Endpoints: Implement create, read, update operations.
- Dependency Injection: Use
ServiceBeanfor logic, injected intoRestControllerBean. - Error Handling: Validate inputs and handle errors.
Example Code
// File: PostService.java
// Description: Service bean for managing posts.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.stereotype.Service;
import java.util.*;
// Marks this class as a Spring service bean
@Service
public class PostService {
private List<String> posts = new ArrayList<>(); // In-memory storage
// Returns all posts
public List<String> getAllPosts() {
return new ArrayList<>(posts); // Defensive copy
}
// Adds a post with validation
// Inputs: post (String)
// Throws: IllegalArgumentException if empty
public void addPost(String post) {
if (post == null || post.isEmpty()) {
throw new IllegalArgumentException("Post cannot be empty");
}
posts.add(post);
}
// Updates a post
// Inputs: index (int), post (String)
// Throws: IllegalArgumentException if invalid index
public void updatePost(int index, String post) {
if (index < 0 || index >= posts.size()) {
throw new IllegalArgumentException("Invalid index");
}
posts.set(index, post);
}
}
// File: BlogController.java
// Description: REST controller for blog post endpoints.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
// Marks this class as a Spring REST controller bean
@RestController
@RequestMapping("/posts")
public class BlogController {
private final PostService postService; // Service bean
// Constructor to inject PostService
@Autowired
public BlogController(PostService postService) {
this.postService = postService;
}
// Handles GET requests
@GetMapping
public List<String> getPosts() {
return postService.getAllPosts();
// Output: JSON array, e.g., ["Post 1", "Post 2"]
}
// Handles POST requests
@PostMapping
public ResponseEntity<String> addPost(@RequestBody String post) {
postService.addPost(post);
return new ResponseEntity<>("Post added", HttpStatus.CREATED);
// Output: HTTP 201 with "Post added"
}
// Handles PUT requests
// Inputs: index (int), post (String)
@PutMapping("/{index}")
public ResponseEntity<String> updatePost(@PathVariable int index, @RequestBody String post) {
postService.updatePost(index, post);
return new ResponseEntity<>("Post updated", HttpStatus.OK);
// Output: HTTP 200 with "Post updated"
}
// Handles errors
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleError(IllegalArgumentException e) {
return new ResponseEntity<>("Error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
// Output: HTTP 400 with "Error: [message]"
}
}Run Command:
mvn spring-boot:runWhy This Command:
- The
mvn spring-boot:runcommand starts the Spring Boot app, enabling/postsendpoints for testing withcurl, similar tonode app.js.
Test Commands:
# Test GET endpoint
curl http://localhost:8080/posts
# Output: ["Post 1", "Post 2"] (if posts exist)
# Test POST endpoint
curl -X POST -H "Content-Type: application/json" -d '"New Post"' http://localhost:8080/posts
# Output: Post added
# Test PUT endpoint
curl -X PUT -H "Content-Type: application/json" -d '"Updated Post"' http://localhost:8080/posts/0
# Output: Post updatedAnalogy
- The blog API is like a minimal Express app with CRUD operations.
Common Pitfalls
- Index Errors: Validate
@PathVariableto avoidIndexOutOfBoundsException. - Null Input: Check
@RequestBodyfor empty values. - Test Coverage: Test all endpoints with valid/invalid inputs.
6. Data Access with JPA
Overview
Use Spring Data JPA to manage database operations, like Sequelize in Node.js, for persistent storage.
Key Concepts
- Spring Data JPA: Maps Java objects to database tables, like Sequelize models.
- Entity Mapping:
@Entitymarks classes as tables, with fields as columns. - RepositoryBean:
JpaRepositoryprovides automatic CRUD methods, like Mongoose queries. - H2 Database: In-memory database for testing, like SQLite.
Mermaid Diagram: JPA Entity Relationship
classDiagram
class Post {
+Long id
+String title
+String content
}
class PostRepository {
<<interface>>
+findAll() List
+save(Post) Post
}
Post --> PostRepository : Managed by
Diagram Explanation:
- This class diagram shows the
Postentity andPostRepositoryfor CRUD operations, like a Sequelize model and its queries.
Syntax Examples
<!-- File: pom.xml -->
<!-- Description: Configures Maven project with JPA and H2 -->
<!-- Author: wkf -->
<!-- Date: 2025-07-07 -->
<!-- Course: SWE - Spring Boot - Introduction -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myapp</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version>
</parent>
<dependencies>
<!-- Spring Boot starter for JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- H2 database for testing -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>// File: Post.java
// Description: Defines Post entity for JPA.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import jakarta.persistence.*;
@Entity
public class Post {
// Primary key, auto-incremented
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title; // Table column
private String content; // Table column
// Getter for id
public Long getId() {
return id;
}
// Setter for id
public void setId(Long id) {
this.id = id;
}
// Getter for title
public String getTitle() {
return title;
}
// Setter for title
public void setTitle(String title) {
this.title = title;
}
// Getter for content
public String getContent() {
return content;
}
// Setter for content
public void setContent(String content) {
this.content = content;
}
}
// File: PostRepository.java
// Description: JPA repository for Post entity.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.data.jpa.repository.JpaRepository;
// Marks this interface as a Spring repository bean
public interface PostRepository extends JpaRepository<Post, Long> {
// Finds posts by title
List<Post> findByTitleContaining(String title);
}# File: application.yml
# Description: Configures H2 database for JPA
# Author: wkf
# Date: 2025-07-07
# Course: SWE - Spring Boot - Introduction
spring:
datasource:
url: jdbc:h2:mem:blogdb # In-memory database
driverClassName: org.h2.Driver
jpa:
hibernate:
ddl-auto: update # Auto-create tablesRun Command:
mvn spring-boot:runWhy This Command:
- The
mvn spring-boot:runcommand starts the Spring Boot app, initializing the H2 database and JPA repository, similar to a Node.js app with Sequelize.
Quick Reference Table
| Concept | Java Syntax | JavaScript Equivalent | Characteristics |
|---|---|---|---|
| Entity | @Entity class Post | Sequelize.define('Post') | Maps to table |
| RepositoryBean | extends JpaRepository | Mongoose model methods | Auto CRUD methods |
| Save | repository.save(post) | model.create(post) | Persists data |
Analogy
- JPA is like Sequelize, mapping objects to database tables.
Common Pitfalls
- Missing Annotations: Ensure
@Entityand@Idare present. - H2 Config: Set
spring.jpa.hibernate.ddl-auto=updatefor schema creation. - Null IDs: Use
@GeneratedValuefor auto-incrementing IDs.
7. Security, Logging, and Testing
Overview
Secure APIs, log events, and test functionality, like frontend auth, debugging, and testing.
Key Concepts
- API Key Authentication: Secure endpoints with a
ComponentBeanfilter, like frontend token auth. - Logging: Use SLF4J/Logback for debugging, like
console.log. - Unit Testing: JUnit 5 with Mockito for
ServiceBean, like Jest. - Integration Testing: MockMvc for
RestControllerBean, like Supertest.
Syntax Examples
<!-- File: pom.xml -->
<!-- Description: Configures Maven project with security and testing -->
<!-- Author: wkf -->
<!-- Date: 2025-07-07 -->
<!-- Course: SWE - Spring Boot - Introduction -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myapp</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version>
</parent>
<dependencies>
<!-- Spring Boot starter for web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot starter for testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>// File: ApiKeyFilter.java
// Description: Component bean for API key authentication.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import jakarta.servlet.*;
import org.springframework.stereotype.Component;
import org.springframework.http.HttpStatus;
import java.io.IOException;
// Marks this class as a Spring component bean
@Component
public class ApiKeyFilter implements Filter {
// Filters requests to check API key
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String apiKey = req.getHeader("X-API-KEY"); // Get header
if ("my-secret-key".equals(apiKey)) {
chain.doFilter(request, response); // Allow request
} else {
((HttpServletResponse) response).sendError(HttpStatus.UNAUTHORIZED.value(), "Invalid API Key");
// Output: HTTP 401 with "Invalid API Key"
}
}
}// File: PostController.java
// Description: REST controller with logging for posts.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
// Marks this class as a Spring REST controller bean
@RestController
@RequestMapping("/posts")
public class PostController {
private static final Logger logger = LoggerFactory.getLogger(PostController.class); // Logger
private final PostService postService; // Service bean
// Constructor to inject PostService
@Autowired
public PostController(PostService postService) {
this.postService = postService;
}
// Handles POST requests
@PostMapping
public ResponseEntity<String> createPost(@RequestBody String post) {
logger.info("Creating post: {}", post); // Log action
postService.addPost(post);
return new ResponseEntity<>("Post created", HttpStatus.CREATED);
// Output: HTTP 201 with "Post created"
}
}// File: PostControllerTest.java
// Description: Tests起点
System: Tests PostController using JUnit 5 and MockMvc.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@SpringBootTest
@AutoConfigureMockMvc
class PostControllerTest {
@Autowired
private MockMvc mockMvc; // MockMvc for testing
@MockBean
private PostService postService; // Mocked service bean
// Tests POST request
@Test
void testCreatePost() throws Exception {
// Mock service behavior
doNothing().when(postService).addPost(anyString());
// Perform POST request with API key
mockMvc.perform(post("/posts")
.header("X-API-KEY", "my-secret-key")
.contentType(MediaType.APPLICATION_JSON)
.content("\"Test Post\""))
.andExpect(status().isCreated()) // Expect HTTP 201
.andExpect(content().string("Post created")); // Expect response
// Output: Test passes if response is "Post created"
}
// Tests GET request
@Test
void testGetPosts() throws Exception {
// Mock service response
when(postService.getAllPosts()).thenReturn(List.of("Post 1"));
// Perform GET request
mockMvc.perform(get("/posts")
.header("X-API-KEY", "my-secret-key"))
.andExpect(status().isOk()) // Expect HTTP 200
.andExpect(content().json("[\"Post 1\"]")); // Expect JSON
// Output: Test passes if response is ["Post 1"]
}
}Run Command:
mvn testWhy This Command:
- The
mvn testcommand runs all JUnit tests, executingPostControllerTestto verify thePostControllerendpoints, similar tonpm testfor Jest tests.
Quick Reference Table
| Concept | Java Syntax | JavaScript Equivalent | Characteristics |
|---|---|---|---|
| Logging | logger.info("Message") | console.log("Message") | Debug output |
| Security Filter | implements Filter | Express middleware | Restricts access |
| MockMvc | mockMvc.perform(get(...)) | supertest(app).get(...) | Tests REST endpoints |
Analogy
- Spring Security filters are like Express middleware; MockMvc is like Supertest for API testing.
Common Pitfalls
- Missing API Key: Include
X-API-KEYin requests. - Log Overuse: Use
infofor key events,debugfor details. - Mock Issues: Ensure
@MockBeanmocks services correctly.
8. Final Capstone: Complete Blog API
Overview
Build a Spring Boot app with CRUD endpoints, JPA, API key authentication, logging, and testing, like a production-ready Express app.
Mermaid Diagram: Blog API Workflow
sequenceDiagram
participant Client
participant Controller
participant Repository
Client->>Controller: GET /posts
Controller->>Repository: findAll()
Repository-->>Controller: List of Posts
Controller-->>Client: JSON response
Client->>Controller: POST /posts
Controller->>Repository: save(Post)
Repository-->>Controller: Saved Post
Controller-->>Client: 201 Created
Diagram Explanation:
- This sequence diagram shows the client interacting with a
RestControllerBeanandRepositoryBeanfor CRUD operations, similar to an Express app with MongoDB.
Example Code
// File: Post.java
// Description: Defines Post entity for JPA.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import jakarta.persistence.*;
@Entity
public class Post {
// Primary key, auto-incremented
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title; // Table column
private String content; // Table column
// Getter for id
public Long getId() {
return id;
}
// Setter for id
public void setId(Long id) {
this.id = id;
}
// Getter for title
public String getTitle() {
return title;
}
// Setter for title
public void setTitle(String title) {
this.title = title;
}
// Getter for content
public String getContent() {
return content;
}
// Setter for content
public void setContent(String content) {
this.content = content;
}
}
// File: PostRepository.java
// Description: JPA repository for Post entity.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.springframework.data.jpa.repository.JpaRepository;
// Marks this interface as a Spring repository bean
public interface PostRepository extends JpaRepository<Post, Long> {}
// File: BlogController.java
// Description: REST controller with logging and security.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
// Marks this class as a Spring REST controller bean
@RestController
@RequestMapping("/posts")
public class BlogController {
private static final Logger logger = LoggerFactory.getLogger(BlogController.class);
private final PostRepository repository; // Repository bean
// Constructor to inject PostRepository
@Autowired
public BlogController(PostRepository repository) {
this.repository = repository;
}
// Handles GET requests
@GetMapping
public List<Post> getPosts() {
logger.info("Fetching all posts"); // Log action
return repository.findAll(); // Retrieve posts
// Output: JSON array, e.g., [{"id":1,"title":"Test","content":"Content"}]
}
// Handles POST requests
@PostMapping
public ResponseEntity<Post> createPost(@RequestBody Post post) {
if (post.getTitle() == null || post.getTitle().isEmpty()) {
throw new IllegalArgumentException("Title cannot be empty");
}
logger.info("Creating post: {}", post.getTitle());
Post saved = repository.save(post); // Save post
return new ResponseEntity<>(saved, HttpStatus.CREATED);
// Output: HTTP 201 with JSON post object
}
// Handles errors
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleError(IllegalArgumentException e) {
return new ResponseEntity<>("Error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
// Output: HTTP 400 with "Error: Title cannot be empty"
}
}
// File: BlogControllerTest.java
// Description: Tests BlogController with JUnit 5 and MockMvc.
// Author: wkf
// Date: 2025-07-07
// Course: SWE - Spring Boot - Introduction
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@SpringBootTest
@AutoConfigureMockMvc
class BlogControllerTest {
@Autowired
private MockMvc mockMvc; // MockMvc for testing
@Autowired
private PostRepository repository; // Real repository
// Tests POST request
@Test
void testCreatePost() throws Exception {
String postJson = "{\"title\":\"Test Post\",\"content\":\"Content\"}";
mockMvc.perform(post("/posts")
.header("X-API-KEY", "my-secret-key")
.contentType(MediaType.APPLICATION_JSON)
.content(postJson))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.title").value("Test Post"));
// Output: Test passes if response contains "Test Post"
}
// Tests GET request
@Test
void testGetPosts() throws Exception {
Post post = new Post();
post.setTitle("Test Post");
repository.save(post);
mockMvc.perform(get("/posts")
.header("X-API-KEY", "my-secret-key"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].title").value("Test Post"));
// Output: Test passes if response contains "Test Post"
}
}Run Command:
mvn testWhy This Command:
- The
mvn testcommand runs all JUnit tests, executingBlogControllerTestto verify the blog API’s CRUD operations, similar tonpm testfor Jest.
Test Commands:
# Test GET endpoint
curl -H "X-API-KEY: my-secret-key" http://localhost:8080/posts
# Output: [{"id":1,"title":"Test Post","content":"Content"}]
# Test POST endpoint
curl -X POST -H "X-API-KEY: my-secret-key" -H "Content-Type: application/json" -d '{"title":"Test Post","content":"Content"}' http://localhost:8080/posts
# Output: {"id":1,"title":"Test Post","content":"Content"}Analogy
- The blog API is like an Express app with MongoDB, providing CRUD with authentication.
Common Pitfalls
- JPA Errors: Ensure
@Entityand@Idare defined correctly. - Security Misconfiguration: Verify API key in filter.
- Test Data: Populate database for integration tests or use mocks.
9. Setup and Resources
Environment Setup
- JDK 17+:
# Install JDK 17 on Linux sudo apt install openjdk-17-jdk - Maven:
# Install Maven sudo apt install maven # Check version mvn --version - VS Code: Install Spring Boot Extension Pack for IntelliSense.
- Spring Initializr: Use
start.spring.ioto generate projects. - H2 Database: Configured in
pom.xmlfor in-memory testing.
Key Resources
- Spring Boot:
org.springframework.boot:spring-boot-starter-web:3.3.1for REST APIs. - JPA:
org.springframework.boot:spring-boot-starter-data-jpafor database access. - H2 Database:
com.h2database:h2for testing. - Testing:
org.springframework.boot:spring-boot-starter-testfor JUnit 5 and MockMvc. - Logging: SLF4J/Logback (included in Spring Boot).
- Spring Docs: Official documentation for setup and APIs.
- H2 Console: Access at
http://localhost:8080/h2-console(enable inapplication.yml).
Terminal Commands
# Generate project
curl https://start.spring.io/starter.zip -d dependencies=web,data-jpa,h2 -d javaVersion=17 -o project.zip
# Run application
mvn spring-boot:run
# Run tests
mvn test
# Build project
mvn clean installAnalogy
- Setting up Spring Boot is like configuring a Node.js app with npm and Express.
Common Pitfalls
- Dependency Issues: Ensure
pom.xmlincludes required starters. - H2 Console: Enable with
spring.h2.console.enabled=trueinapplication.yml. - Maven Cache: Clear
.m2folder if build fails (rm -rf ~/.m2/repository).
10. Tips for Recall
- Analogies: Compare Spring Boot to Express (e.g.,
RestControllerBean≈ routes, JPA ≈ Sequelize). - Practice: Test endpoints with
curland check/h2-consolefor database data. - Visualize: Use tables and diagrams to connect Java and JavaScript concepts.
- Test-Driven: Write JUnit/MockMvc tests to reinforce learning.
- Error Handling: Learn exceptions like
IllegalArgumentException. - Capstones: Revisit the blog API to apply concepts practically.