I have a need of creating a simple application that,
- Reads first available message from a RabbitMq Queue
- Save the object into a DB Table
The application is MVC type, and have an exposed http endpoint to trigger the operation by user.
All operations in the call need to participate in distributed transaction, and hence under one unit of work.
The code classes are like:-
Queue operation class:
public class ReadFromQueue {
pubic String readMessage(queue name) {
try {
rabbitTemplate.receiveAndConvert(queue);
} catch (AmqpException ex) {
return "failure";
}
}
Database operation class:
public class SavetoDatabase {
public String saveObject(object){
try { pigRepository.saveAndFlush(objectMapper.readValue(receivedPig,Pig.class));
} catch (Exception ex) {
ex.printStackTrace();
return "failure";
}
return "success";
}
}
The controller class:
@RestController
public class MyController {
@Transactional
@RequestMapping("/read")
public String readAndSavePigFromQueue(){
String databaseSaveResult;
String messageFromQueue = ReadFromQueue.readMessageFromQueue(queueName);
// Some checks on returned message
databaseSaveResult = SaveToObject.savePigToDatabase(messageFromQueue);
if ("failure" == databaseSaveResult) {
return "Failed Transaction";
}
return "Successful transaction";
}
}
Now the challenge is that, how can this complete operation be controlled transactionally on these distributed resources.
RabbitMq is said to be unspportive
to distributed transactions
, and hence the concern.
I want any failed save to database operation to result in message rollback to the queue, and leaving the failed message back in original state.
Any suggestions?