Advanced Saga Pattern Simulation using Spring Boot without External Brokers #152
akash-coded
started this conversation in
Guidelines
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Let's create an advanced saga pattern simulation using Spring Boot without external brokers, but instead, with Spring's
ApplicationEventPublisherto publish events between services.Part-1: Basics
1. Set Up:
Dependencies:
Generate Spring Boot projects for
OrderServiceandPaymentServicewith the following dependencies:2. Application Properties:
For both services, configure the H2 database:
src/main/resources/application.properties:3. Define the Domains:
Just like previously outlined, define entities and repositories for both services.
4. Implement the Saga Workflow using Event-Driven Approach:
This is where things get interesting. Instead of HTTP calls, we'll simulate an event-driven architecture using Spring's event system.
OrderService:
Define an Event:
Publish the Event:
PaymentService:
Note: In a real-world scenario, these two services (OrderService and PaymentService) would be in separate JVMs, so the event publishing/listening approach used above would not work. The above code simulates this within a single JVM for demonstration purposes. For decoupled services, we'd have to rely on a system like Kafka or RabbitMQ.
5. Testing:
Run the service and use Postman or any API testing tool to place an order via the OrderService. After placing an order, you should see the payment processed based on our dummy logic.
6. Advanced/Extensions:
Introduce Compensating Transactions: If a payment fails, implement logic in the OrderService to handle the failure. This might involve updating the order status to
PAYMENT_FAILEDand possibly notifying the user.Asynchronous Communication: You can extend the simple event system to more advanced and asynchronous communication using a broker like RabbitMQ or Kafka. However, this goes beyond our current constraints.
Monitoring and Logging: Introduce centralized logging using the ELK stack or any other log management tool. Track saga transactions across services.
Remember, while this approach uses a single JVM and simplifies event-driven communication, in real-world microservices, we'd use something more robust for asynchronous and decoupled communication. This example, however, should help learners grasp the concepts before moving on to more complex tools.
Part-2: Advanced
Let's incorporate the idea of compensating transactions into our Spring Boot saga simulation. The goal of compensating transactions is to ensure that when something goes wrong during the saga, an action is taken to revert or handle the failure.
Given our current setup with the
OrderServiceandPaymentService, let's consider the situation where a payment fails. We'll want theOrderServiceto react to this failure.1. Add New Event for Payment Failures:
PaymentService:
Define a new event to signal payment failures:
Modify the
PaymentEventListenerto publish this event when a payment fails:2. Listen to the Payment Failure Event in OrderService:
OrderService:
Add a listener to handle the
PaymentFailedEvent:This listener updates the order status to
PAYMENT_FAILEDwhen it receives a payment failure event.3. Testing the Compensating Transaction:
PaymentServicewill raise aPaymentFailedEvent.OrderServiceshould catch this event and update the order status toPAYMENT_FAILED.Advanced:
Notification System: Consider incorporating a notification system. When the payment fails and the order status is updated, the system can notify the user about the payment failure. This could be through an email, SMS, or a simple logging mechanism for the sake of this exercise.
Manual Override: Add an endpoint to manually approve a failed payment. This can mimic scenarios where a customer service representative might need to handle false positives in payment failures.
Monitoring and Logging: Introduce more granular logging. For example, log the exact reason for payment failures (could be insufficient funds, payment gateway timeout, etc.). This provides better visibility into the system's workings and aids in debugging.
Remember, while this exercise demonstrates the saga pattern and compensating transactions within a single JVM for simplicity, in a real-world scenario with distributed microservices, you'd likely use message brokers and other tools to handle these patterns across service boundaries.
Beta Was this translation helpful? Give feedback.
All reactions