3

Seems like spring ignores @Transactional annotations on service classes. I read a few q&a on SO and blogs but none of the options seems to work for me.

  1. I'm NOT calling a private method - I call a public method that is exposed on the interface.
  2. I'm calling a method on a different class (i.e. not calling on from the same class).
  3. My "service" class is annotated with @Component and @Transactional.
  4. My "service class has an interface, and I'm injecting it using the interface, and @Inject annotation.
  5. I tried adding proxy-target-class="true" as described here in one of the answers - didn't work.
  6. I'm using JAX-RS (not spring-mvc).

The error happens on the DAO layer, annotated with @Transactional(propagation = Propagation.MANDATORY), when I get this exception:

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'

Here's some general code that represents the classes and interfaces involved:

public interface IService<T extends BaseEntity> {
    void save(T entity);
}

public abstract class AbstractService<T extends BaseEntity> implements IService<T> {

    @Inject
    private IDao dao;

    @Override
    public void save(T entity) {
        dao.save(entity);
    }
}

public interface IPersonService extends IService<PersonEntity> {
        void saveAll(List<PersonEntity> persons);
}

@Component
@Transactional
public class PersonService extends AbstractService<PersonEntity> implements IPersonService {

    @Override
    public void saveAll(List<PersonEntity> persons) {
        for (PersonEntity person : persons) {
            super.save(person);
        }
    }
}

@Component
public class PersonApi {

    @Inject
    private IPersonService personService;

    public void saveAll(...) {
        ...
        personService.saveAll(persons);
    }
}

Any ideas or suggestions?

Elad Tabak
  • 2,317
  • 4
  • 23
  • 33
  • 2
    And none of this matters if you are calling a method on the same class. AOP only works for external method calls not internal method calls. However as you haven't added code it is impossible to see where your error is. – M. Deinum Sep 11 '17 at 11:41
  • What makes you think that its not working? Can you share some code? – Leffchik Sep 11 '17 at 11:41
  • I'm not calling the method from the same class. As I said, I'm injecting the service using it's interface and I call it using the interface. I'm working on providing some code samples... – Elad Tabak Sep 11 '17 at 11:49

1 Answers1

2

So it turns out I must also annotate the abstract class with @Transactional as well, otherwise it will not work. Spring documentation talks only about interfaces. Since I'm calling an abstract class method here, it also needs to be @Transactional.

@Transactional
public abstract class AbstractService<T extends BaseEntity> implements IService<T> {

    @Inject
    private IDao dao;

    @Override
    public void save(T entity) {
        dao.save(entity);
    }


}
Elad Tabak
  • 2,317
  • 4
  • 23
  • 33