Domain knowledge for Java 21+ and Spring Boot 3.x development patterns. Covers constructor injection, records for DTOs, JPA entity patterns, @ControllerAdvice, Spring profiles, Flyway migrations, and testing with Testcontainers. Use as the primary coding reference for all Java/Spring Boot code generation.
This skill establishes the coding standards and patterns for Java 21+ with Spring Boot 3.x. All generated code should follow these conventions for consistency across the codebase. This serves as the primary reference for code generation decisions.
Use records for all immutable data carriers — request DTOs, response DTOs, and value objects:
// Request DTO with validation
public record CreateFieldRequest(
@NotBlank String fieldName,
@NotBlank String fieldType,
String format,
String description,
boolean required,
@NotBlank String schemaName
) {}
// Response DTO
public record FieldResponse(
Long id,
String fieldName,
String fieldType,
String format,
String description,
boolean required,
String schemaName,
Instant createdAt
) {
public static FieldResponse from(ApiField entity) {
return new FieldResponse(
entity.getId(),
entity.getFieldName(),
entity.getFieldType(),
entity.getFormat(),
entity.getDescription(),
entity.isRequired(),
entity.getSchemaName(),
entity.getCreatedAt()
);
}
}
// Paginated response wrapper
public record PageResponse<T>(
List<T> content,
int page,
int size,
long totalElements,
int totalPages,
boolean hasNext
) {
public static <T> PageResponse<T> from(Page<T> page) {
return new PageResponse<>(
page.getContent(),
page.getNumber(),
page.getSize(),
page.getTotalElements(),
page.getTotalPages(),
page.hasNext()
);
}
}
Use sealed classes for domain type hierarchies:
public sealed interface SearchResult permits FieldResult, SchemaResult, EndpointResult {
String displayName();
double relevanceScore();
}
public record FieldResult(String fieldName, String type, double relevanceScore) implements SearchResult {
@Override public String displayName() { return fieldName; }
}
public record SchemaResult(String schemaName, int fieldCount, double relevanceScore) implements SearchResult {
@Override public String displayName() { return schemaName; }
}
// switch expressions with pattern matching
public String describe(SearchResult result) {
return switch (result) {
case FieldResult f -> "Field: %s (%s)".formatted(f.fieldName(), f.type());
case SchemaResult s -> "Schema: %s with %d fields".formatted(s.schemaName(), s.fieldCount());
case EndpointResult e -> "Endpoint: %s %s".formatted(e.method(), e.path());
};
}
// instanceof pattern matching
if (obj instanceof ApiField field && field.isRequired()) {
processRequired(field);
}
Use text blocks for multi-line strings, SQL, and JSON:
String sql = """
SELECT f.id, f.field_name, f.description
FROM api_fields f
WHERE f.schema_name = :schemaName
ORDER BY f.field_name
""";
Enable virtual threads in application.yml: