Model Layer
📝 Note: This guide uses generic placeholder names to be reusable across any Spring Boot microservice. Replace with your actual implementation:
{YourService}→ Your service name (e.g.,OrderService,PaymentService)BusinessService→ Your core service (e.g.,OrderService,UserService)DataService→ Your data processing service (e.g.,PaymentService,InventoryService)IntegrationService→ Your external integration (e.g.,PaymentGatewayService){RequestType}→ Your request DTO (e.g.,CreateOrderRequest){ResponseType}→ Your response DTO (e.g.,OrderResponse)
Purpose
The model layer contains all data transfer objects (DTOs), domain models, and request/response schemas. It defines the structure of data flowing through the application and to/from external systems.
Core Principles
- Immutability First: All DTOs use final fields with no setters for thread safety
- Builder Pattern: Complex objects use fluent builders for readable construction
- Type Safety: Enums over strings for type-safe constants
- Clean Separation: Pure data models without business logic
- OpenAPI-Driven: API models generated from OpenAPI specifications
Package Structure
model/
├── rest/ # OpenAPI-generated REST DTOs
├── auth/rest/ # Authentication-specific models
├── token/ # Token-related models
│ ├── ping/redis/ # Redis token models
│ └── rest/ # REST token models
├── profile/rest/ # User profile models
├── claims/ # JWT claims models
├── wrapper/ # Parameter wrapper objects
└── featureflags/ # Feature flag models
Documentation
📚 Guides
Comprehensive guides covering model layer development:
- Design Patterns - DTO, Builder, Value Object, Wrapper patterns
- Best Practices - Immutability, naming, validation, serialization
- Testing Strategies - Unit tests, serialization tests, validation tests
- Anti-Patterns - Common mistakes and how to avoid them
💡 Examples
Compilable Java examples demonstrating key concepts:
- SchemasAccountExample.java - Immutable DTO pattern
- AuthParametersWrapperExample.java - Builder pattern
- SchemasAuthenticatedAmcnTokensExample.java - JSON annotations
- EnumTypeExample.java - Type-safe enums
- TokenPayloadWrapperExample.java - Wrapper pattern
Quick Reference
Common Model Types
| Type | Purpose | Example |
|---|---|---|
| Request Models | API request bodies | CreateAccountRequest |
| Response Models | API responses | AuthenticatedAmcnTokens |
| Domain Models | Business entities | Account, Token |
| Wrappers | Parameter aggregation | RequestParametersWrapper |
| Claims | data token claims | PayloadWrapper |
| Events | Message queue events | DomainEvent |
Key Annotations
| Annotation | Purpose | Example |
|---|---|---|
@JsonProperty |
Map field to JSON property | @JsonProperty("accessToken") |
@JsonInclude |
Control field inclusion | @JsonInclude(NON_NULL) |
@JsonIgnore |
Exclude from serialization | @JsonIgnore |
@NotNull |
Field cannot be null | @NotNull(message = "Required") |
@Email |
Email format validation | @Email |
@Size |
String/collection size | @Size(min=8, max=128) |
@Pattern |
Regex validation | @Pattern(regexp="^[A-Z]{2}$") |
Design Pattern Selection
| Scenario | Pattern | Guide |
|---|---|---|
| API request/response | DTO | Patterns Guide |
| Complex object (4+ fields) | Builder | Patterns Guide |
| Type-safe constants | Enum | Best Practices |
| Many method parameters (4+) | Wrapper | Patterns Guide |
| Generated from API spec | OpenAPI | Patterns Guide |
Essential Commands
Code Formatting
# Apply Spotless formatting (required before commit)
./gradlew spotlessApply
# Check formatting without changes
./gradlew spotlessCheck
OpenAPI Code Generation
# Generate models from OpenAPI spec
./gradlew openApiGenerate
# Generated models appear in: model/rest/
Development Checklist
When creating a new model, ensure:
- ✅ Immutable: Final fields, no setters
- ✅ Builder: Use builder pattern for 4+ fields
- ✅ Annotations: Proper Jackson annotations (
@JsonProperty,@JsonInclude) - ✅ Validation: Bean validation annotations where appropriate
- ✅ Javadoc: Document public classes and methods
- ✅ Naming: Descriptive PascalCase for classes, camelCase for fields
- ✅ No Logic: Pure data, no business logic
- ✅ Security: No sensitive data in
toString()or logs - ✅ Formatted: Run
./gradlew spotlessApply - ✅ Tested: Unit tests for construction, serialization, validation
Common Pitfalls
Avoid these anti-patterns:
| ❌ Don't | ✅ Do |
|---|---|
| Mutable DTOs with setters | Immutable with final fields |
| Business logic in models | Pure data, logic in services |
| God objects (20+ fields) | Split into focused models |
| Circular references | Use IDs or @JsonIgnore |
| 5+ method parameters | Use wrapper objects |
| String constants | Type-safe enums |
| Modifying generated code | Extend or wrap |
| Missing null handling | Validate or use Optional |
| Sensitive data exposure | @JsonIgnore + separate DTOs |
See Anti-Patterns Guide for detailed explanations and solutions.
Need Help?
- Design pattern question? → Patterns Guide
- How to implement something? → Best Practices
- How to test? → Testing Guide
- Something not working? → Anti-Patterns Guide
- Need examples? → Check examples/ directory
Summary
The model layer uses proven patterns (DTO, Builder, Value Object, Wrapper) to create clean, type-safe, and maintainable data structures. All technical content has been organized into focused guides and runnable examples. Follow the checklist above for consistent, high-quality model implementations.