79527389

Date: 2025-03-22 11:54:57
Score: 1
Natty:
Report link

Using Value Objects (VOs) for validation is a great approach to encapsulate constraints and avoid repeated annotations. However, as you pointed out, a fundamental property of value objects is that they should not be null, which conflicts with the optional fields in your BankUpdateRequest.

Possible Approaches

Here are some ways to balance clean design with flexibility for updates:

1. Use Value Objects but Allow null in DTOs

public record Name(String value) {     public Name {         if (value != null) {             if (value.isBlank()) throw new IllegalArgumentException("The name is a required field.");             if (value.length() > 255) throw new IllegalArgumentException("The name cannot be longer than 255 characters.");             if (!value.matches("^[a-zA-ZčćžšđČĆŽŠĐ\\s]+$"))                  throw new IllegalArgumentException("The name can only contain alphabetic characters.");         }     } } 

Then your DTOs become:

public record BankCreateRequest(@NotNull Name name, @NotNull BankAccountNumber bankAccountNumber, Fax fax) {}  public record BankUpdateRequest(Name name, BankAccountNumber bankAccountNumber, Fax fax) {} 

Pros:

Cons:


2. Combine VOs with Bean Validation

An alternative is keeping Spring’s validation for DTOs but still using Value Objects:

public record BankCreateRequest(     @NotNull Name name,     @NotNull BankAccountNumber bankAccountNumber,     Fax fax ) {}  public record BankUpdateRequest(     Name name,     BankAccountNumber bankAccountNumber,     Fax fax ) {} 

Then keep Hibernate Validator annotations inside the VOs:

@Value public class Name {     @NotBlank(message = "The name is a required field.")     @Size(max = 255, message = "The name cannot be longer than 255 characters.")     @Pattern(regexp = "^[a-zA-ZčćžšđČĆŽŠĐ\\s]+$", message = "The name can only contain alphabetic characters.")     String value; } 

Key Trick: Use @Valid in DTOs to trigger Spring validation:

public record BankCreateRequest(@Valid @NotNull Name name, @Valid @NotNull BankAccountNumber bankAccountNumber, @Valid Fax fax) {}  public record BankUpdateRequest(@Valid Name name, @Valid BankAccountNumber bankAccountNumber, @Valid Fax fax) {} 

Pros:

Cons:


Which is Better?

Recommendation: Use Approach 2 (@Valid + VOs). It’s simpler, aligns with Spring Boot, and still removes duplication.

Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • User mentioned (1): @Valid
  • Low reputation (1):
Posted by: bingeek