# Org / Springframework / Samples / Petclinic / Model

## Overview

The `org.springframework.samples.petclinic.model` package defines the small set of shared domain base classes used across Petclinic. It provides reusable pieces for identity, naming, and person-name fields so concrete domain objects can inherit consistent persistence and validation behavior.

This package also contains a focused validation test that confirms Bean Validation is wired correctly for the model layer. In practice, that test acts as a safeguard for the package’s `@NotBlank` constraints and helps catch regressions when validation dependencies change.

## Key Classes and Interfaces

### [BaseEntity](src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java:32)

`BaseEntity` is the foundational superclass for model objects that need a database identifier. It is marked with `@MappedSuperclass`, so JPA treats its mapping metadata as part of subclasses rather than as a standalone entity table.

**Role in the model layer**

- Centralizes the `id` property that most persisted domain objects need.
- Provides a standard `isNew()` check used to determine whether the object has been persisted yet.
- Implements `Serializable`, which is a common requirement for JPA-managed domain objects.

**Key methods**

- `getId()` returns the current `Integer` identifier.
- `setId(Integer id)` assigns the identifier. This is typically managed by persistence, but the setter is present for framework use.
- `isNew()` returns `true` when `id` is `null`, which indicates the object has not yet been assigned a persistent identity.

**Why it exists**

The class keeps identity behavior consistent across the domain model. Instead of each model class reimplementing ID handling, subclasses inherit the same persistence conventions.

### [NamedEntity](src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java:30)

`NamedEntity` extends `BaseEntity` and adds a single `name` field. It is also a `@MappedSuperclass`, making it a reusable base for domain objects that are identified by both an `id` and a human-readable name.

**Role in the model layer**

- Represents the common pattern of “persistent object with an ID and a name.”
- Adds Bean Validation via `@NotBlank` so empty names are rejected before persistence.
- Supplies a `toString()` implementation that is useful when logging or displaying simple references.

**Key methods**

- `getName()` returns the current name value.
- `setName(String name)` updates the name.
- `toString()` returns the name when it is present, otherwise it returns `"<null>"`.

**Important behavior**

`toString()` does not expose the entity ID or other fields. That makes it safe and concise for UI/debug output, but it also means subclasses relying on richer string representations will need to override it.

### [Person](src/main/java/org/springframework/samples/petclinic/model/Person.java:27)

`Person` is the shared base class for person-like model objects. It extends `BaseEntity` and adds first and last name fields, both validated with `@NotBlank`.

**Role in the model layer**

- Encapsulates the shared name structure used by person-oriented domain objects.
- Keeps validation rules close to the data so blank names fail early.
- Serves as a simple foundation for richer person entities in the application.

**Key methods**

- `getFirstName()` / `setFirstName(String firstName)` access and mutate the first-name field.
- `getLastName()` / `setLastName(String lastName)` access and mutate the last-name field.

**Why it exists**

The class avoids duplicating first/last name fields across multiple domain types. Subclasses inherit both persistence identity and name validation behavior, which keeps the model consistent.

### [ValidatorTests](src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java:35)

`ValidatorTests` is a small integration-style test for Bean Validation on the model package. It creates a `Validator` through Spring’s `LocalValidatorFactoryBean` and validates a `Person` instance with an empty first name.

**Role in the test suite**

- Verifies that validation infrastructure is active.
- Confirms that `@NotBlank` on `Person.firstName` produces the expected violation.
- Acts as a regression test for validation provider upgrades.

**Key methods**

- `createValidator()` creates and initializes a Spring `LocalValidatorFactoryBean`, then returns it as a Jakarta `Validator`.
- `shouldNotValidateWhenFirstNameEmpty()` constructs a `Person`, sets `firstName` to an empty string and `lastName` to `"smith"`, validates it, and asserts that exactly one violation is raised on `firstName` with the message `"must not be blank"`.

## Data Model

The package is intentionally small and inheritance-based:

- `BaseEntity` provides the shared `id` field.
- `NamedEntity` builds on `BaseEntity` with a validated `name`.
- `Person` builds on `BaseEntity` with validated `firstName` and `lastName`.

Although `NamedEntity` and `Person` do not inherit from each other, they follow the same base pattern: a shared JPA superclass plus Bean Validation annotations on required fields.

```mermaid
flowchart TD
  BaseEntity["BaseEntity"] --> NamedEntity["NamedEntity"]
  BaseEntity --> Person["Person"]
  NamedEntity --> NamedName["name property"]
  Person --> PersonNames["firstName and lastName properties"]
  ValidatorTests["ValidatorTests"] --> Person
  ValidatorTests --> Validator["Jakarta Validator"]
```

## How It Works

### Object identity and persistence

1. A new model instance starts with `id == null`.
2. `BaseEntity.isNew()` returns `true` until persistence assigns an identifier.
3. Once the entity has been stored, `id` is populated and `isNew()` becomes `false`.

This pattern is a simple but important convention for distinguishing transient objects from persisted ones.

### Validation flow for person data

1. A `Person` instance is created.
2. Application or test code assigns values to `firstName` and `lastName`.
3. Bean Validation inspects the `@NotBlank` constraints on those fields.
4. If a field is blank, a violation is raised with the default message `must not be blank`.

The test in [ValidatorTests.shouldNotValidateWhenFirstNameEmpty()](src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java:43) demonstrates this flow directly.

### Named entity display behavior

1. A `NamedEntity` subclass sets a `name`.
2. `toString()` returns that name for concise display.
3. If `name` has not been set, the method returns `"<null>"` instead of throwing an error.

That makes the class predictable in logs and debugging output.

## Dependencies and Integration

This package is lightweight and depends mainly on JPA and Bean Validation annotations:

- `jakarta.persistence.MappedSuperclass`, `@Id`, `@GeneratedValue`, `@Column`
- `jakarta.validation.constraints.NotBlank`
- Spring’s `LocalValidatorFactoryBean` in the test
- Jakarta `Validator` and `ConstraintViolation` in the test

The package-info comment describes these classes as utilities used by the domain, which matches their role as shared building blocks rather than feature-specific business objects.

## Notes for Developers

- `BaseEntity` uses `GenerationType.IDENTITY`, so identifier generation is database-driven.
- `isNew()` is purely null-based. If you manually assign IDs in tests or fixtures, `isNew()` will immediately report the object as existing.
- `NamedEntity.toString()` only returns the name. If a subclass needs richer diagnostics, override it explicitly.
- The validation messages in the test rely on the default Bean Validation message for `@NotBlank`. If the validation provider or locale setup changes, the expectation may need to be revisited.
- Both `NamedEntity` and `Person` are `@MappedSuperclass` types, so they are designed for inheritance rather than direct table mapping.
