# Error Handling and Resilience

## Overview

This codebase handles error conditions primarily through validation-driven recovery rather than exception-heavy control flow. In the owner/pet flow, invalid input is detected early, attached to the model as field errors, and the user is returned to the same form with feedback instead of being redirected into a failure path. The tests show three key signals that shape this behavior: form-level error wrappers such as `ProcessCreationFormHasErrors` and `ProcessUpdateFormHasErrors`, and validator-level checks such as `ValidateHasErrors`.

This approach keeps the application resilient in the face of malformed requests, missing required values, and type conversion problems. Rather than treating these cases as fatal, the code routes them back into the same UI and preserves enough context for the user to correct the input.

## Implementation Patterns

### 1. Validation before persistence

The pet creation and update flows validate submitted data before allowing the request to succeed. The controller tests in [PetControllerTests](../../src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java) show the intended contract:

- blank names are rejected with a `required` error
- missing pet types are rejected with a `required` error
- duplicate pet names are rejected with a `duplicate` error
- invalid birth dates are rejected with binding/type-mismatch errors

When validation fails, the request stays on `pets/createOrUpdatePetForm` instead of redirecting away.

### 2. Model-backed error recovery

The tests assert that the `owner` model attribute remains error-free while the `pet` model attribute collects field errors. That separation matters: the owner context is preserved, while the pet form is re-rendered with the specific problems highlighted. This is a common resilience pattern in MVC applications because it avoids losing user input and avoids forcing the user to start over.

### 3. Centralized validation rules

[PetValidatorTests](../../src/test/java/org/springframework/samples/petclinic/owner/PetValidatorTests.java) exercise the validator directly. The validator is responsible for rejecting invalid pet state such as:

- empty names
- missing types
- missing birth dates

This keeps the validation rules reusable and consistent across controller entry points. The controller is free to focus on orchestration, while the validator owns the domain checks.

### 4. Error codes as stable contracts

The controller tests assert specific field error codes such as `required`, `duplicate`, `typeMismatch.birthDate`, and `typeMismatch`. That means the application does not just detect errors; it classifies them in a predictable way. These codes are important for view rendering and for keeping behavior stable over time.

## Key Classes

- [ProcessCreationFormHasErrors](../../src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java)
  - Nested controller test group covering invalid pet creation requests.
  - Documents the resilience behavior for blank names, duplicate names, missing types, and invalid birth dates.

- [ProcessUpdateFormHasErrors](../../src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java)
  - Nested controller test group covering invalid pet update requests.
  - Shows that the update path uses the same recovery model as creation: stay on the form and report field-level problems.

- [ValidateHasErrors](../../src/test/java/org/springframework/samples/petclinic/owner/PetValidatorTests.java)
  - Nested validator test group covering rule-level failures.
  - Demonstrates that validation failures are localized to the relevant fields instead of failing the whole operation.

- [PetControllerTests](../../src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java)
  - The main specification for request handling and error recovery in the pet lifecycle.
  - Shows how controller behavior is expected to respond to invalid input.

- [PetValidatorTests](../../src/test/java/org/springframework/samples/petclinic/owner/PetValidatorTests.java)
  - The main specification for domain validation rules.
  - Shows which pet states are considered invalid before a request can proceed.

## How It Fits Together

```mermaid
flowchart TD
    Controller["PetController"] --> Validator["PetValidator"]
    Validator --> Errors["BindingResult / Errors"]
    Errors --> Form["createOrUpdatePetForm"]
    Form --> User["User corrects input"]
    User --> Controller
    Validator --> Success["Valid pet state"]
    Success --> Redirect["Redirect to owner page"]
```

The flow is straightforward:

1. The controller accepts submitted pet data.
2. The validator checks required fields and domain rules.
3. If validation fails, the form is re-rendered with field errors.
4. If validation succeeds, the request completes with a redirect.

This design prevents invalid input from escaping into the rest of the system and keeps user-facing recovery localized to the form that needs correction.

## Notes for Developers

- Prefer validation and field errors for recoverable problems such as missing input, duplicate values, and type conversion issues.
- Keep controller tests focused on user-visible recovery behavior: same form, preserved model state, and explicit error codes.
- Keep validator tests focused on domain rules, so the validation contract stays reusable and easy to reason about.
- When adding new form fields, update both the validator and the controller tests so the recovery path stays covered.
- Use stable error codes when possible. The view layer and tests can then depend on them without coupling to presentation text.
- Treat redirection as a success signal and form re-rendering as the normal recovery path for invalid submissions.
