Saga Pattern Example

Saga Pattern Example

In this tutorial, we are going to discuss about the Saga Pattern Example. The Saga Pattern is a design pattern for managing distributed transactions. It ensures that a sequence of operations (each of which is a transaction in its own right) are executed successfully across multiple services. If any operation fails, compensating transactions are triggered to undo the changes made by previous operations.

Saga Pattern Example

Understanding the concept is great, but seeing it in action is even better! Here’s a Java example of the Saga Pattern using a similar travel booking scenario. We’ll use simple classes and methods to simulate the services and the saga coordinator.

1. Define the Services

Each service will handle its respective operations for booking and cancellation.

FlightService.java

public class FlightService {
    public String bookFlight(String userId, String flightDetails) {
        System.out.println("Flight booked for user " + userId + " with details " + flightDetails);
        return "flight123";
    }

    public void cancelFlight(String bookingId) {
        System.out.println("Flight booking " + bookingId + " canceled");
    }
}

HotelService.java

public class HotelService {
    public String bookHotel(String userId, String hotelDetails) {
        System.out.println("Hotel booked for user " + userId + " with details " + hotelDetails);
        return "hotel123";
    }

    public void cancelHotel(String bookingId) {
        System.out.println("Hotel booking " + bookingId + " canceled");
    }
}

CarRentalService.java

public class CarRentalService {
    public String bookCar(String userId, String carDetails) {
        System.out.println("Car rented for user " + userId + " with details " + carDetails);
        return "car123";
    }

    public void cancelCar(String bookingId) {
        System.out.println("Car rental " + bookingId + " canceled");
    }
}
2. Define the Saga Coordinator

The Saga Coordinator manages the sequence of operations and their compensations in case of failure.

SagaCoordinator.java

import java.util.HashMap;
import java.util.Map;

public class SagaCoordinator {
    private FlightService flightService;
    private HotelService hotelService;
    private CarRentalService carService;
    private Map<String, String> bookings;

    public SagaCoordinator() {
        this.flightService = new FlightService();
        this.hotelService = new HotelService();
        this.carService = new CarRentalService();
        this.bookings = new HashMap<>();
    }

    public void bookTrip(String userId, Map<String, String> tripDetails) {
        try {
            String flightBookingId = flightService.bookFlight(userId, tripDetails.get("flight"));
            bookings.put("flight", flightBookingId);

            String hotelBookingId = hotelService.bookHotel(userId, tripDetails.get("hotel"));
            bookings.put("hotel", hotelBookingId);

            String carBookingId = carService.bookCar(userId, tripDetails.get("car"));
            bookings.put("car", carBookingId);

            System.out.println("Trip booked successfully");
        } catch (Exception e) {
            System.out.println("Error occurred: " + e.getMessage());
            compensate();
        }
    }

    private void compensate() {
        if (bookings.containsKey("car")) {
            carService.cancelCar(bookings.get("car"));
        }
        if (bookings.containsKey("hotel")) {
            hotelService.cancelHotel(bookings.get("hotel"));
        }
        if (bookings.containsKey("flight")) {
            flightService.cancelFlight(bookings.get("flight"));
        }
        System.out.println("Compensation completed");
    }

    public static void main(String[] args) {
        SagaCoordinator coordinator = new SagaCoordinator();
        Map<String, String> tripDetails = new HashMap<>();
        tripDetails.put("flight", "Goa, 2022-07-10");
        tripDetails.put("hotel", "Goa, 2022-07-10 to 2022-07-15");
        tripDetails.put("car", "SUV, 2022-07-10");

        coordinator.bookTrip("ashok_here", tripDetails);
    }
}
Explanation
  1. Services: Each service class (FlightService, HotelService, CarRentalService) has methods to book and cancel operations.
  2. SagaCoordinator: This class coordinates the booking process. It tries to book a flight, hotel, and car rental. If any booking fails, it triggers compensating transactions to cancel the previously successful bookings.
  3. Main Method: The main method simulates the booking process for a user.

This example demonstrates how to implement the Saga Pattern in Java, ensuring that if any part of the process fails, the system compensates by undoing the successful operations to maintain consistency.

We have now seen a complete Java example of the Saga Pattern, demonstrating how it can maintain data consistency in a distributed system.

However, this is only a basic Saga Pattern Example. In a real-world application, there would be more complexity, more services involved, and more potential for failures. But don’t be intimidated! The Saga Pattern is well-equipped to handle these complexities. It allows us to split a large transaction into manageable, independent parts that can be executed and compensated for separately.

That’s all about the Saga Pattern Example. If you have any queries or feedback, please write us email at contact@waytoeasylearn.com. Enjoy learning, Enjoy Microservices..!!.!!

Saga Pattern Example
Scroll to top