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");
}
}
}
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.