# Error Handling and Resilience

## Overview

Error handling in this codebase is centered on defensive validation and form recovery rather than deep exception hierarchies. The main pattern is simple: user input is bound into domain objects, validated, and then either accepted or returned to the same form with errors attached. This keeps failures local, visible, and recoverable for the user.

The strongest examples live in the owner/pet workflow, where controller tests and validator tests show how invalid input is detected, how error codes are surfaced, and how the UI is re-rendered without losing the user’s data. See [PetControllerTests](../../src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java) and [PetValidatorTests](../../src/test/java/org/springframework/samples/petclinic/owner/PetValidatorTests.java).

## Implementation Patterns

### Validate before persisting

The `PetValidator` path demonstrates the core resilience strategy: validate the object before any state-changing action proceeds. The tests in [PetValidatorTests](../../src/test/java/org/springframework/samples/petclinic/owner/PetValidatorTests.java) show that the validator rejects missing names, missing pet types, and missing birth dates by attaching field-specific errors to the `Errors` object.

### Keep the form in a recoverable state

Controller tests in [PetControllerTests](../../src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java) show the recovery behavior when validation fails:

- blank pet names produce a `required` error
- duplicate names produce a `duplicate` error
- missing pet types produce a `required` error
- malformed birth dates produce type-mismatch errors

Instead of failing the request, the controller returns `pets/createOrUpdatePetForm` so the user can correct the input. This is a classic resilience pattern: preserve the request context, annotate the failure, and let the workflow continue.

### Separate binding errors from business-rule errors

The tests also distinguish between:

- binding failures, such as malformed dates
- business validation failures, such as duplicate pet names

That distinction matters because it lets the UI and validation layer communicate more precisely. A malformed date is an input-format issue, while a duplicate name is a domain-rule violation.

### Use HTTP redirects only after successful processing

When the submission is valid, the controller returns a redirect to the owner page. That gives a clean success path and avoids duplicate submissions.

## Key Classes

### [ProcessCreationFormHasErrors](../../src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java)

A test grouping that documents how creation requests recover from invalid input. It is especially useful as executable documentation for the expected failure modes during pet creation.

### [ProcessUpdateFormHasErrors](../../src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java)

A test grouping that documents the same recovery behavior for updates. It shows that the edit flow follows the same resilience pattern as creation: detect the error, preserve the form, and return the user to the editor.

### [ValidateHasErrors](../../src/test/java/org/springframework/samples/petclinic/owner/PetValidatorTests.java)

A test grouping that focuses on validator-level failures. It verifies that the validator attaches field-level errors for invalid name, type, and birth date values.

## How It Fits Together

```mermaid
flowchart TD
A["User submits pet form"] --> B["Controller binds request data"]
B --> C["Validator checks domain rules"]
C --> D["No errors"]
C --> E["Errors collected"]
D --> F["Persist and redirect"]
E --> G["Return createOrUpdatePetForm"]
G --> H["Show field errors to user"]
```

The flow is intentionally linear: bind, validate, either persist or recover. The validator supplies structured failures, and the controller turns those failures into a user-facing form response.

## Notes for Developers

- Prefer validation-driven recovery over throwing exceptions for expected user input problems.
- Keep error codes stable; the tests assert specific codes such as `required`, `duplicate`, and `typeMismatch`.
- Distinguish clearly between field binding issues and business validation rules.
- Reuse the same form view for both create and update failures so users do not lose context.
- When adding new rules, update both validator tests and controller tests so the recovery path stays documented.
- Treat these tests as a contract: they define the expected resilience behavior of the owner/pet workflow.
