A complete demonstration of the Service Layer architectural pattern in Spring Boot, showing how to build clean, maintainable, and testable REST APIs with proper separation of concerns.
This project demonstrates the Service Layer Pattern - an architectural pattern that separates business logic from controllers and data access layers. It shows best practices for building scalable Spring Boot applications with:
- Clean Architecture: Clear separation between Controller, Service, and Repository layers
- Business Logic Isolation: All business rules centralized in the service layer
- Proper Exception Handling: Custom exceptions with global error handling
- Input Validation: Bean Validation with comprehensive error responses
- MongoDB Integration: Using Spring Data MongoDB for data persistence
- Comprehensive Testing: Unit and integration tests with high coverage
- User management (CRUD operations)
- Email validation and uniqueness checks
- Active/inactive user states
- RESTful API design
- Global exception handling with proper HTTP status codes
- Mock email service for demonstration
- Unit tests for service and controller layers
- Spring Data MongoDB integration
- Java 17
- Spring Boot 3.5.7
- Spring Data MongoDB
- Spring Boot Validation
- MongoDB
- JUnit 5 & Mockito for testing
- Maven for dependency management
Before you begin, ensure you have the following installed:
- Java 17 or higher (Download)
- Maven 3.9+ (Download)
- MongoDB Atlas account (Sign up free) or local MongoDB installation
git clone https://github.com/mongodb-developer/spring-service-layer.git
cd spring-service-layer- Create a free account at MongoDB Atlas
- Create a new cluster (free tier M0 is fine)
- Create a database user with read/write permissions
- Whitelist your IP address (or use
0.0.0.0/0for development) - Get your connection string by clicking "Connect" → "Connect your application"
Your connection string will look like:
mongodb+srv://username:[email protected]/?appName=Cluster0
Update src/main/resources/application.properties:
spring.application.name=spring-service-layer
# MongoDB Configuration
# IMPORTANT: Replace ?appName=Cluster0 with ?appName=spring-service-layer-tutorial
# This helps track tutorial usage!
# For MongoDB Atlas:
spring.data.mongodb.uri=mongodb+srv://username:[email protected]/?appName=spring-service-layer-tutorial
# For Local MongoDB:
# spring.data.mongodb.uri=mongodb://localhost:27017/serviceLayer?appName=spring-service-layer-tutorial
spring.data.mongodb.database=serviceLayer
# Logging
logging.level.com.mongodb.springservicelayer=INFOImportant: Replace username, password, and cluster.abc12 with your actual MongoDB credentials.
mvn clean installmvn spring-boot:runThe application will start on http://localhost:8080
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "[email protected]"
}'Response (201 Created):
{
"id": "generated-uuid",
"email": "[email protected]",
"name": "John Doe",
"createdAt": "2024-11-06T10:30:45.123",
"active": true
}curl -X GET http://localhost:8080/api/users/{id}curl -X PUT http://localhost:8080/api/users/{id}/name \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Doe"
}'curl -X DELETE http://localhost:8080/api/users/{id}curl -X GET http://localhost:8080/api/users/activemvn test# Controller tests
mvn test -Dtest=UserControllerTest
# Service tests
mvn test -Dtest=UserServiceImplTestThe project includes comprehensive tests for:
- Controller layer (REST API endpoints)
- Service layer (business logic)
- Exception handling
- Validation logic
spring-service-layer/
├── src/
│ ├── main/
│ │ ├── java/com/mongodb/springservicelayer/
│ │ │ ├── SpringServiceLayerApplication.java
│ │ │ ├── controller/
│ │ │ │ ├── UserController.java
│ │ │ │ ├── CreateUserRequest.java
│ │ │ │ └── UpdateNameRequest.java
│ │ │ ├── service/
│ │ │ │ ├── UserService.java
│ │ │ │ ├── UserServiceImpl.java
│ │ │ │ ├── EmailService.java
│ │ │ │ └── EmailServiceImpl.java
│ │ │ ├── repository/
│ │ │ │ └── UserRepository.java
│ │ │ ├── model/
│ │ │ │ └── User.java
│ │ │ └── exception/
│ │ │ ├── DuplicateEmailException.java
│ │ │ ├── InvalidEmailException.java
│ │ │ ├── UserNotFoundException.java
│ │ │ ├── UserInactiveException.java
│ │ │ └── GlobalExceptionHandler.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/
│ └── java/com/mongodb/springservicelayer/
│ ├── controller/
│ │ └── UserControllerTest.java
│ └── service/
│ └── UserServiceImplTest.java
├── pom.xml
└── README.md
Business logic is isolated in the service layer, keeping controllers thin and repositories focused on data access.
All components use constructor injection for better testability and immutability.
Custom business exceptions with a global exception handler that returns proper HTTP status codes:
400 Bad Request- Validation errors403 Forbidden- Business rule violations (inactive users)404 Not Found- Resource not found409 Conflict- Duplicate resources
Bean Validation annotations (@NotBlank, @Email) with automatic error responses.
- Unit tests with mocked dependencies
- Integration tests for API endpoints
- High test coverage for critical business logic
Topics covered:
- What is the Service Layer pattern and why use it?
- How it fits with MVC architecture
- Step-by-step implementation guide
- Best practices and common mistakes
- MongoDB integration
⭐ If you found this project helpful, please give it a star!