Speedy offers a lightweight, annotation-driven validation layer that is automatically
executed for every CREATE / UPDATE / DELETE request.
Validation rules can be declared with either Jakarta Bean Validation annotations
or Speedy-specific annotations – both variants are mapped to the same internal
rules so you can choose the style that best suits your codebase.
⚠️ Server-side validation is performed before persistence; invalid payloads result in HTTP
400 Bad Requestwith a descriptive error message.
Jakarta
@Column(name = "salary", nullable = false)
@Positive
private BigDecimal salary;
Speedy
@Column(name = "salary", nullable = false)
@SpeedyPositive
private BigDecimal salary;
If the client submits salary <= 0 the request fails with:
HTTP 400 – salary must be > 0
| Category | Speedy Annotation | Jakarta Equivalent | Description |
|---|---|---|---|
| Numeric Bounds | @SpeedyMin(long) |
@Min |
Value must be >= min |
@SpeedyMax(long) |
@Max |
Value must be <= max |
|
| Numeric Sign | @SpeedyPositive |
@Positive |
Value > 0 |
@SpeedyPositiveOrZero |
@PositiveOrZero |
Value >= 0 |
|
@SpeedyNegative |
@Negative |
Value < 0 |
|
@SpeedyNegativeOrZero |
@NegativeOrZero |
Value <= 0 |
|
| Decimal Bounds | @SpeedyDecimalMin(value, inclusive) |
@DecimalMin |
Decimal >= / > value |
@SpeedyDecimalMax(value, inclusive) |
@DecimalMax |
Decimal <= / < value |
|
| Precision | @SpeedyDigits(integer, fraction) |
@Digits |
Max digits before / after decimal |
| String Length | @SpeedyLength(min, max) |
@Size |
Length between min..max |
| Pattern | @SpeedyRegex("regex") |
@Pattern |
Must match regex |
@SpeedyEmail |
@Email |
Must be valid email | |
| URL | @SpeedyUrl |
— | Must be valid URL |
| Date & Time | @SpeedyDateWithFormat(ISO_DATE) |
— | Value must match ISO format (DATE or DATE_TIME) |
@SpeedyFuture |
— | Date/time strictly in the future | |
@SpeedyPast |
— | Date/time strictly in the past | |
@SpeedyDateRange(min,max) |
— | Date within inclusive range | |
| Blank Check | @SpeedyNotBlank |
@NotBlank |
Not null / empty / whitespace |
Tip: You can freely mix Speedy and Jakarta annotations – duplicates are ignored, only one instance of each rule is added.
FieldRules.SpeedyEntity and validated before hitting the repository.If you need more complex logic you can register a class implementing
ISpeedyCustomValidation and annotate its methods with @SpeedyValidator.
By default custom validators run in addition to the built-in field rules:
the default checks (required fields, type/association/collection/enum) run
first, then your validator runs on top.
@Component
public class PersonValidation implements ISpeedyCustomValidation {
@SpeedyValidator(entity = "AnnotatedPerson", requests = CREATE)
public boolean checkAgeRange(AnnotatedPerson person) {
return person.getAge() >= 18 && person.getAge() <= 60;
}
}
replacesDefaultIf a validator should completely replace the built-in checks for an entity and
request type — for example when your custom logic already covers required-field
and type validation — set replacesDefault = true. The default field rules are
then skipped and only your validator runs.
@SpeedyValidator(entity = "Category", requests = CREATE, replacesDefault = true)
public boolean validateCategory(Category category) {
// This validator is now solely responsible for Category CREATE validation.
return category.getName() != null && !category.getName().isEmpty();
}
⚠️ With
replacesDefault = truethe built-in required-field / type checks no longer run for that entity + request type, so your validator must enforce everything you need. Leave itfalse(the default) to keep the safety net.
See docs/put-operation.md for more information on custom validators.
Q: Do I need to annotate with both Speedy and Jakarta?
A: No. Pick one. Both annotations resolve to the same rule – using both is
redundant but harmless.
Q: Are validation rules also applied on DELETE?
A: Only for key fields (e.g. immutable primary keys). For DELETE operations
Speedy validates that key values are present and not empty.
Q: Can I disable validation globally?
A: Not currently. Validation is a core safety feature of Speedy API.
Happy validating! 🎉