Service APIs

The interviewer just said…

“What APIs or services would you expose?”

They have your entities. Now they want boundaries — who owns which operation, and what methods a client (or controller) would call.


What you should do next

Propose five services. One orchestrator (BookingService), three domain services, one stub. Write method signatures only — no implementation yet. Say which service owns seat state transitions (ShowService).


Service map

┌──────────────┐     ┌─────────────┐     ┌───────────────┐
│ MovieService │     │ ShowService │     │ TicketService │
│ search       │     │ seats       │     │ tickets       │
└──────┬───────┘     └──────┬──────┘     └───────┬───────┘
       │                    │                    │
       └────────────────────┼────────────────────┘

                   ┌─────────────────┐
                   │ BookingService  │  ◄── orchestrates saga
                   └────────┬────────┘

                   ┌────────▼────────┐
                   │ PaymentService  │  ◄── stub in v1
                   └─────────────────┘

MovieService — discovery by city

Owns read-only movie/theater/show discovery. No seat mutations.

public class MovieService {
    // Movies currently playing in a city (distinct movie names/ids)
    Set<String> searchMovieForCity(String city);

    // Shows for a movie (theater, time) — extend in later iterations
    List<String> searchShowForMovie(String movieId);

    // Which theaters host a given show
    List<String> searchTheaterForShow(String showId);
}

Reference: MovieService.searchMovieForCity walks TheaterRepoShowRepo and collects movie IDs.


ShowService — seat inventory

Only service that should flip ShowSeat.status (reserve, book, release).

public class ShowService {
    List<ShowSeat> getAvailableSeats(String showId);

    void reserveSeat(String showId, List<String> seatIds) throws ReserveException;

    void bookSeat(String showId, List<String> seatIds) throws BookingException;

    void releaseSeat(List<String> seatIds, String showId);
}

Implementation note for later: reserveSeat checks all requested seats are AVAILABLE, sets RESERVE + reserveTime. bookSeat moves RESERVEBOOKED. releaseSeatAVAILABLE.


BookingService — saga orchestrator

Coordinates the multi-step flow. Does not mutate seat rows directly — delegates to ShowService.

public class BookingService {
    String bookShow(String showId, String userId, List<String> seats);

    void cancelTicket(String ticketId);
}

Expected internal sequence for bookShow:

showService.reserveSeat(showId, seats);
String paymentId = paymentService.initiatePayment(userId, showId, seats);
showService.bookSeat(showId, seats);
return ticketService.bookTicket(userId, showId, seats, paymentId);

In hub/scripts/movie-ticket-sourced/ v1 demo, payment is commented out and "paymentId" is hardcoded — fine for LLD.


TicketService + PaymentService (stub)

public class TicketService {
    String bookTicket(String userId, String showId, List<String> seats, String paymentId);
    Ticket findById(String id);
}

public class PaymentService {
    String initiatePayment(String userId, String showId, List<String> seats)
            throws PaymentException;
    void refund(String paymentId);
}

TicketService generates a UUID and saves to TicketRepo. PaymentService is stubbed — “Real gateway out of scope; I return paymentId or throw PaymentException.”


Exception types (mention on board)

Exception When
ReserveException Seat not AVAILABLE at reserve time
PaymentException Charge failed
BookingException Could not confirm after payment
TicketException Ticket row failed after seats BOOKED

These drive compensating actions in BookingService (next implementation chapters).

Client entry points: search → MovieService.searchMovieForCity; seats → ShowService.getAvailableSeats; book/cancel → BookingService. Method names are your API in LLD — no controller layer required.