A Controller Should Never Return an Optional
Why Optional belongs to the database layer, not a business action, and the exact point in the call chain where an Optional stops making sense.
TicketController's bookTicket method calls straight into a service, and the return type that method should never carry is Optional.
The Analogy: A Waiter Doesn't Say "Maybe"
Calling an API is like asking a waiter for food. The waiter doesn't say "probably I will, probably I won't." They bring the food, or they tell you clearly why they can't. An API answering a real request should behave the same way: a real result, or a clear failure, never an ambiguous maybe.
Optional Belongs to the Database Layer, Not a Business Action
Optional exists for exactly one kind of uncertainty: a row may or may not exist when you look it up. That's a database-layer concern, the honest answer to "does this ID exist in this table," nothing more.
Booking a ticket isn't that kind of question. It's a business action with a clear outcome: it succeeds, and a real ticket comes back, or it fails, and the caller gets a clear exception explaining why. A service performing an actual action should never hand back a "maybe." It returns the real object it was asked to produce, or it says clearly that it couldn't.
That leaves Optional doing exactly one job in this whole chain: at the repository layer, where a lookup by ID either finds a row or it doesn't. Everything built on top of that lookup, the service and the controller both, is expected to already know what happened and respond accordingly, not pass the uncertainty further up the chain.
A List Doesn't Need Optional Either
The same question comes up for a lookup that can return several rows instead of one: does a method returning a list of seats need to wrap that list in an Optional too? No — a list already represents "zero or more" on its own. Nothing found is just an empty list, not a missing value, so there's nothing left for Optional to add.
Keep reading