1

I was testing some code and found an interesting scenario.

Scenario:

public class ServiceA {
        public List<Object> saveAndGetAllV1() {
            serviceB.saveAll();
            return getAll();
        }

        public List<Object> saveAndGetAllV2() {
            serviceB.saveAll();
            return serviceB.getAll();
        }

        @Transactional(propagation = Propagation.MANDATORY)
        public List<Object> getAll() {
            repository.findAll();
        }
    }

    public class ServiceB {
        public void saveAll() {
            serviceC.saveAll();
        }

        public List<Object> getAll() {
            return repository.findAll();
        }
    }

    public class ServiceC {

        public void saveAll() {
            repository.saveAll(object);
        }

        @Transactional(propagation = Propagation.MANDATORY)
        public List<Object> getAll() {
            return repository.findAll();
        }
    }

The method saveAndGetAllV1() does not give any error even when the transaction is mandatory in serviceA.getAll() method. While on the other hand saveAndGetAllV2() gives error as serviceC.getAll() requires mandatory transaction.

So my question is why in serviceA.getAll() method the transaction is automatically created but in serviceC.getAll() method the transaction is not automatically created?

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • Spring uses proxies and only method calls INTO the proxy will get intercepted and have the aspect applied. Your first is in internal method call and thus doesn't pass through the proxy and basically is being ignored. – M. Deinum May 23 '20 at 08:31
  • @M.Deinum ok got it. But is there any elegant way I can find out all those methods whose @Transactional annotation is of no use. Like the one on ```serviceA.getAll()``` method. – Rajat Gupta May 23 '20 at 08:45

1 Answers1

1

The method saveAndGetAllV1() does not give any error even when the transaction is mandatory in serviceA.getAll() method.

That's because the call of getAll() is a local call and then the @Transactional is not used because the local call is not using the proxy.

Simon Martinelli
  • 34,053
  • 5
  • 48
  • 82