input-validation

Implement Spring Boot input validation using Jakarta ConstraintValidator and Spring Validator patterns.

Updated Jun 25, 2026
One-click install
npx skills add https://github.com/oriddd/ai-toolkit --skill input-validation-oriddd
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: input-validation
Source: https://github.com/oriddd/ai-toolkit/tree/main/copilot/public/skills/input-validation
Command: npx skills add https://github.com/oriddd/ai-toolkit --skill input-validation-oriddd

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Spring Boot services often accumulate ad-hoc if/throw guard clauses scattered across controllers and services, making validation logic inconsistent, untestable, and hard to maintain. This Skill enforces a canonical two-style validation architecture so every input rule lives in a dedicated, testable validator that surfaces RFC 7807 ProblemDetail 400 responses automatically. ## Core Features & Use Cases - Jakarta ConstraintValidator style: Author custom constraint annotations with Spring-bean-aware validators for field and parameter-level rules, including annotation attribute propagation via initialize() and dynamic violation messages. - Spring Validator style: Implement cross-field and object-level rules registered through a scoped @InitBinder in a ValidationConfig @ControllerAdvice. - Domain rule beans: Extract business logic into pure rule/ package components that validators delegate to, keeping validators thin and unit-testable. - OpenAPI redundancy check: Decision tree to avoid writing custom validators for constraints OpenAPI schema already expresses (enums, ranges, patterns, formats). - Use Case: When adding an endpoint that must verify an entity ID is editable before an update, create an @EditableEntityId annotation, a ConstraintValidator delegating to an EntityEditabilityRule bean, and a component test asserting the 400 ProblemDetail response. ## Quick Start Apply the input-validation skill to add a custom validation rule for the new endpoint in my Spring Boot controller.

Frequently Asked Questions about input-validation

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I create a custom validation annotation in Spring Boot?

Create an annotation interface with message, groups, and payload elements, declare its validator via @Constraint(validatedBy = {...}), and target PARAMETER or FIELD. Implement a ConstraintValidator as a Spring @Component, capturing annotation attributes in initialize() and returning false with a custom violation in isValid().

When should I use Jakarta ConstraintValidator vs Spring Validator?

Use Jakarta ConstraintValidator for single field or parameter rules, especially reusable ones needing injected Spring beans. Use Spring Validator (org.springframework.validation.Validator) for cross-field or object-level rules where validity depends on multiple DTO fields combined.

Why is my custom validation annotation on @PathVariable not working?

Parameter-level constraints are silently ignored without @Validated on the controller class. Add @Validated to enable Spring's method-level validation proxying, and use @Valid on @RequestBody parameters for nested DTO validation.

Should I write a custom validator for enum or range checks?

No. If OpenAPI schema can express the constraint (enum, minimum/maximum, minLength/maxLength, pattern, format), the generated code already validates it. Reserve custom validators for cross-field rules, business logic, database lookups, and conditional validation.

How do I test Spring Boot custom validators?

Unit-test rule beans as plain POJOs with mocked dependencies, drive the validator's isValid() directly with a mocked ConstraintValidatorContext, and add a @WebMvcTest component test asserting the 400 ProblemDetail response with @MockBean on registered validators.

Why does my Spring Validator run on every request?

An @InitBinder method without a value binds the validator to all requests. Scope it with the lower-camel-case DTO class name, such as @InitBinder("createScheduleRequest"), so it only runs when the request body matches that type.