dany giguere
11/07/2025, 8:46 PMsuspend fun register(
@RequestBody request: RegisterRequest,
exchange: ServerWebExchange
): ResponseEntity<DataResponse<Map<String, String>>> {
registerRequestValidator.validate(request, exchange)
or with an annotation
@ValidateWith(RegisterPayloadValidator::class)
suspend fun register(
@RequestBody request: RegisterRequest,
exchange: ServerWebExchange
): ResponseEntity<DataResponse<Map<String, String>>> {
The annotation is simpler but then the end users will have to add these 2 librairies to their spring app
// AspectJ dependencies for ValidationAspect
implementation("org.springframework:spring-aop")
implementation("org.aspectj:aspectjweaver:1.9.22")
Anyone know these dependencies ? would it be a turn off ? There are also other options (to make the validation happen before entering the method) but I like the simplicity of the annotation. @ValidateWith(RegisterPayloadValidator::class)ashmelev
11/07/2025, 8:51 PMRiccardo Cardin
11/08/2025, 7:58 AMdany giguere
11/09/2025, 1:48 AM@Component
class UniqueEmailRule(
private val userService: UserService,
private val messageSource: MessageSource
) : ValidationRule {
override suspend fun validate(value: Any?, locale: Locale): String? {
if (value == null || value !is String) return null // Single Responsibility: Each rule does ONE thing well
if (value.isBlank()) return null
return try {
val exists = userService.findByEmail(value) != null
if (exists) {
messageSource.getMessage("enter_unique_email", null, locale)
} else null
} catch (e: Exception) {
null // If error checking, let it pass (other validations will catch issues)
}
}
}
// Usage in validator
validator.validate(request, locale) {
field(RegisterRequest::email) {
required()
email()
custom(uniqueEmailRule) // Check database for uniqueness
}
}
I had to do a a runBlocking with the Jakarta Validation. And by the way, I ended up not adding the other libraries to keep the package simple.Riccardo Cardin
11/09/2025, 8:29 AMRiccardo Cardin
11/09/2025, 8:32 AMdany giguere
11/09/2025, 9:15 AMRiccardo Cardin
11/09/2025, 9:20 AMI wonder though if any validation doing queries to the db would be considered businessyes, they do. I would remove the example from the documentation.
Riccardo Cardin
11/09/2025, 9:22 AMdany giguere
11/09/2025, 9:23 AMdany giguere
11/09/2025, 9:23 AMThere are indeed two types of validation:
1. Syntactic/Input Validation (Data validation)
- Format checks (email format, length, regex patterns)
- Type validation (is this a number? a valid date?)
- Structure validation (required fields, field relationships)
- Purpose: Ensure the data is well-formed and safe to process
2. Business/Domain Validation (Business rules)
- Uniqueness constraints
- Business logic rules (e.g., "can't delete an order that's already shipped")
- Domain-specific constraints (e.g., "age must be 18+ for this product")
- Purpose: Ensure the operation is valid within your business context
Where Each Should Live
Traditional separation:
- Controller/Presentation Layer: Syntactic validation only
- Service/Domain Layer: Business validation
So checking if an email is unique would typically belong in your service layer, not in a validation framework at the controller boundary.
However, There's Nuance Here
Arguments FOR including uniqueness in this validation DSL:
1. User Experience: You want to tell the user immediately "this email is taken" rather than fail later in the service layer
2. Fail Fast: Why process the entire request if you know it will fail on a business rule?
3. Consistent Error Format: Users get the same error response structure for all validation failures
4. Pragmatism: In many CRUD applications, the line between "input validation" and "business validation" is blurry
Arguments AGAINST:
1. Architectural Purity: Mixing concerns - validation framework now has database dependencies
2. Reusability: Service methods should validate their own business rules regardless of how they're called (API, CLI, internal service)
3. Testing Complexity: Harder to unit test validators that need database access
4. Performance: Syntactic validation is fast; business validation might be slowdany giguere
11/09/2025, 9:25 AMkqr
11/10/2025, 7:47 AMdany giguere
11/10/2025, 12:33 PM