0

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

0 Answers0