0

I have below method call hierarchy

public class UpdateProcess   { 

       public void startingMethod(List<Object> objects){
          for (Object obj : objects) {
              method1(obj);
           }
       }

        @Transactional
        public void method1(Object obj) {
            method2(obj);
        }


        public void method2(Object obj) {
           EmployeeService.updateObject(obj)
        }
    }   

public class EmployeeService

    @Transactional
    public void updateObject(Object obj) {

        return customerDao.update(obj);
    }


  }

In above scenario, My expectation is spring should commit the transaction as thread comes out of Method1 or rollback if exception occurs anywhere in hierarchy.

But spring is committing the transaction as soon as update is executed in method2. I am not getting why ?

UPDATE:- Even if I change @Transactional to @Transactional(propagation=Propagation.REQUIRES_NEW) its still committing the transaction. So No impact

emilly
  • 10,060
  • 33
  • 97
  • 172
  • 1
    Please post proper code if you want to get answers. – Kayaman Nov 09 '16 at 18:49
  • @Kayaman I have posted the relevant code. Is there any specific stuff you are looking for here ? – emilly Nov 09 '16 at 19:01
  • That code won't even compile, so it's clearly not the real code and it would be useless to comment on it. – Kayaman Nov 09 '16 at 19:02
  • What about posting some classes rather than a random bunch of methods. – Alan Hay Nov 09 '16 at 19:03
  • @AlanHay complete code is too big(too big classes/XML configuration). If you can guys can provide the direction where can be the problem , it will be really helpful or if you are looking for specific stuff, I can post it – emilly Nov 09 '16 at 19:08
  • @Kayaman extremely sorry. I am not sure how come I missed it. Corrected it. – emilly Nov 09 '16 at 19:18
  • @emilly It looks a bit odd. Do you have an ongoing transaction when you're entering `method1()`? In any case, if you're making a call to it from the same object (e.g. from `startingMethod()`), the annotation won't be processed at all since it's a local method call that can't be intercepted. Calling `updateObject()` works because you're making a method call to another object, it will be intercepted and the transaction mechanism will be handled. – Kayaman Nov 09 '16 at 19:23
  • 1
    See http://stackoverflow.com/questions/23931698/spring-transactional-annotation-self-invocation and http://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html#transaction-declarative-annotations – Alan Hay Nov 09 '16 at 19:24
  • Is your EmployeeService declared as interface or concrete class in UpdateProcess? – Alexey Soshin Nov 09 '16 at 19:30
  • @AlexeySoshin EmployeeService is an interface – emilly Nov 09 '16 at 19:32
  • @Kayaman Perfect. I got your point. Is there a way I can make self invocation method(in this case method1) Transactional or I have to move it to separate class ? I don't want to make `startingMethod` Transactional as I want to commit per object instead on collection – emilly Nov 09 '16 at 19:34
  • @emilly It's usually a better idea to redesign so you don't need to do the tricks required for self invocation. You should have a layered architecture anyway, that way it's harder to run into this problem (as well as getting additional advantages). – Kayaman Nov 09 '16 at 19:46
  • @Thankyou kayaman – emilly Nov 13 '16 at 14:52

1 Answers1

0

When using Proxy-based Spring AOP, calling another method on the same object does not cause aspects to get applied. The implementation of @Transactional for UpdateProcess would be created in a proxy that resides between UpdateProcess and other beans. So if you call the method from "inside" the bean instead of "outside" of it, the call does not pass through the proxy and the aspects are not applied.

Affe
  • 47,174
  • 11
  • 83
  • 83