Validator 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 validator layer centralizes all input validation logic. It validates HTTP headers, request parameters, and business rules before data reaches the service layer, ensuring fail-fast behavior and consistent error messages.
Architecture
- Validator Component Pattern: Spring
@Componentvalidators injected into controllers - Fail-Fast Validation: Validate all inputs before processing
- Single Responsibility: Each validation method has one clear purpose
- Consistent Error Messages: Standardized exception types and messages
Package Structure
validator/
└── RequestValidator.java # Centralized validation logic
Quick Reference
Basic Validator Pattern
@Component
public class RequestValidator {
public void validateEmail(String email) {
if (StringUtils.isBlank(email)) {
throw new BadRequestException("Email is required");
}
if (!EMAIL_PATTERN.matcher(email).matches()) {
throw new BadRequestException("Email format is invalid");
}
}
}
Controller Integration
@RestController
public class BusinessApiImpl {
private final RequestValidator validator;
@Override
public ResponseEntity<Response> endpoint(String param) {
// Validate first
validator.validateParam(param);
// Process with valid inputs
return ResponseEntity.ok(service.process(param));
}
}
Validation Types
- Required Field: Check null/blank values
- Format: Email, UUID, country code patterns
- Range: Min/max value validation
- Enum: Whitelist of valid values
- Conditional: Business rule-based validation
Common Utilities
// Apache Commons Lang
StringUtils.isBlank(str) // null, empty, or whitespace
StringUtils.isEmpty(str) // null or empty
// Pre-compiled patterns
private static final Pattern EMAIL_PATTERN =
Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
Testing Pattern
@Test
void testValidate_Valid() {
assertDoesNotThrow(() -> validator.validate("valid-input"));
}
@Test
void testValidate_Invalid() {
BadRequestException ex = assertThrows(
BadRequestException.class,
() -> validator.validate(null)
);
assertEquals("Field is required", ex.getMessage());
}
Key Principles
✅ DO
- Validate all inputs before processing
- Use specific exception types (BadRequestException)
- Write descriptive error messages
- Pre-compile regex patterns
- Test happy path and error cases
- Order validations by cost (cheap first)
❌ DON'T
- Validate in service layer (keep in validators)
- Return boolean (throw exceptions instead)
- Use generic error messages
- Make expensive calls (DB, API) in validators
- Duplicate validation logic
Documentation
Detailed Guides
- Patterns - Architectural patterns and design approaches
- Best Practices - Coding standards and conventions
- Testing - Comprehensive testing strategies
- Anti-Patterns - Common mistakes to avoid
Code Examples
See examples/ for complete, working code:
RequestValidator.java- Full validator implementationBusinessApiImpl.java- Controller integrationRequestValidatorTest.java- Comprehensive test suite- Supporting classes (exceptions, services, etc.)
Package: com.example.microserviceorch.validator.example
Code Formatting
All Java code is formatted using Spotless with Google Java Format (AOSP style).
./gradlew spotlessApply
Summary
The validator layer ensures:
- Reliability: All invalid inputs are caught early
- Consistency: Standardized validation across endpoints
- Maintainability: Centralized, reusable validation logic
- Security: Proper input sanitization and validation
- Performance: Fast, efficient validation checks
For detailed information on specific topics, see the guides above.