patternjavaspringTip
Java records as immutable DTOs and value objects
Viewed 0 times
Java 16+
recordsDTOimmutableJava 16value objectJackson deserialization
Problem
Writing data carrier classes in Java requires boilerplate: private fields, constructor, getters, equals/hashCode, and toString. This noise obscures the actual data model and creates maintenance burden when fields change.
Solution
Use Java records (Java 16+) for DTOs, value objects, and response/request bodies:
Jackson serializes/deserializes records out of the box in Spring Boot 2.5+ (Jackson 2.12+).
// DTO — accessor methods are field names, not getBean()
public record OrderResponse(
Long id,
String status,
BigDecimal total,
List<OrderItemResponse> items,
Instant createdAt
) {}
// With custom validation (records work with Bean Validation)
public record CreateOrderRequest(
@NotBlank String customerId,
@NotEmpty @Size(max = 50) List<@Valid OrderItemRequest> items
) {}
// With compact constructor for normalization
public record EmailAddress(String value) {
public EmailAddress {
Objects.requireNonNull(value);
value = value.trim().toLowerCase();
}
}Jackson serializes/deserializes records out of the box in Spring Boot 2.5+ (Jackson 2.12+).
Why
Records are transparent data carriers: all fields are declared in the header, the compiler generates a canonical constructor, accessors, equals, hashCode, and toString. They enforce immutability via final fields.
Gotchas
- Records cannot extend classes (they implicitly extend java.lang.Record) — use interfaces instead
- Record accessor methods are named after the field (id(), not getId()) — check MapStruct and other frameworks that expect getX() naming
- Jackson requires a no-args constructor or @JsonCreator for deserialization on some older versions — test explicitly
Revisions (0)
No revisions yet.