# Org / Springframework / Samples / Petclinic / Owner/other

## Overview

This subpackage contains the core domain model and supporting infrastructure for the Petclinic owner flow. It appears to be responsible for representing owners, pets, pet types, and visits, plus the formatting and validation logic that makes those objects work cleanly with Spring MVC form binding and persistence.

The classes here form the backbone of the owner-facing part of the application: owners own pets, pets have a type and a set of visits, and the MVC layer needs a formatter and validator to turn form values into domain objects and back again.

## Key Classes and Interfaces

### `Owner`

Source: [Owner](src/main/java/org/springframework/samples/petclinic/owner/Owner.java:47)

`Owner` is the aggregate root for the owner domain model. It extends `Person`, is mapped to the `owners` table, and stores the owner’s address, city, telephone, and pets.

Important responsibilities:

- Stores owner contact data with Bean Validation constraints on `address`, `city`, and `telephone`.
- Owns a `List<Pet>` that is persisted eagerly, cascaded, and ordered by pet name.
- Provides lookup helpers for finding pets by name or id.
- Provides a convenience method for adding a `Visit` to one of the owner’s pets.

Key methods:

- `getAddress()` / `setAddress(String address)` — access the owner’s street address.
- `getCity()` / `setCity(String city)` — access the owner’s city.
- `getTelephone()` / `setTelephone(String telephone)` — access the telephone number. The field is constrained with `@Pattern(regexp = "\\d{10}", message = "{telephone.invalid}")`, so the phone number must be exactly 10 digits.
- `getPets()` — returns the live `List<Pet>` managed by the entity.
- `addPet(Pet pet)` — adds the pet only if `pet.isNew()` is true. This prevents adding an already-persisted pet twice through the aggregate helper.
- `getPet(String name)` — convenience lookup by name, delegating to `getPet(name, false)`.
- `getPet(Integer id)` — scans the current pets and returns the matching persisted pet by identifier, or `null` if none match.
- `getPet(String name, boolean ignoreNew)` — case-insensitive lookup by name with optional filtering of unsaved pets.
- `toString()` — builds a structured string including id, new state, name fields, and address data.
- `addVisit(Integer petId, Visit visit)` — validates both arguments, finds the matching pet, and delegates the visit addition to that pet. It fails fast with `Assert` if the pet id, visit, or pet lookup is invalid.

Design notes:

- The entity uses eager fetching for pets, which makes owner details convenient for UI/controller use but should be kept in mind if the model grows.
- The helper methods treat `null` as “not found,” so callers need to handle absence explicitly.
- `addPet` only accepts new pets; updates to existing pets should happen through the pet itself rather than re-adding it.

### `Pet`

Source: [Pet](src/main/java/org/springframework/samples/petclinic/owner/Pet.java:44)

`Pet` is the child entity in the owner aggregate. It extends `NamedEntity`, is mapped to the `pets` table, and represents an individual pet with a birth date, type, and visit history.

Important responsibilities:

- Carries the pet’s birth date and type.
- Owns a set of visits, persisted eagerly and ordered by visit date.
- Acts as the target for visit additions from the owner aggregate.

Key methods:

- `setBirthDate(LocalDate birthDate)` / `getBirthDate()` — mutate and read the pet’s birth date. The field uses `@DateTimeFormat(pattern = "yyyy-MM-dd")`, which aligns form binding with the expected date format.
- `getType()` / `setType(PetType type)` — access the selected pet type.
- `getVisits()` — returns the live `Collection<Visit>` used by JPA and by the domain helper methods.
- `addVisit(Visit visit)` — appends a visit to the collection.

Design notes:

- The visit collection is a `LinkedHashSet`, so insertion order is preserved while still preventing duplicate visit objects.
- The mapping uses `cascade = CascadeType.ALL` and `fetch = FetchType.EAGER`, which means visits are saved and loaded together with the pet.

### `PetType`

Source: [PetType](src/main/java/org/springframework/samples/petclinic/owner/PetType.java:26)

`PetType` is a lightweight reference entity representing the classification of a pet, such as cat, dog, or hamster. It extends `NamedEntity` and is mapped to the `types` table.

This class has no custom methods or fields beyond those inherited from `NamedEntity`. Its role is to provide a stable, persisted lookup value for the pet form and the formatter.

### `PetTypeFormatter`

Source: [PetTypeFormatter](src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java:36)

`PetTypeFormatter` connects Spring MVC data binding to the `PetType` entity. It is a Spring `Formatter<PetType>` component, so MVC can convert between the string values used in HTML forms and the domain object used in controllers and entities.

Important responsibilities:

- Print a `PetType` as its display name.
- Parse a posted string back into a `PetType` by looking it up in the repository.

Key methods:

- Constructor `PetTypeFormatter(PetTypeRepository types)` — receives the repository used for lookup.
- `print(PetType petType, Locale locale)` — returns the type name, or `"<null>"` if the name is absent. The locale parameter is present because the `Formatter` contract requires it, but this implementation does not use it.
- `parse(String text, Locale locale)` — iterates over `types.findPetTypes()` and returns the matching `PetType` whose name equals the submitted text. If no match is found, it throws `ParseException("type not found: " + text, 0)`.

Design notes:

- Parsing is name-based, not id-based.
- The formatter depends on the repository returning the universe of available pet types.
- This class is what lets MVC bind form submissions to the `Pet.type` field without manual conversion code in controllers.

### `PetValidator`

Source: [PetValidator](src/main/java/org/springframework/samples/petclinic/owner/PetValidator.java:32)

`PetValidator` is a Spring `Validator` for pet form submissions. It performs imperative validation rules that are easier to express in Java than with Bean Validation annotations.

Important responsibilities:

- Requires a non-empty pet name.
- Requires a pet type when creating a new pet.
- Requires a birth date.

Key methods:

- `validate(Object obj, Errors errors)` — casts the input to `Pet` and applies three checks:
  - `name` must contain text, or it rejects the field with code `required`.
  - if the pet is new and has no type, it rejects `type` with code `required`.
  - if `birthDate` is `null`, it rejects `birthDate` with code `required`.
- `supports(Class<?> clazz)` — returns `true` when the class is assignable to `Pet`, so Spring knows when the validator applies.

Design notes:

- Validation is intentionally simple and field-focused.
- The validator uses the same `required` message code for all three failures, so message resolution is likely centralized in message bundles.

### `Visit`

Source: [Visit](src/main/java/org/springframework/samples/petclinic/owner/Visit.java:34)

`Visit` represents a single veterinary visit. It extends `BaseEntity`, is mapped to the `visits` table, and stores a visit date plus a textual description.

Important responsibilities:

- Captures the date of the visit.
- Captures a required description.
- Defaults the date to the current day when a visit instance is created.

Key methods:

- Constructor `Visit()` — initializes `date` to `LocalDate.now()`, which makes new visits immediately usable in forms and controllers without requiring the caller to supply a date.
- `getDate()` / `setDate(LocalDate date)` — access and mutate the visit date.
- `getDescription()` / `setDescription(String description)` — access and mutate the visit description.

Design notes:

- `description` is annotated with `@NotBlank`, so blank visit descriptions are invalid.
- The `visit_date` column name is explicit, while the form binding format is fixed at `yyyy-MM-dd`.

## How It Works

The main flow in this subpackage is the owner-to-pet-to-visit lifecycle:

1. An `Owner` is loaded or created.
2. Pets are attached to the owner through `Owner.addPet(Pet pet)`.
3. The selected pet type is bound through `PetTypeFormatter`, which translates between UI strings and `PetType` entities.
4. Pet data is checked by `PetValidator` before persistence.
5. When a visit is created, `Owner.addVisit(Integer petId, Visit visit)` locates the pet and delegates to `Pet.addVisit(Visit visit)`.
6. JPA cascades persist the aggregate state across owner, pets, and visits according to the mappings.

A typical request in the owner area appears to move through the code like this:

- The controller binds form fields to an `Owner` or `Pet` instance.
- The formatter resolves the pet type field into a managed entity.
- The validator rejects missing or invalid fields before save.
- The aggregate helper methods add child objects while preserving the object graph invariants.

## Data Model

The entities in this subpackage form a small aggregate:

- `Owner` extends `Person` and is stored in `owners`.
- `Owner` contains many `Pet` objects through `owner_id`.
- `Pet` extends `NamedEntity` and is stored in `pets`.
- `Pet` references one `PetType` through `type_id`.
- `Pet` contains many `Visit` objects through `pet_id`.
- `Visit` extends `BaseEntity` and is stored in `visits`.
- `PetType` extends `NamedEntity` and is stored in `types`.

Mermaid relationship diagram:

```mermaid
flowchart TD
OwnerEntity["Owner"] --> PersonBase["Person"]
OwnerEntity --> PetList["pets: List<Pet>"]
PetEntity["Pet"] --> NamedBase["NamedEntity"]
PetEntity --> PetTypeEntity["PetType"]
PetEntity --> VisitSet["visits: Set<Visit>"]
PetTypeEntity --> NamedBase
VisitEntity["Visit"] --> BaseEntity["BaseEntity"]
Formatter["PetTypeFormatter"] --> Repo["PetTypeRepository"]
Validator["PetValidator"] --> PetEntity
```

## Dependencies and Integration

This module integrates with a small set of Spring and Jakarta APIs:

- JPA annotations define persistence mapping and relationships.
- Bean Validation annotations enforce basic field requirements.
- Spring MVC formatting via `Formatter<PetType>` makes type binding work in forms.
- Spring validation via `Validator` adds custom form checks.
- Spring utility classes such as `Assert` and `StringUtils` support defensive checks.
- `PetTypeFormatter` depends on `PetTypeRepository` to resolve available types.

The module also depends on the shared Petclinic base types:

- `Person`
- `NamedEntity`
- `BaseEntity`

## Notes for Developers

- `Owner.addPet(Pet pet)` only adds new pets. If you are updating an existing pet, update it in place rather than trying to re-add it.
- `Owner.getPet(String name, boolean ignoreNew)` and `Owner.getPet(Integer id)` both return `null` when there is no match. Callers should handle absence explicitly.
- `Owner.addVisit(Integer petId, Visit visit)` validates its inputs with `Assert` and fails fast if the pet cannot be found.
- `PetValidator` only applies to `Pet` instances, so if you introduce a subclass or alternate form object, the validator will not automatically cover it.
- `PetTypeFormatter` currently uses type names for conversion. If pet type names change, form binding behavior changes with them.
- The eager collection mappings make the aggregate convenient for controller use, but they also mean loading an owner can bring back all pets and visits immediately.
- The test classes in this package show the intended behavior for validation, formatter parsing, and controller interactions:
  - [PetValidatorTests](src/test/java/org/springframework/samples/petclinic/owner/PetValidatorTests.java:39)
  - [OwnerControllerTests](src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java:58)
  - [PetControllerTests](src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java:48)
  - [PetTypeFormatterTests](src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java:41)
  - [VisitControllerTests](src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java:43)

## Related Tests

The following test classes exercise the behavior documented above and are good starting points when changing this module:

- [PetValidatorTests](src/test/java/org/springframework/samples/petclinic/owner/PetValidatorTests.java:39)
- [OwnerControllerTests](src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java:58)
- [PetControllerTests](src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java:48)
- [PetTypeFormatterTests](src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java:41)
- [VisitControllerTests](src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java:43)
