Validation Error Handling

Back

Loading concept...

Validation Error Handling in Jakarta EE

🎭 The Story of the Friendly Gatekeeper

Imagine a theme park entrance. Before anyone can enter, a friendly gatekeeper checks their tickets. If something’s wrong—ticket expired, wrong date, or missing name—the gatekeeper doesn’t just say “NO!” and slam the door.

Instead, they kindly explain what’s wrong and how to fix it.

That’s exactly what Validation Error Handling does in Jakarta EE!


🎯 What You’ll Learn

  • Constraint Violation Handling — Catching and processing validation errors
  • Custom Validation Messages — Making error messages friendly and helpful

🎪 Part 1: Constraint Violation Handling

What is a Constraint Violation?

Think of constraints as rules. Like:

  • “You must be at least 5 years old to ride”
  • “Your name cannot be empty”
  • “Password must have 8 characters”

When someone breaks a rule, that’s a constraint violation.

The ConstraintViolation Object

When validation fails, Jakarta EE gives you a ConstraintViolation object. It’s like a report card that tells you:

Information What It Means
getMessage() What went wrong
getPropertyPath() Which field failed
getInvalidValue() The bad value entered
getRootBean() The object being checked

Simple Example: Catching Violations

// Create a validator
Validator validator = Validation
    .buildDefaultValidatorFactory()
    .getValidator();

// Check a user object
Set<ConstraintViolation<User>> violations =
    validator.validate(user);

// Did anything fail?
if (!violations.isEmpty()) {
    for (ConstraintViolation<User> v : violations) {
        System.out.println("Error: " + v.getMessage());
        System.out.println("Field: " + v.getPropertyPath());
    }
}

🎨 How It Works (Visual Flow)

graph TD A["User enters data"] --> B["Validator checks rules"] B --> C{Any violations?} C -->|Yes| D["Get violation details"] C -->|No| E["Data is valid!"] D --> F["Show friendly error"] F --> A

🏠 Real-World Example: Registration Form

Let’s say someone tries to register with:

  • Name: “” (empty!)
  • Age: 5 (too young!)
  • Email: “notanemail” (invalid!)

Here’s how we catch ALL these errors:

public class User {
    @NotBlank(message = "Name is required")
    private String name;

    @Min(value = 13, message = "Must be 13+")
    private int age;

    @Email(message = "Invalid email format")
    private String email;
}

// Validate and collect ALL errors
Set<ConstraintViolation<User>> errors =
    validator.validate(newUser);

List<String> messages = errors.stream()
    .map(ConstraintViolation::getMessage)
    .collect(Collectors.toList());

// messages = ["Name is required",
//             "Must be 13+",
//             "Invalid email format"]

🎨 Part 2: Custom Validation Messages

Why Custom Messages Matter

Default messages are technical and scary:

❌ “must not be null” ❌ “size must be between 1 and 50”

Friendly messages help users:

✅ “Please enter your name” ✅ “Name should be 1-50 characters”

Three Ways to Customize Messages

Way 1: Inline Messages (Simple)

Put the message right in the annotation:

@NotNull(message = "Please enter your email")
private String email;

@Size(min = 8, message = "Password needs 8+ chars")
private String password;

Way 2: Message Properties File (Organized)

Create ValidationMessages.properties:

user.name.required=Please enter your name
user.email.invalid=That email looks wrong
user.age.minimum=You must be at least {min} years old

Then use it:

@NotBlank(message = "{user.name.required}")
private String name;

@Min(value = 13, message = "{user.age.minimum}")
private int age;

Notice {min}? It gets replaced with 13 automatically!

Way 3: Dynamic Parameters

You can include the actual values in messages:

@Size(min = 2, max = 50,
      message = "Name must be {min}-{max} characters")
private String name;
// Output: "Name must be 2-50 characters"

🎭 The Complete Picture

graph TD A["Define Constraints"] --> B["Add Custom Messages"] B --> C["Validate Object"] C --> D["Get Violations"] D --> E["Extract Messages"] E --> F["Show to User"] F --> G["User Fixes Errors"] G --> C

đź’ˇ Pro Tips

Tip 1: Group Related Errors

Map<String, String> errorMap = violations.stream()
    .collect(Collectors.toMap(
        v -> v.getPropertyPath().toString(),
        v -> v.getMessage()
    ));
// {"name": "Required", "age": "Must be 13+"}

Tip 2: Handle in REST Endpoints

@POST
public Response create(@Valid User user) {
    // Jakarta EE auto-validates!
    // If invalid, throws ConstraintViolationException
    return Response.ok(user).build();
}

@ExceptionHandler(ConstraintViolationException.class)
public Response handleError(ConstraintViolationException e) {
    List<String> errors = e.getConstraintViolations()
        .stream()
        .map(v -> v.getMessage())
        .collect(Collectors.toList());
    return Response.status(400).entity(errors).build();
}

Tip 3: Internationalization (i18n)

Create multiple message files:

ValidationMessages.properties (default)
ValidationMessages_es.properties (Spanish)
ValidationMessages_fr.properties (French)

Jakarta EE picks the right one based on user’s locale!


🎯 Quick Summary

Concept What It Does
ConstraintViolation Holds error details
getMessage() Gets the error message
getPropertyPath() Gets the field name
getInvalidValue() Gets what user entered
Custom Messages Makes errors friendly
{parameters} Adds dynamic values
Properties Files Organizes messages

🚀 You Did It!

You now understand how to:

  1. âś… Catch validation errors using ConstraintViolation
  2. âś… Extract useful information (message, field, value)
  3. âś… Create friendly messages inline or in files
  4. âś… Use dynamic parameters like {min} and {max}

Think of yourself as that friendly gatekeeper now. You don’t just block bad data—you help users fix it with clear, kind messages!


Remember: Good error messages turn frustrated users into happy users! 🎉

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.