---

# (DD41) Business Logic — PetController.findPet() [13 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `org.springframework.samples.petclinic.owner.PetController` |
| Layer | Controller |
| Module | `owner` (Package: `org.springframework.samples.petclinic.owner`) |

## 1. Role

### PetController.findPet()

This method serves as the model-preparation entry point for the pet maintenance flow in the owner management area. Its business purpose is to supply the `pet` model attribute before the create/update form is rendered, ensuring the UI receives either a fresh pet instance for registration or an existing pet loaded from the selected owner record for editing. The method supports two service categories: new-pet initialization when no `petId` is supplied, and owner-scoped pet retrieval when `petId` is present. It implements a simple routing/delegation pattern by branching on whether the request is creating a new pet or editing an existing one, then delegating to the owner repository and domain model as needed. Within the larger system, it is a controller-level composition method that shields the view layer from the persistence lookup logic and from conditional object construction.

When `petId` is absent, the method creates a new `Pet` object so the form can bind to an empty domain instance. When `petId` is provided, it validates the owner context by loading the owner identified by `ownerId`; if the owner does not exist, it fails fast with an `IllegalArgumentException`. After the owner is resolved, it delegates to `owner.getPet(petId)` to return the specific pet that belongs to that owner. This means the method is both a form model factory and an ownership guard, preventing the pet form from editing a pet outside the requested owner scope.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["findPet(params)"])
    DECISION{"petId == null?"}
    NEWPET["Create new Pet()"]
    FINDOWNER["owners.findById(ownerId)"]
    THROW["Throw IllegalArgumentException if owner missing"]
    GETPET["owner.getPet(petId)"]
    ENDNODE(["Return Pet"])

    START --> DECISION
    DECISION -->|Yes| NEWPET
    DECISION -->|No| FINDOWNER
    FINDOWNER --> THROW
    THROW --> GETPET
    NEWPET --> ENDNODE
    GETPET --> ENDNODE
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `ownerId` | `@PathVariable("ownerId") int` | The unique owner identifier taken from the URL path. It identifies which customer account owns the pet being created or edited and is required when a stored pet must be retrieved. |
| 2 | `petId` | `@PathVariable(name = "petId", required = false) Integer` | The optional pet identifier from the URL path. When absent, the method prepares a new pet registration instance; when present, it triggers lookup of the existing pet under the specified owner. |

Instance state and external state read by the method:
- `this.owners` repository to load the owner record by ID
- `Owner.getPet(petId)` on the resolved owner aggregate

## 4. CRUD Operations / Called Services

### Pre-computed evidence from code analysis graph:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `OwnerRepository.findById` | OwnerRepository | Owner | Calls `findById` in `OwnerRepository` |

Analyze all method calls within this method and classify each as a CRUD operation.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| C | `new Pet()` | N/A | Pet | Creates a new in-memory pet model for the create flow when no pet identifier is supplied. |
| R | `OwnerRepository.findById` | OwnerRepository | Owner | Loads the owner aggregate by `ownerId` so that the requested pet is resolved within the correct ownership context. |
| R | `Owner.getPet` | N/A | Pet | Retrieves the matching pet from the owner's pet collection using `petId`. |

## 5. Dependency Trace

Trace who calls this method and what this method ultimately calls.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Controller: `PetController` model binding | `PetController.findPet` | `new Pet() [C] Pet` or `OwnerRepository.findById [R] Owner` or `Owner.getPet [R] Pet` |

Notes:
- No Java call sites were found that invoke `findPet(` directly.
- The method is used by Spring MVC as a `@ModelAttribute` provider, so its primary consumer is the web data-binding pipeline rather than another Java class.

## 6. Per-Branch Detail Blocks

**Block 1** — IF `(petId == null)` (L77)

> Branch for the pet creation path. This prepares an empty domain object for the form when the request does not target an existing pet.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return new Pet();` |

**Block 2** — ELSE `(petId != null)` (L81-L85)

> Branch for the pet update path. This loads the owner first, then resolves the requested pet from that owner.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `this.owners.findById(ownerId);` |
| 2 | SET | `Optional<Owner> optionalOwner = this.owners.findById(ownerId);` |
| 3 | CALL | `optionalOwner.orElseThrow(...);` |
| 4 | SET | `Owner owner = optionalOwner.orElseThrow(() -> new IllegalArgumentException("Owner not found with id: " + ownerId + ". Please ensure the ID is correct "));` |
| 5 | CALL | `owner.getPet(petId);` |
| 6 | RETURN | `return owner.getPet(petId);` |

**Block 2.1** — CALL target of `orElseThrow` (L82-L84)

> Failure path when the owner record does not exist. The method raises a business exception to stop form binding and signal the missing owner context.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `new IllegalArgumentException("Owner not found with id: " + ownerId + ". Please ensure the ID is correct ")` |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|-------------------|
| `ownerId` | Field | Owner identifier used to scope pet access to the correct customer account. |
| `petId` | Field | Pet identifier used to load an existing pet record for editing. |
| `Owner` | Domain entity | Customer aggregate that owns one or more pets. |
| `Pet` | Domain entity | Animal record managed in the clinic system. |
| `@ModelAttribute` | Spring MVC annotation | Indicates that the returned object is added to the model before the controller handler executes. |
| `@PathVariable` | Spring MVC annotation | Binds a value from the URL path into a method parameter. |
| `Optional` | Java type | Container used to represent the possible absence of an owner record. |
| `IllegalArgumentException` | Exception type | Signals that the requested owner does not exist and the request cannot continue. |
| CRUD | Acronym | Create, Read, Update, Delete — the standard data operation categories. |
| Controller | Layer | Web layer component that handles request routing and prepares data for views. |
| Model attribute | MVC concept | Data object exposed to the form/view layer for rendering and binding. |
| Ownership scope | Business term | Rule that a pet must be resolved only within the context of its owning customer. |
| Create flow | Business term | The path used when registering a new pet and no existing pet identifier is present. |
| Update flow | Business term | The path used when editing an existing pet already stored for an owner. |
