# ADR-035 — `Optional<String>` for three-way PATCH semantics

**Status:** Accepted  
**Date:** 2026-06-08  
**Issue:** #751 (JourneyItem CRUD API)

## Context

The `PATCH /api/geschichten/{id}/items/{itemId}` endpoint must distinguish three cases for the `note` field:

| JSON body         | Intended meaning      |
|-------------------|-----------------------|
| `{"note": "text"}`| Set note to "text"    |
| `{"note": null}`  | Clear the note        |
| `{}` (absent)     | Leave note unchanged  |

The standard library for this on Jackson 2.x is `jackson-databind-nullable` (`JsonNullable<T>` from `org.openapitools`). However, that library targets `com.fasterxml.jackson.*` (Jackson 2.x) and is incompatible with Spring Boot 4.0 / Spring Framework 7, which uses `tools.jackson.*` (Jackson 3.x). The module fails to register and throws at startup.

## Decision

Use `Optional<String>` with Java's default field initializer (`= null`) to encode the three states:

```java
@Data
public class JourneyItemUpdateDTO {
    private Optional<String> note = null;  // Java default — absent = no-op
}
```

| Java value         | JSON wire         | Semantics     |
|--------------------|-------------------|---------------|
| `null` (default)   | field absent      | no-op         |
| `Optional.empty()` | `{"note": null}`  | clear         |
| `Optional.of("x")` | `{"note": "x"}`   | set           |

Jackson 3.x natively maps a JSON `null` to `Optional.empty()` and leaves absent fields at their Java default. No custom module is needed.

## Consequences

- No external dependency for PATCH semantics — simpler pom.xml.
- The DTO field type is `Optional<String>`, not `String` — service code must null-check the field first (`if (noteField == null) return;`) and then call `.orElse(null)` to unwrap.
- This pattern applies to any future PATCH DTO that needs three-way semantics on a nullable field.
- `jackson-databind-nullable` is removed from `pom.xml`; `JacksonConfig.java` is kept as a placeholder for future custom modules.
