Validation is a critical aspect of API development to ensure data integrity and early invalid requests detection. In this post, we’ll learn how to implement field-level validation and custom validation logic in Spring REST Framework (SRF) using Dto objects during deserialization.
1. Field-Level Validation with Annotations
The SRF provides the @FieldValidation
annotation for quick and declarative validation on DTO fields. You can enforce rules such as minimum/maximum length, numeric ranges, and more.
Example: Basic Field Validation
import io.github.nikanique.springrestframework.annotation.FieldValidation;
import io.github.nikanique.springrestframework.annotation.ReadOnly;
import io.github.nikanique.springrestframework.dto.Dto;
import lombok.Data;
@Data
public class StudentDto extends Dto {
@ReadOnly
private Long id;
@FieldValidation(minLength = 2, maxLength = 50)
private String name;
@FieldValidation(allowNull = false)
private String nationality;
@FieldValidation(minValue = 1, maxValue = 12)
private Integer grade;
}
This declarative validation automatically applies during deserialization. If the incoming request fails these validations, an error response will be generated.
The complete list of supported attributes and their functionality:
1. maxLength
and minLength
These attributes validate the length of a string field.
-
maxLength
: The maximum allowed length of the string (default:Integer.MAX_VALUE
, meaning no limit). -
minLength
: The minimum required length of the string (default:-1
, meaning no restriction).
Example
@FieldValidation(minLength = 3, maxLength = 50)
private String name;
- Ensures the
name
field has a length between 3 and 50 characters. - If
name
is shorter than 3 or longer than 50, an error is returned.
2. blank
This attribute validates whether the field can be blank.
-
blank = true
: Allows blank values. -
blank = false
: Disallows blank values (default).
Example
@FieldValidation(blank = false)
private String description;
- Ensures the
description
field cannot be blank.
3. minValue
and maxValue
These attributes validate the numeric range of a field.
-
minValue
: The minimum allowable numeric value (default:Integer.MIN_VALUE
). -
maxValue
: The maximum allowable numeric value (default:Integer.MAX_VALUE
).
Example
@FieldValidation(minValue = 1, maxValue = 12)
private Integer grade;
- Ensures the
grade
field contains a value between 1 and 12 (inclusive).
4. nullable
This attribute specifies whether the field can accept null
values.
-
nullable = true
: Allowsnull
values (default). -
nullable = false
: Disallowsnull
values.
Example
@FieldValidation(nullable = false)
private String nationality;
- Ensures the
nationality
field cannot benull
.
5. minDate
and maxDate
These attributes validate whether a date field falls within a specific range. It should be provided in yyyy-MM-dd
or yyyy-MM-dd HH:mm:ss
formats.
-
minDate
: The earliest allowable date (default: ""). -
maxDate
: The latest allowable date (default: "").
Example
@FieldValidation(minDate = "2000-01-01", maxDate = "2024-12-31")
private String dateOfBirth;
- Ensures the
dateOfBirth
is between January 1, 2000 and December 31, 2024.
Full Example Using All Field Validation Options:
Here’s an example DTO that uses various @FieldValidation
attributes to validate input fields:
import io.github.nikanique.springrestframework.annotation.FieldValidation;
import io.github.nikanique.springrestframework.dto.Dto;
import lombok.Data;
@Data
public class StudentDto extends Dto {
@FieldValidation(nullable = false, minLength = 2, maxLength = 50)
private String name; // Must be between 2 and 50 characters, and cannot be null.
@FieldValidation(blank = false)
private String nationality; // Cannot be blank (empty or whitespace).
@FieldValidation(minValue = 1, maxValue = 12)
private Integer grade; // Must be between 1 and 12.
@FieldValidation(minDate = "2000-01-01", maxDate = "2024-12-31")
private String dateOfBirth; // Must be within the specified date range.
}
If a request contains invalid data, SRF will return a structured response with detailed error messages. For example, if the name
is too short and grade
is out of range, the response will look like this:
Request (Invalid Data)
{
"name": "A",
"nationality": "",
"grade": 13,
"dateOfBirth": "1990-12-31"
}
Response (Validation Errors)
{
"errors": {
"name": "Length must be between 2 and 50 characters.",
"nationality": "Cannot be blank.",
"grade": "Value must be between 1 and 12.",
"dateOfBirth": "Date must be between 2000-01-01 and 2024-12-31."
}
}
Notice that fields marked as
@ReadOnly
will not be validated because they are excluded from input.
2. Overriding the validate Method for Custom Logic
For more complex scenarios, you can combine these annotations with custom validation logic by overriding the validate
method in your DTO. Here’s an example of overriding the validate method of a Dto:
import io.github.nikanique.springrestframework.annotation.FieldValidation;
import io.github.nikanique.springrestframework.dto.Dto;
import lombok.Data;
import java.util.Map;
@Data
public class ProductDTO extends Dto {
@ReadOnly
private Integer id;
private String model;
@FieldValidation(minLength = 3)
private String company;
@Override
public Map<String, String> validate(Boolean raiseValidationError) throws Throwable {
Map<String, String> validationErrors = super.validate(false);
if (company != null && company.equalsIgnoreCase("BMW")) {
validationErrors.put("company", "Company cannot be BMW.");
}
// Raise validation error if specified
if (!validationErrors.isEmpty() && raiseValidationError) {
throw new ValidationException(validationErrors);
}
return validationErrors;
}
}
The super.validate(false)
calls the default validation logic for @FieldValidation
annotations to apply base validation logic for standard validations. Here I passed false
to called validate
method to let the overridden method to send complete validation error in the exception message.
Conclusion
The @FieldValidation
annotation in Spring REST Framework (SRF) provides a powerful way to enforce input validation. It simplifies validation for common rules like length, range, nullability, and date constraints. For more complex scenarios, you can combine these annotations with custom validation logic by overriding the validate
method in your DTO.
Top comments (0)