Creating OrderInitializeExecutor
You know that the request comes to the OrderController
and the request is transferred to the UserDetailExecutor
as the first step to collect the user details.
And next, we are going to initiate the order in the own service (order-service).
To initiate the order will be creating an executor called OrderInitializeExecutor
.
The OrderInitializeExecutor should be a command-executor because the primary execution (updating order database) makes some changes in the database, and then if a failure occurred at some point after executing the order initialization process, it should be recovered again.
(1)
@SagaExecutor(executeFor = "order-service", liveCheck = false, value = "OrderInitializeExecutor")
@RequiredArgsConstructor
public class OrderInitializeExecutor implements CommandExecutor<PlaceOrderAggregator> { (2)
(3)
private final OrderService orderService;
private final ObjectMapper objectMapper;
@Override (4)
public ProcessStepManager<PlaceOrderAggregator> doProcess(PlaceOrderAggregator currentAggregator, ProcessStepManagerUtil<PlaceOrderAggregator> stepManager) throws RetryableExecutorException, NonRetryableExecutorException {
try {
currentAggregator.getExecutions().add(this.getClass().getSimpleName() + ":" + LocalDateTime.now());
(5)
this.orderService.initialize(
OrderEntity
.builder()
.orderId(currentAggregator.getAggregatorTransactionId())
.userId(currentAggregator.getUserId())
.createAt(LocalDateTime.now())
.isCancelled(false)
.items(objectMapper.writeValueAsString(currentAggregator.getItems()))
.build()
);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
(6)
return stepManager.next(PreAuthExecutor.class, OrderStatus.INITIALIZED_ORDER);
}
@Override
public SagaExecutionEventName doRevert(NonRetryableExecutorException processException, PlaceOrderAggregator finalAggregatorState, RevertHintStore revertHintStore) throws RetryableExecutorException {
(7)
this.orderService.cancelOrder(finalAggregatorState.getAggregatorTransactionId());
(8)
revertHintStore.put(
String.valueOf(System.currentTimeMillis()),
this.getClass().getSimpleName() + ":doRevert"
);
(9)
if (finalAggregatorState.getHasRevertError()) {
throw new RuntimeException("dummy error for revert-failed.");
}
(10)
return OrderStatus.CANCELED_ORDER;
}
}
1 | Annotate the OrderInitializeExecutor class as a SagaExecutor by using @SagaExecutor annotation.
Read more about |
||
2 | The class has been extended from the CommandExecutor .
Read more about |
||
3 | Autowire the OrderService service to make the execution.
(ObjectMapper has been Autowired just for getting the JSON string) |
||
4 | Overridden the doProcess and doRevert methods. |
||
5 | Initialize the order-details by calling the orderService. | ||
6 | After Initializing the order successfully, SEC is navigated to the next executor by using stepManager.next .
The next executor is PreAuthExecutor and also the current executed is marked as INITIALIZED_ORDER in the event-store. |
||
7 | The order is marked as canceled one if the primary execution should be reverted. |
||
8 | Update the hint-store object by adding current millisecond and the revert method name with the executor name while the revert process. In your real application, the hint-store can be used for adding some data regarding the revert process. It can be accessed from the next revert process. |
||
9 | We used a variable called hasRevertError in the aggregator to test a revert-failed transaction.
If we have passed the hasRevertError value as true , throw an exception to terminate the transaction.
|
||
10 | If the canceling process is successfully executed, return the event name as CANCELED_ORDER. |