How to rollback child transaction if any exception in parent transaction?

893 views Asked by At

I have two transaction manager for two database. I need to persist same data into both databases. If one transaction failed, other one need rollback. I have done like below

public interface DataService {
    void saveData();
}

@Service
public class DataServiceImpl implements DataService {

    @Autowired
    private DataRepository dataRepository;
    
    @Autowired
    private OrDataRepository orDataRepository;
    
    @Autowired
    @Qualifier("orService")
    private OrService orDataServiceImpl;
    
    
    @Override
    @Transactional(transactionManager = "transactionManager", rollbackFor = {RuntimeException.class})
    public void saveData() {
        Data data = new Data();
        data.setCompKey(UUID.randomUUID().toString().substring(1,5));
        data.setName("data");
        dataRepository.save(data);
        orDataServiceImpl.save();
        //throw new RuntimeException("");
    }
}

public interface OrService {
    void save();
}


@Service("orService")
public class OrDataServiceImpl implements OrService {
    @Autowired
    private OrDataRepository orDataRepository;
    
    
    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public void save() {
        OrData data = new OrData();
        data.setCompKey(UUID.randomUUID().toString().substring(1,5));
        data.setName("ordata");
        orDataRepository.save(data);
    }
}

I have two transaction manager (entityManager & orEntityManager) for two different DB.

If any exception in OrDataServiceImpl save method, data is not getting persisted in both DB. But if any exception in DataServiceImpl saveData method, data is getting persisted into OrData table.

I want to rollback the data from both DB if any exception.

chainedTransactionManager is deprecated. So can't use. atomikos and bitronix also can't use due to some restrictions. Kindly suggest better way to achieve distributed transation

1

There are 1 answers

4
kus On
  • The code need to be refactored, edit the DataServiceImpl.save() method.

    Comment the orDataServiceImpl.save() line

     public void saveData() {
     Data data = new Data();
     data.setCompKey(UUID.randomUUID().toString().substring(1,5));
     data.setName("data");
     dataRepository.save(data);
     //orDataServiceImpl.save();
     //throw new RuntimeException("");
     }
    
  • Refactor/Edit the OrDataService Interface

     public interface OrDataService {
    
     void save(String uuid); 
     void delete(String uuid); 
    //will be use for compensating transaction
    

    }

  • Update the OrDataServiceImpl class to implement above interface

  • Write new orchestration Method and use compensating transaction to rollback

    pseudo code

    1. call OrDataServiceImpl.save()
    2. if step#1 was success
    3.   -> DataServiceImpl.saveData()
      
    4.  if Exception at step#3,
      
    5.       ->OrDataServiceImpl.delete() [//to rollback]
      
    6. else if, Exception at step#1 //do nothing