A comprehensive Spring Boot learning project that demonstrates all core concepts, best practices, and industry-standard patterns for mastering the Spring Boot framework.
This is a User Management System that showcases enterprise-level Spring Boot architecture. The application demonstrates how modern web applications are built using Spring Boot's powerful features and industry-standard patterns.
What You'll Master:
- Complete request-response flow from browser to database
- Enterprise layered architecture patterns
- Spring Boot's "magic" - auto-configuration and dependency injection
- Real-world API design and implementation
- Security, caching, validation, and testing strategies
Current Application Status: ✅ Running and Ready for Interaction
- Main Application: http://localhost:8080/api/v1
- Interactive API Documentation: http://localhost:8080/api/v1/swagger-ui.html
- Database Console: http://localhost:8080/api/v1/h2-console
- Health Monitoring: http://localhost:8080/api/v1/actuator
The project follows a layered architecture pattern:
┌─────────────────┐
│ Controller │ ← REST API endpoints, request/response handling
├─────────────────┤
│ Service │ ← Business logic, transaction management
├─────────────────┤
│ Repository │ ← Data access layer, JPA queries
├─────────────────┤
│ Entity │ ← JPA entities, database mapping
└─────────────────┘
- Auto-configuration - Leveraging Spring Boot's intelligent defaults
- Dependency Injection - Constructor injection and @Autowired
- Component Scanning - Automatic bean discovery and registration
- Profiles - Environment-specific configurations (dev, prod)
- REST Controllers - @RestController, @RequestMapping
- HTTP Methods - GET, POST, PUT, DELETE operations
- Request/Response Handling - @RequestBody, @PathVariable, @RequestParam
- Validation - Bean validation with JSR-303 annotations
- Exception Handling - Global exception handling with @RestControllerAdvice
- JPA/Hibernate - Object-relational mapping
- Spring Data JPA - Repository pattern implementation
- Custom Queries - JPQL and native SQL queries
- Relationships - One-to-Many, Many-to-One mappings
- Pagination - Page and Sort support
- Transactions - @Transactional management
- Authentication - Basic authentication setup
- Authorization - Role-based access control
- Password Encoding - BCrypt password hashing
- Security Configuration - Custom security rules
- Method Caching - @Cacheable, @CacheEvict
- Cache Configuration - CacheManager setup
- Performance Optimization - Reducing database calls
- Unit Testing - JUnit 5, Mockito
- Integration Testing - @SpringBootTest
- Web Layer Testing - @WebMvcTest, MockMvc
- Repository Testing - @DataJpaTest
- API Documentation - Swagger/OpenAPI integration
- Interactive API Explorer - Swagger UI
- Code Documentation - Comprehensive JavaDoc
- Actuator - Health checks, metrics, info endpoints
- Logging - Structured logging configuration
- Profiles - Environment-specific settings
src/
├── main/
│ ├── java/com/springboot/master/
│ │ ├── SpringBootMasterApplication.java # Main application class
│ │ ├── config/ # Configuration classes
│ │ │ ├── SecurityConfig.java # Security configuration
│ │ │ ├── OpenApiConfig.java # Swagger configuration
│ │ │ └── AppConfig.java # General configuration
│ │ ├── controller/ # REST controllers
│ │ │ └── UserController.java # User management endpoints
│ │ ├── service/ # Business logic layer
│ │ │ └── UserService.java # User business operations
│ │ ├── repository/ # Data access layer
│ │ │ ├── UserRepository.java # User data operations
│ │ │ └── PostRepository.java # Post data operations
│ │ ├── entity/ # JPA entities
│ │ │ ├── User.java # User entity
│ │ │ ├── Post.java # Post entity
│ │ │ └── UserRole.java # User role enum
│ │ ├── dto/ # Data Transfer Objects
│ │ │ ├── CreateUserDto.java # User creation request
│ │ │ └── UserResponseDto.java # User response
│ │ └── exception/ # Exception handling
│ │ ├── ResourceNotFoundException.java
│ │ ├── DuplicateResourceException.java
│ │ └── GlobalExceptionHandler.java
│ └── resources/
│ ├── application.properties # Main configuration
│ ├── application-dev.properties # Development profile
│ └── application-prod.properties # Production profile
└── test/ # Test classes
└── java/com/springboot/master/
├── SpringBootMasterApplicationTests.java
├── controller/
├── service/
└── repository/
- Java 17 - Programming language
- Spring Boot 3.2.0 - Framework
- Spring Data JPA - Data persistence
- Spring Security - Authentication & authorization
- H2 Database - In-memory database (development)
- MySQL - Production database
- Maven - Build tool
- JUnit 5 - Testing framework
- Mockito - Mocking framework
- Swagger/OpenAPI - API documentation
- Java 17 or higher
- Maven 3.6 or higher
- IDE (IntelliJ IDEA, Eclipse, VS Code)
-
Clone the repository
git clone <repository-url> cd spring-boot-master
-
Run with Maven
mvn spring-boot:run
-
Run with IDE
- Import the project as a Maven project
- Run
SpringBootMasterApplication.java
- Application: http://localhost:8080/api/v1
- H2 Console: http://localhost:8080/api/v1/h2-console
- Swagger UI: http://localhost:8080/api/v1/swagger-ui.html
- API Docs: http://localhost:8080/api/v1/api-docs
- Actuator: http://localhost:8080/api/v1/actuator
- Start with
SpringBootMasterApplication.java- understand auto-configuration - Explore
application.properties- configuration management - Review entity classes - JPA mapping concepts
- Study
UserController.java- REST API patterns - Understand request/response handling
- Learn about validation and error handling
- Examine
UserService.java- service layer patterns - Understand transaction management
- Learn about caching mechanisms
- Review repository interfaces - Spring Data JPA
- Study custom queries and pagination
- Understand entity relationships
- Explore
SecurityConfig.java- security configuration - Understand authentication and authorization
- Learn about password encoding
- Study test classes - different testing strategies
- Understand mocking and integration testing
- Learn about test slices (@WebMvcTest, @DataJpaTest)
- Configuration and profiles
- Caching strategies
- API documentation
- Monitoring with Actuator
- Development: Uses H2 in-memory database, detailed logging
- Production: Configured for MySQL, optimized logging
# Development (H2)
spring.datasource.url=jdbc:h2:mem:testdb
spring.h2.console.enabled=true
# Production (MySQL)
spring.datasource.url=jdbc:mysql://localhost:3306/springboot_master_prod
spring.jpa.hibernate.ddl-auto=validateRun tests with Maven:
# Run all tests
mvn test
# Run specific test class
mvn test -Dtest=UserControllerTest
# Run with coverage
mvn test jacoco:report- Layered Architecture - Clear separation of concerns
- DTO Pattern - Separate API contracts from domain models
- Exception Handling - Centralized error management
- Input Validation - Comprehensive validation strategies
- Security - Authentication and authorization
- Testing - Comprehensive test coverage
- Documentation - Self-documenting APIs
- Configuration - Environment-specific settings
- Auto-configuration and starters
- Dependency injection and IoC
- Data access with Spring Data JPA
- RESTful web services
- Security implementation
- Caching mechanisms
- Testing strategies
- Monitoring and management
This project is designed for learning purposes. Feel free to:
- Add new features to practice concepts
- Improve existing implementations
- Add more comprehensive tests
- Enhance documentation
This project is licensed under the MIT License - see the LICENSE file for details.
Spring Boot's power lies in its auto-configuration and convention over configuration approach. When you start the application, here's what happens:
-
@SpringBootApplicationannotation triggers:- Component Scanning: Finds all classes with
@Component,@Service,@Repository,@Controller - Auto-Configuration: Automatically configures beans based on classpath dependencies
- Configuration Processing: Loads properties from
application.properties
- Component Scanning: Finds all classes with
-
Dependency Injection Container is created:
- Spring creates instances of all your classes (beans)
- Injects dependencies automatically (constructor injection in our project)
- Manages the lifecycle of these objects
-
Embedded Server Starts:
- Tomcat server starts on port 8080
- Web context is initialized
- All REST endpoints become available
User Browser → http://localhost:8080/api/v1/users
HTTP Request → DispatcherServlet → UserController
What Happens:
- DispatcherServlet (Spring's front controller) receives the request
- HandlerMapping determines which controller method should handle it
- UserController.getAllUsers() method is invoked
@GetMapping
public ResponseEntity<Page<UserResponseDto>> getAllUsers() {
// Controller validates request, delegates to service
Page<UserResponseDto> users = userService.getAllUsers(pageable);
return ResponseEntity.ok(users);
}Responsibilities:
- Handle HTTP requests/responses
- Validate input parameters
- Convert between DTOs and HTTP responses
- Return appropriate HTTP status codes
@Cacheable("users")
@Transactional(readOnly = true)
public Page<UserResponseDto> getAllUsers(Pageable pageable) {
// Business logic, caching, transaction management
Page<User> users = userRepository.findAll(pageable);
return users.map(this::convertToDto);
}Responsibilities:
- Implement business logic
- Manage transactions (
@Transactional) - Handle caching (
@Cacheable) - Convert entities to DTOs
- Orchestrate multiple repository calls if needed
public interface UserRepository extends JpaRepository<User, Long> {
// Spring Data JPA generates implementation automatically
Page<User> findAll(Pageable pageable);
}What Spring Boot Does:
- Proxy Creation: Spring creates a proxy implementation of your interface
- Method Translation:
findAll()becomesSELECT * FROM users - Result Mapping: Database rows are mapped to
Userentities
-- Generated SQL query
SELECT u.id, u.username, u.email, u.created_at, u.role
FROM users u
LIMIT 20 OFFSET 0;What Happens:
- Hibernate (JPA implementation) generates SQL
- HikariCP (connection pool) manages database connections
- H2 Database executes the query
- Results are mapped back to Java objects
Database → Repository → Service → Controller → HTTP Response → User Browser
1. User Action:
curl -X POST http://localhost:8080/api/v1/users \
-H "Content-Type: application/json" \
-d '{
"username": "john_doe",
"email": "john@example.com",
"password": "securePassword123",
"role": "USER"
}'2. Spring Boot Processing:
// Controller receives request
@PostMapping
public ResponseEntity<UserResponseDto> createUser(@Valid @RequestBody CreateUserDto dto) {
// @Valid triggers validation
UserResponseDto user = userService.createUser(dto);
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}3. Validation Process:
// JSR-303 validation annotations are checked
@NotBlank(message = "Username is required")
@Size(min = 3, max = 50)
private String username;
@Email(message = "Invalid email format")
private String email;4. Service Layer Processing:
@Transactional
public UserResponseDto createUser(CreateUserDto dto) {
// Check for duplicate email
if (userRepository.existsByEmail(dto.getEmail())) {
throw new DuplicateResourceException("Email already exists");
}
// Encode password
String encodedPassword = passwordEncoder.encode(dto.getPassword());
// Create and save user
User user = new User(dto.getUsername(), dto.getEmail(), encodedPassword, dto.getRole());
User savedUser = userRepository.save(user);
// Clear cache
cacheManager.getCache("users").clear();
return convertToDto(savedUser);
}5. Database Transaction:
INSERT INTO users (username, email, password, role, created_at)
VALUES ('john_doe', 'john@example.com', '$2a$10$...', 'USER', '2024-01-15 10:30:00');User sends invalid data:
{
"username": "",
"email": "invalid-email",
"password": "123"
}Spring Boot Response:
// Global Exception Handler catches validation errors
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
// Extract validation errors
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage())
);
return ResponseEntity.badRequest().body(new ErrorResponse("Validation failed", errors));
}
}User receives:
{
"message": "Validation failed",
"errors": {
"username": "Username is required",
"email": "Invalid email format",
"password": "Password must be at least 8 characters"
},
"timestamp": "2024-01-15T10:30:00"
}First request to get users:
@Cacheable("users")
public Page<UserResponseDto> getAllUsers(Pageable pageable) {
// Hits database, stores result in cache
log.info("Fetching users from database");
return userRepository.findAll(pageable).map(this::convertToDto);
}Second identical request:
// Returns cached result, no database hit
log.info("Returning cached users");Cache eviction on user creation:
@CacheEvict(value = "users", allEntries = true)
public UserResponseDto createUser(CreateUserDto dto) {
// Cache is cleared to ensure fresh data
}When user accesses protected endpoint:
- Request Interception:
// Security filter chain intercepts request
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/v1/users/**").authenticated()
)
.httpBasic(Customizer.withDefaults())
.build();
}
}- Authentication Check:
- User provides credentials in request header
- Spring Security validates against configured user details
- If valid, request proceeds to controller
- If invalid, returns 401 Unauthorized
1. Connection Pooling:
# HikariCP configuration
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=52. JPA Optimization:
@Entity
@Table(name = "users", indexes = {
@Index(name = "idx_user_email", columnList = "email"),
@Index(name = "idx_user_username", columnList = "username")
})
public class User {
// Database indexes improve query performance
}3. Pagination:
// Instead of loading all users
public Page<UserResponseDto> getAllUsers(Pageable pageable) {
// Only loads requested page (e.g., 20 records)
return userRepository.findAll(pageable).map(this::convertToDto);
}Actuator endpoints provide insights:
- Health Check:
GET /actuator/health
{
"status": "UP",
"components": {
"db": { "status": "UP" },
"diskSpace": { "status": "UP" }
}
}- Metrics:
GET /actuator/metrics/http.server.requests
{
"name": "http.server.requests",
"measurements": [
{ "statistic": "COUNT", "value": 150 },
{ "statistic": "TOTAL_TIME", "value": 45.2 }
]
}- Spring Boot Handles Complexity: You write simple code, Spring Boot handles the infrastructure
- Convention Over Configuration: Follow naming conventions, get functionality for free
- Layered Architecture: Each layer has specific responsibilities and concerns
- Automatic Wiring: Dependencies are injected automatically based on types
- Production Ready: Built-in security, monitoring, and performance optimizations
- Developer Friendly: Auto-reload, embedded server, comprehensive error messages
This is how Spring Boot transforms complex enterprise application development into a streamlined, productive experience while maintaining professional-grade quality and performance.
After mastering this project, consider exploring:
- Microservices with Spring Cloud
- Reactive Programming with Spring WebFlux
- Message Queues with Spring AMQP
- NoSQL Databases with Spring Data MongoDB
- GraphQL APIs with Spring GraphQL
- Containerization with Docker
- Cloud Deployment with Spring Cloud
Happy Learning! 🚀