0

I am have service-1's method calling service-2 and service-3 methods using @Transactional.

Now, Scenario_1 (Working scenario):

Service-1:

@Transactional
void m1() {
    m2();  // of Service 2  
    m3();  // of Service 3
}

Service-2:
@Transactional(propagation = Propagation.REQUIRES_NEW)
void m2() {
    //1. Insert Employee
}

Service-3:
@Transactional
void m3() {
    // 1. Insert Insurance 
    // 2. Throw RuntimeException
}

Result:
1. Employee inserted
2. Insurance object not inserted (i.e. rolled back)

Scenario_2 (Not getting expected result): (put "propagation = Propagation.REQUIRES_NEW" in Service-3 method instead of Service-2 method)

Service-2:
@Transactional
void m2() {
    //1. Insert Employee
}

Service-3:
@Transactional(propagation = Propagation.REQUIRES_NEW)
void m3() {
    // 1. Insert Insurance 
    // 2. Throw RuntimeException
}

Result:
1. Employee not inserted  (why ?)
2. Insurance not inserted (i.e. rolled back)

In Scenario_2, should exception in Service-3 affect (roll back) Service-2, as Service-3 is running in new transaction ? Is my understanding correct or am I missing something ? Please suggest.

Following are the actual files for reference (working scenario):

1. OrganzationServiceImpl.java

@Service
public class OrganzationServiceImpl implements OrganizationService {
    @Autowired
    EmployeeService employeeService;

    @Autowired
    HealthInsuranceService healthInsuranceService;

    @Transactional
    @Override
    public void joinOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance) {
        employeeService.insertEmployee(employee);
        healthInsuranceService.registerEmployeeHealthInsurance(employeeHealthInsurance);
    }
}

2. EmployeeServiceImpl.java

@Service
public class EmployeeServiceImpl implements EmployeeService {
    @Autowired
    EmployeeDao employeeDao;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void insertEmployee(Employee employee) {
        employeeDao.insertEmployee(employee);
    }   
}

3. HealthInsuranceServiceImpl.java

@Service
public class HealthInsuranceServiceImpl implements HealthInsuranceService {

    @Autowired
    HealthInsuranceDao healthInsuranceDao;

    @Transactional
    @Override
    public void registerEmployeeHealthInsurance(EmployeeHealthInsurance employeeHealthInsurance) {
        healthInsuranceDao.registerEmployeeHealthInsurance(employeeHealthInsurance);
        if (employeeHealthInsurance.getEmpId().equals("emp1")) {
            throw new RuntimeException("thowing RuntimeException for testing");
        }
    }
}

1 Answers1

0

In my understanding, the issue is that in Scenario 2, the transaction from Service-1 also gets rolled back because you don't handle RuntimeException from Service-3. Since Service-2 is, in this scenario, in the same transaction as Service-2 the employee insertion is rolled back. This does not happen in Scenario 1 because you have a separate transaction for Service-2.

João Dias
  • 16,277
  • 6
  • 33
  • 45
  • Thanks @João Dias , Catching the RuntimeException in joinOrganization() method gives the expected result. I was wondering even if we don't handle it, it should not have affected the Service2 in Scenario-2 as the it was running in completely different transaction. I referred to the following post also: [https://stackoverflow.com/questions/33729810/what-does-suspending-a-transaction-means](https://stackoverflow.com/questions/33729810/what-does-suspending-a-transaction-means) – ranjan kalita Aug 11 '21 at 04:54
  • But that is the thing. In Scenario 2 you have 2 transactions: 1. Service3 which is rolled back due to uncaught `RuntimeException`. 2. Service1 and Service2 which is also rolled back due to the uncaught `RuntimeException` thrown in Service3. Either you handle the exception in Service1 as you just did our you use `@Transactional(propagation = Propagation.REQUIRES_NEW)` in Service2 as well, but you need to think if that makes sense in terms of business logic. – João Dias Aug 11 '21 at 08:51
  • Thanks again for this clear explanation. I appreciate it, unfortunately I can not up vote your answer as I lack required reputation points. – ranjan kalita Aug 11 '21 at 19:36
  • If my answer helped you I believe you are able to mark it as the "correct" one. Thanks. – João Dias Aug 11 '21 at 21:43