β¬ οΈ Back to Architecture Index
Layers Architecture Overview
Introduction
Smart Supply Proβs backend is organized into five distinct logical layers, each with specific responsibilities and clear separation of concerns. This layered architecture enables:
- Maintainability: Changes in one layer donβt cascade to others
- Testability: Each layer can be tested independently with mocks
- Scalability: Layers can be scaled independently based on demand
- Clarity: Clear responsibility boundaries reduce cognitive overhead
The Five Layers
1. Controller Layer (HTTP Entry Point)
Location:
src/main/java/.../controller/
Handles all HTTP concerns: routing, request/response mapping, validation triggering, authorization checks.
Key Components: -
SupplierController - Supplier CRUD endpoints -
InventoryItemController - Inventory management -
StockHistoryController - Audit trail queries -
AnalyticsController - Reporting endpoints -
AuthController - OAuth2 callbacks
Responsibilities: - Route HTTP requests to handlers - Validate incoming DTOs - Check user authorization - Convert HTTP βοΈ DTOs - Build HTTP responses with proper status codes
Learn More: π Controller Layer
2. Service Layer (Business Logic)
Location:
src/main/java/.../service/
The business logic heart of the application. Services orchestrate complex operations, manage transactions, validate business rules, and handle domain logic.
Key Services: - SupplierService - Supplier lifecycle management - InventoryItemService - Item and stock tracking - StockHistoryService - Audit trail management - AnalyticsService - Business intelligence
Responsibilities: - Execute business logic - Manage transaction boundaries - Validate business rules - Translate exceptions to HTTP status codes - Transform between DTOs and entities - Set audit logging
Learn More: π Service Layer
3. Repository Layer (Data Access)
Location:
src/main/java/.../repository/
Abstracts database interactions behind repository interfaces. Built on Spring Data JPA, repositories provide CRUD operations and custom queries.
Key Repositories: -
SupplierRepository - Supplier data access -
InventoryItemRepository - Item persistence and
queries - StockHistoryRepository - Audit entry
access - AppUserRepository - User authentication
data
Responsibilities: - Encapsulate SQL/JPQL queries - Manage entity persistence - Handle pagination and sorting - Provide query results to services - Manage transaction boundaries with database
Learn More: π Repository Layer
4. Domain Model & Data Layer (Entities)
Location:
src/main/java/.../model/ and
src/main/java/.../enums/
Defines JPA entities that map to database tables. These are the core domain objects representing business concepts.
Key Entities: - Supplier - Goods providers - InventoryItem - Products in inventory - StockHistory - Immutable audit trail - AppUser - OAuth2 principals - Enumerations - Role and StockChangeReason types
Responsibilities: - Map database schema to Java objects - Define entity relationships (foreign keys) - Enforce data constraints (unique, not null) - Track audit information (creator, timestamp) - Support optimistic locking with version fields
Learn More: π Domain Model & Data Layer
5. Infrastructure & Cross-Cutting Concerns (Support Services)
Location:
src/main/java/.../config/,
src/main/java/.../security/,
src/main/java/.../validation/,
src/main/java/.../exception/,
src/main/java/.../mapper/
Provides foundational services and handles concerns that span multiple layers.
Key Components: - Security:
OAuth2 authentication, authorization, @PreAuthorize
- Validation:
Custom validators for business rules - Exception
Handling: Global exception handler, error responses
- Data
Mapping: DTO βοΈ Entity converters - Configuration:
Spring beans, application properties
Responsibilities: - Authenticate and authorize users - Validate inputs across all layers - Handle exceptions consistently - Transform data between representations - Configure Spring beans and properties
Learn More: π Infrastructure & Cross-Cutting Concerns
Layered Architecture Diagram
REST Requests"] subgraph "Layer 1: Presentation" Controllers["Controllers
SupplierController
InventoryItemController
AnalyticsController"] end subgraph "Layer 2: Business Logic" Services["Services
SupplierService
InventoryItemService
AnalyticsService"] Validators["Validators
SupplierValidator
InventoryItemValidator"] end subgraph "Layer 3: Data Access" Repositories["Repositories
SupplierRepository
InventoryItemRepository
StockHistoryRepository"] end subgraph "Layer 4: Domain Model" Entities["Entities
Supplier
InventoryItem
StockHistory
AppUser"] end subgraph "Layer 5: Infrastructure" Security["Security
OAuth2, @PreAuthorize"] Exception["Exception Handler
GlobalExceptionHandler"] Mapper["Mappers
DTO β Entity"] Config["Configuration
Spring Beans"] end Database["Database
Oracle/PostgreSQL"] Client -->|HTTP| Controllers Controllers -->|Call| Services Services -->|Call| Validators Services -->|Call| Repositories Repositories -->|Query/Persist| Entities Entities -->|Map| Database Controllers -->|Use| Security Controllers -->|Use| Mapper Services -->|Use| Exception Services -->|Use| Mapper Security -.->|Protect| Controllers Exception -.->|Handle| Services Config -.->|Configure| Controllers Config -.->|Configure| Services style Client fill:#e3f2fd style Controllers fill:#bbdefb style Services fill:#90caf9 style Validators fill:#fff9c4 style Repositories fill:#64b5f6 style Entities fill:#42a5f5 style Security fill:#ef9a9a style Exception fill:#ef9a9a style Mapper fill:#a5d6a7 style Config fill:#c8e6c9 style Database fill:#0277bd
Request Flow Through Layers
Hereβs how a typical request (creating a supplier) flows through all layers:
1. HTTP POST /api/suppliers
Client β Network
β
2. SupplierController.create(CreateSupplierDTO)
- Receives JSON request body
- @Valid validates DTO fields
- @PreAuthorize("hasRole('ADMIN')") checks authorization
β
3. SupplierService.create(CreateSupplierDTO)
- SupplierValidator validates uniqueness
- Converts DTO β Entity
- Sets createdBy from SecurityContext
β
4. SupplierRepository.save(Supplier)
- Executes INSERT to SUPPLIER table
- Handles primary key generation
- Triggers database constraints
β
5. Database executes INSERT
- Validates UNIQUE constraint on NAME
- Stores record in SUPPLIER table
β
6. Repository returns saved entity
- With generated ID
β
7. Service converts Entity β DTO
β
8. Controller builds HTTP response
- Status: 201 CREATED
- Body: SupplierDTO
- Header: Location: /api/suppliers/{id}
β
9. HTTP Response
Client β Network
Layer Communication Patterns
Downward Communication (Normal Flow)
Layers call the layer directly below them:
Controller β Service β Repository β Database
- Controllers delegate to services
- Services delegate to repositories
- Repositories delegate to database
Upward Communication (Error Flow)
Exceptions propagate upward to be handled:
Database β Repository β Service β GlobalExceptionHandler β HTTP Response
- Database constraint violation
- Repository translates to domain exception
- Service lets exception propagate
- GlobalExceptionHandler catches and translates to HTTP response
Cross-Layer Communication (Infrastructure)
Infrastructure components available to all layers:
All Layers β Security, Validation, Exception Handling, Mapping, Configuration
Benefits of Layered Architecture
1. Separation of Concerns
Each layer has one clear responsibility. You know where to look for specific code.
2. Testability
Each layer can be unit tested in isolation by mocking layers below it.
// Test service without touching database
@ExtendWith(MockitoExtension.class)
class SupplierServiceCreateTest {
@Mock
private SupplierRepository repository;
@InjectMocks
private SupplierService service;
// Tests run without database
}3. Maintainability
Changes in one layer donβt cascade to others. Update database schema without touching services.
4. Scalability
Layers can be scaled independently. Cache the service layer, scale the database tier separately.
5. Clarity
New developers quickly understand where to add new features.
Dependency Rules
Key Principle: Never skip layers or call downward incorrectly.
β
Correct Dependencies:
Controller β Service β Repository β Database
β Incorrect Dependencies:
Controller β Repository (skips service logic)
Repository β Controller (upward communication)
Service β Service (cross-service dependencies)
Layer Decision Flow
When adding a new feature, ask:
1. Is it HTTP concern? β Controller
2. Is it business logic? β Service
3. Is it data access? β Repository
4. Is it domain model? β Entity
5. Is it cross-cutting? β Infrastructure
Files in This Directory
| File | Purpose | Audience |
|---|---|---|
| controller-layer.html | HTTP API handling | API developers, Controllers |
| service-layer.html | Business logic | Feature developers, Services |
| repository-layer.html | Data persistence | Database developers, Queries |
| model-layer.html | Domain entities | Data modelers, Entity authors |
| infrastructure/index.html | Cross-cutting concerns | All developers, Security/Exceptions |
Quick Navigation
By Role:
- Backend Developer: Start with Service Layer β Controller Layer
- Database Developer: Focus on Repository Layer β Model Layer
- Security Engineer: Review Infrastructure Layer
- DevOps/Infrastructure: Check Infrastructure Layer configuration
By Activity:
- Adding a new endpoint: Controller Layer β Service Layer
- Implementing business logic: Service Layer β Repository Layer
- Working with data: Model Layer β Repository Layer
- Fixing exceptions: Exception Handling
- Adding validation: Validation or Service Layer