Search code examples
javaspringspring-mvcspring-datamicroservices

how to roll back a transaction happening between microservices?


we have microservice architecture where for most part each microservice is independent. But for some legacy reasons, there is a situation where we have to call another microservice from within another.

eg: the following method is part of Legal Service

@Autowired
public ServiceManager UserServiceManager;

public void updateUserLegalData(){

    //do db update of Legal info for the user

   userServiveManager.setAcceptedLegal(true);


}

There are two db transactions going on above. one is updating legalService db and other is updating UserService db. please NOTE userService is a microservicerunning on a separate VM.

we are seeing situations where legal Service db is updated but call to userService is failing (Internal server error). so this leaves the application in an inconsistent state. How can we fix this in a recommended way?

Thanks


Solution

  • This situation can be handled only with JTA global/distributed transactions. JTA is part of Java EE standard and can have various implementors. Atomikos is often tool of choice.

    Here is good writeup from Dave Syer (Spring ecosystem contributor). It contain also working examples. It's little bit outdated, but still relevant. You can apply some more modern Spring abstractions on top of his examples.

    I created few GitHub examples of JTA transactions for my book. Notice that there are errors simulated and transaction is spread across JMS and JDBC datasources.

    But also bear in mind that JTA transactions across various data sources are slow, because of 2-phased commit algorithm involved. So often people try to avoid them and rather deal with inconsistencies somehow pragmatically.