I'm trying the Camel SAGA-LRA component and I have two doubts about how to pass data from main actions to compensating actions, bu using the SAGA OPTION mechanism.
What I would do is reuse an ID returned by the first SAGA main action, to eventually use in compensating actions:
@Override
public void configure() throws Exception {
// Start SAGA
from("direct:checkout")
.log(LoggingLevel.INFO,"A new ORDER CHECKOUT has been requested --> JSON Request: ${body} --> Starting new SAGA/checkout")
// START the SAGA
.saga()
.timeout(15000, TimeUnit.MILLISECONDS)
.to("direct:createOrder") // Create an Order --> Call a REST Service which return the ID of the created Order. I want to pass this ID to compensating actions in case of failure
.to("direct:updateProductsAvailableStock"); // Update the Available Stock of product's order
// SAGA STEP: CREATE ORDER --> provided by ORDERS-API service
from("direct:createOrder")
.id("CREATE_ORDER_ROUTE")
.saga() // Join the SAGA
.compensation("direct:rollbackCreateOrder") // Configure the compensation action
// Call the underlying REST API: POST /order
.toD("rest:post:order/user/{user_email}?host=localhost:12000/orders-api&bindingMode=json")
.option("create_order_response",body()) // Passing the "CREATE ORDER JSON RESPONSE" (which contains the ID of the ORDER to delete) to the compensating action
.unmarshal().json(Order.class)
.throwException(new Exception("@@@@ CAUSED EXCEPTION @@@@")); // Deliberately thrown exception which triggers the compensating action
// SAGA COMPENSATION ACTION - ROLLBACK CREATED ORDER [Must be idempotent] --> ORDERS-API - DELETE /order/{order_code}
from("direct:rollbackCreateOrder")
.id("ROLLBACK_CREATED_ORDER")
.log(LoggingLevel.WARN,"Order to delete: ${header.create_order_response}"); // Here is the problem: the body of original request is logged rather then the response of the called service
// TODO: Call the REST service to delete the Order
}
The problem is that when the compensating action is triggered, the option passed as header is populated with the message body of the original request (the body of from("direct:checkout") ) rather than the body of the message returned by the " .toD("rest:post:order/user/{user_email}?host=localhost:12000/orders-api&bindingMode=json")".
Is this a bad approach? Should I generate global IDs to reuse both in main actions and in compensating actions?
Thank you