Skip to content
Ameen Abozaid
JNR-014

Validation

  • 6 Lessons
  • 2 h practice (estimate)
On this page 8 topics

Overview

Topics

  • Jakarta Bean Validation
  • custom validators
  • input sanitization

Learn first

2 h of practice (estimate)

Learning outcomes

  1. Validate request DTOs with Jakarta Bean Validation annotations and @Valid.
  2. Write a custom constraint annotation and validator.
  3. Use validation groups or separate DTOs for create vs update.
  4. Distinguish input validation (at the edge) from business-rule validation (in the domain).

Lessons

  1. 01Validating at the edge
  2. 02Built-in constraints
  3. 03Custom constraints
  4. 04Input validation vs business rules
  5. 05Sanitization and why validation is not escaping
  6. 06Demo: writing a custom @ValidSku constraint

Lab and exercises

Lab

JNR-014-LAB1 · Validated product creation

Outcomes: 1–4 · Time: ~2 h

  1. Add POST /products with CreateProductRequest (name, sku, price, optional description).
  2. Add constraints: name not blank and sized, price positive, description size-limited.
  3. Write @ValidSku with its validator and apply it.
  4. Use a separate UpdateProductRequest for update rules.
  5. Keep "SKU must be unique" as a service check, not an annotation.

Acceptance: invalid requests never reach the service (shown by a service call count or log); business rule lives in the service.

Exercises (assessment: 4 exercises)

IDOutcomeTask
JNR-014-EX011Write a CreateCustomerRequest with name, email, age (18+) constraints and @Valid on the controller.
JNR-014-EX022Write @ValidCountryCode (two uppercase letters) with a validator.
JNR-014-EX033Design CreateProductRequest and UpdateProductRequest so create requires all fields and update allows a partial set; explain the choice versus groups.
JNR-014-EX044Classify each rule as input or business: quantity > 0, stock available, email format, coupon not expired.
Show solutions
  • EX01 record CreateCustomerRequest(@NotBlank String name, @Email @NotBlank String email, @Min(18) int age){} and create(@Valid @RequestBody ...).
  • EX02 Annotation with @Constraint(validatedBy=...); validator: value == null || value.matches("[A-Z]{2}").
  • EX03 Separate DTOs are clearer and easier to read than groups; groups work when you must share one type (@NotNull(groups=Create.class)).
  • EX04 Input: quantity > 0, email format. Business: stock available, coupon not expired.
  • Outcome 1 is also covered by the lab and quiz; all four outcomes are covered by EX01-EX04.

Quiz

Outcomes: O1 constraints and @Valid · O2 custom constraints · O3 create vs update · O4 input vs business rules.

A self-check for you: nothing is graded, saved or sent anywhere. Choose an answer, then check it. You can try again as often as you like.

  1. 1Which annotation on a controller parameter triggers validation?O1
  2. 2Best constraint for a required, non-empty-looking name:O1
  3. 3Frontend validation is:O1
  4. 4@Positive on a price rejects:O1
  5. 5A custom constraint needs:O2
  6. 6The validator interface is:O2
  7. 7A clean way to have different rules for create and update:O3
  8. 8"SKU must not already exist" is:O4
  9. 9"Quantity must be greater than zero" is:O4
  10. 10Passing validation means output is safe for HTML:O4

Practical part

Four exercises JNR-014-EX01 to EX04 plus the lab. Pass: quiz at least 8/10, all four exercises correct, lab acceptance met.

Common mistakes

Validating only in the frontend; business rules as annotations.

Assessment

4 exercises.

Career relevance

Input-related vulnerabilities (JNR-041).

Type to search levels, phases, modules and lessons.