0
@Controller
public class MyControllerClass{
    @Autowired
    private MyService service;

    public SomeResponse callServiceMethod(SomeRequest reqObj){
         try{
            //lines of codes
            service.serviceMethod(reqObj);
           //lines of codes
        } catch(Exception ex){
            S.O.P("caught inside callServiceMethod of Controller 
            class");
        }
    }


public interface MyService{
    SomeResponse serviceMethod(SomeRequest reqObj);
}


@service
public class MyServiceImpl implements MyService{
    @Autowired
    private EmployeeDAO empDAO;

    @Autowired 
    private PersonDAO personDAO;

    @Autowired 
    private MetadataDAO metaDAO;

    @Transactional(value="transaction_manager_Bean_Name")
    public SomeResponse serviceMethod(SomeRequest reqObj){
         List<Person> personList = ....;//fetch list of person from 
                                         //reqObj
         List<Employee> empList = ......;//fetch list of Employee 
                                         //from reqObj

         SomeHelper someHelper = new SomeHelper(empDAO, personDAO, 
                                          metaDAO);

         try{
            doOperationOnPerson(...);
            doOperationOnEmployee(...);
            doOperationOnMetadata(...);
        } catch(Exception ex){
            S.O.P("caught inside serviceMethod of Impl class");
        }

     }


     @Transactional(value="transaction_manager_Bean_Name")
     public void doOperationOnPerson(List<Person> personList, 
                  List<String> personErrors, SomeHelper someHelper){
        personList.stream().forEach(person ->{
            try{
               someHelper.performTaskOnPerson(person, personErrors);
            } catch(Exception ex){
                  S.O.P("caught inside doOperationOnPerson of Impl 
                  class");
                  personErrors.add(ex.getMessage());
            }
        }
     }

     @Transactional(value="transaction_manager_Bean_Name")
     public void doOperationOnEmployee(List<Employee> empList, 
               List<String> empErrors, SomeHelper someHelper){
        empList.stream().forEach(emp ->{
            try{
               someHelper.performTaskOnEmployee(emp, empErrors);
            } catch(Exception ex){
                 S.O.P("caught inside doOperationOnEmployee of Impl 
                 class");
                 personErrors.add(ex.getMessage());
            }
        }
     }

     @Transactional(value="transaction_manager_Bean_Name")
     public void doOperationOnMetadata(SomeOtherData metadata, 
            List<String> metaDataList, SomeHelper someHelper){
          empList.stream().forEach(emp ->{
             try{
                  someHelper.performTaskOnMetaData(metadata, 
                      metaDataList);
             } catch(Exception ex){
                  S.O.P("caught inside doOperationOnMetadata of Impl 
                  class");
                  personErrors.add(ex.getMessage());
             }
          }
      }
 } 

 public class SomeHelper{
     private PersonDAO personDAO;
     private EmployeeDAO empDAO;
     private MetadataDAO metaDAO;

     SomeHelper(PersonDAO personDAO, EmployeeDAO empDAO, MetadataDAO 
                metaDAO){
          this.personDAO = personDAO;
          this.empDAO = empDAO;
          this.metaDAO = metaDAO;
     }

     @Transactional(value="transaction_manager_Bean_Name", 
                    propagation=Propagation.REQUIRES_NEW)
     public void performTaskOnEmployee(Employee emp, List<String> 
                          empErrors){
          EmpEntity empEntity = empDAO.getEmployee(emp);
          empEntity.setName(...);
         //update other fields
     }

     @Transactional(value="transaction_manager_Bean_Name", 
                    propagation=Propagation.REQUIRES_NEW)
     public void performTaskOnEmployee(Person person, List<String> 
                           personErrors){
          PersonEntity perEntity = personDAO.getPerson(person);
          perEntity.setName(...);
          //update other fields
     }

     @Transactional(value="transaction_manager_Bean_Name", 
                        propagation=Propagation.REQUIRES_NEW)
     public void performTaskOnMetaData(SomeOtherData metadata, 
                                List<String> metaDataList){
        MetaEntity metaEntity = metaDAO.getOther(metadata);
        metaEntity.setName(...);
        //update other fields
    }
}

When some exception occurs in any of the method (having transactional block with propagation behaviour set as 'requires_new') in somehelper class, why it is not being handled in the caller class (having transactional block with default propagation behaviour)? Instead of seeing the msg "caught inside doOperationOnMetadata of Impl class", I am getting message "caught inside callServiceMethod of Controller class".

Azzabi Haythem
  • 2,318
  • 7
  • 26
  • 32
Sumit
  • 1,733
  • 1
  • 8
  • 4
  • What I meant to ask is when a exception is thrown from a method ( method 2 with propagation as requires_new) which is being called from another method (method 1 with default propagation), can that exception (which means rollback) be handled at caller method (method 1) – Sumit Jul 26 '18 at 16:11

1 Answers1

0

If the question is on whether transaction rollback can happen at the outer method should there be an exception in the underlying method, then the answer is no with Propagation as REQUIRES_NEW since each method would be considered as an independent transaction.

Reference - @Transactional(propagation=Propagation.REQUIRED) and https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html#tx-propagation

Kishore
  • 1
  • 1
  • 7