# (DD26) Business Logic — OwnerController.findOwner() [7 LOC]

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

## 1. Role

### OwnerController.findOwner()

This method acts as a model-preparation entry point for owner-related web flows. It resolves the `owner` model attribute before request handling continues, ensuring that downstream create and edit screens always receive an `Owner` instance even when the route does not carry an identifier. When an `ownerId` is present, it performs a repository-backed lookup and either returns the persisted owner record or fails fast if the record cannot be found. In business terms, the method distinguishes between two lifecycle states: a new owner being created and an existing owner being edited or inspected.

The method implements a simple routing and delegation pattern: it branches on the presence of the path variable, constructs a new aggregate root for blank create flows, and delegates existing-owner retrieval to `OwnerRepository`. It is not a standalone business service; rather, it is a shared controller helper that supports multiple owner screens by centralizing identity resolution. The failure branch is intentionally strict so that invalid owner references do not silently propagate into the UI or later form submission logic.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["findOwner(ownerId)"])
    DECISION{"ownerId == null"}
    NEW_OWNER["Create new Owner()"]
    FIND_BY_ID["Call this.owners.findById(ownerId)"]
    OR_ELSE["Call orElseThrow with IllegalArgumentException supplier"]
    THROW["Throw IllegalArgumentException - Owner not found with id"]
    RETURN_OWNER["Return Owner"]
    START --> DECISION
    DECISION -->|Yes| NEW_OWNER
    DECISION -->|No| FIND_BY_ID
    FIND_BY_ID --> OR_ELSE
    OR_ELSE --> RETURN_OWNER
    OR_ELSE --> THROW
```

**Branch meaning:**
- If `ownerId` is absent, the controller prepares a fresh `Owner` instance for creation flows.
- If `ownerId` is present, the controller loads the persisted owner from the repository.
- If the repository does not contain the requested owner, the controller raises an `IllegalArgumentException` with a descriptive message.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `ownerId` | `@PathVariable(name = "ownerId", required = false) Integer` | Optional owner identifier from the request path. When present, it selects an existing owner record for update or display flows; when absent, it indicates a new owner creation context and triggers construction of an empty owner aggregate. |

**Instance fields / external state read by the method:**
- `this.owners` — the injected `OwnerRepository` used to retrieve an existing owner by primary key.

## 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.
Use the pre-computed evidence above. If SC Code or Entity/DB is missing, try to infer from:
- The **SC Code** (Service Component code, e.g., `EKK0361A010SC`, `EKK1081D010CBS`) — look at the class name of the called method or its containing class.
- The **Entity/DB tables** — search for table name constants (often `KK_T_*` pattern), SQL references, or entity names in the called method's source code.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `OwnerRepository.findById` | `OwnerRepository` | `Owner` | Loads a single owner aggregate by identifier and returns it when present. |
| C | `new Owner()` | N/A | `Owner` | Creates a transient owner instance for a create form when no owner identifier is supplied. |
| C | `IllegalArgumentException` supplier | N/A | N/A | Constructs the exception message used when the requested owner cannot be found. |

## 5. Dependency Trace



Trace who calls this method and what this method ultimately calls.
Use the pre-computed evidence and caller search results from Step 2 above.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Screen: PetController | `PetController.findOwner` -> `OwnerController.findOwner` | `OwnerRepository.findById [R] Owner` |

**Instructions:**
- Use `search_files` with pattern `**/*.java` and content_pattern `findOwner` to find all callers.
- For each caller, identify if it's a Screen (class name contains `KKSV*`, `Screen*`), Batch, Controller, or CBS.
- Build the full call chain from the entry point to this method. 
- Each row = one unique entry point. Show ALL found callers (up to 15 rows).
- The Terminal column lists ALL CRUD endpoints reached FROM this method.
- Format terminal as: `methodName [C/R/U/D] EntityOrTableName`
- If a caller class name matches `KKSV\d{4}`, format as `Screen:KKSVxxxx`.

## 6. Per-Branch Detail Blocks

Analyze the method's control flow block by block. Analyze ALL nesting levels — no depth limit.

> Each branch of the control flow is displayed as a hierarchical block structure.

**Block 1** — **IF** `(ownerId == null)` (L65)

> Creates a new owner aggregate for creation flows.

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

**Block 2** — **ELSE** `(ownerId != null)` (L65)

> Loads an existing owner from persistence for update or display flows.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `this.owners.findById(ownerId)` |
| 2 | CALL | `.orElseThrow(() -> new IllegalArgumentException(...))` |
| 3 | RETURN | `return` resolved `Owner` instance |

**Block 2.1** — **ELSE** `(Owner not found)` (L66-L69)

> Fails fast when the requested owner identifier does not correspond to a persisted record.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `new IllegalArgumentException("Owner not found with id: " + ownerId + ". Please ensure the ID is correct and the owner exists in the database.")` |
| 2 | RETURN | `throw IllegalArgumentException` |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `ownerId` | Field | Owner identifier from the URL path, used to select an existing owner record. |
| `owner` | Model attribute | MVC model object bound to owner create/edit screens. |
| `Owner` | Domain entity | Customer/household record that owns pets in the PetClinic domain. |
| `OwnerRepository` | Repository | Data access component that retrieves owner records from persistence. |
| `path variable` | Web term | A value embedded in the URL path and mapped into controller parameters. |
| `ModelAttribute` | MVC annotation | Indicates a method that prepares a model object before the handler executes. |
| `IllegalArgumentException` | Exception | Runtime exception used to signal an invalid or missing owner reference. |
| create flow | Business term | Screen journey for registering a new owner record. |
| update flow | Business term | Screen journey for editing an existing owner record. |
| display flow | Business term | Screen journey that needs the owner record loaded for presentation. |
| aggregate root | Domain term | The primary domain object that owns related state and is loaded as a single unit. |
