2

I have 2 questions where I can't figure answers for them regarding @Transactional:

1- @Transnational on interface
as per answers :

If you have your app set to proxy-target-class='true' (in your application context, then your @Transactional information wont be picked up if you annotate the Interface.

I configured my application.properties with :

spring.aop.proxy-target-class=true

and the annotation on interface still picked up , I have tried also the following ( proxyTargetClass = true on EnableTransacationManagement ) :

@SpringBootApplication
@EnableAsync
@EnableTransactionManagement(proxyTargetClass = true)
public class Application extends SpringBootServletInitializer {
}

still the @Transnational is working where I'm configuring only on interface , so what am I missing here ?

2- @Transnational has @Inherited, the @inherited as per java doc :

Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

I have the following interface annotated with @Transnational and it's still working on the interfaces extending it :

@Repository
@Transactional
public interface UserRepository extends JpaRepository<User, Long> {


}

The following/below interface has modifying query where it won't work without @Transactional, I have annotated the interface above with @Transacational and it's being picked up ( it even works if I configure on parent methods instead of class ) :

public interface TestRepository extends UserRepository {

@Query("UPDATE User U set U.name='hello' where U.id=1")
@Modifying
public void test();

}

so how the transaction worked if the @Inherited doesn't have effect on interface ?


Update : for Question 1

I even tried @Async on interface method and it worked without annotating implementing class , the AOP is working with CGLIB proxies ( when annotating interface methods only ) this is contradiction with most of the answers not sure if there is anything wrong.

Mohammad Karmi
  • 1,403
  • 3
  • 26
  • 42
  • `@Transactional` and `@Async` work because Spring, in these cases` will also scan the interfaces implemented by a class for that annotation. This is a feature in Spring and has nothing to do with an annotation being `@Inherited` or not. Although, imho, you shouldn’t put those annotations on an interface as they belong on the class. Those behaviors should be an implementation detail. Finally you are using Spring Data JPA while you quote the regular Spring reference guide. Spring Data JPA has another way of detecting `@Transactional` etc. – M. Deinum Oct 24 '18 at 14:06
  • @M.Deinum what about proxy target class ? shouldn't annotations be ignored on the interface if we dont use JDK proxy ? if the annotation is set only on interface method then why the CGLIB doesn't ignore it – Mohammad Karmi Oct 24 '18 at 15:32
  • Because it doesn’t matter how it is proxied, Spring will detect the implemented interfaces and scan those if not found on the implementing class. – M. Deinum Oct 24 '18 at 17:30
  • @M.Deinum then the second answer here is not correct ?https://stackoverflow.com/questions/5551541/where-to-put-transactional-in-interface-specification-or-implementation). ? it has 40 votes and it says If you have your app set to proxy-target-class='true' (in your application context, then your Transactional information wont be picked up if you annotate the Interface. – Mohammad Karmi Oct 24 '18 at 17:51
  • That answer doesn’t apply here because you are using Spring Data JPA... That answer is for regular Spring based beans and IIRC that behavior has changed and that information is detected on interfaces regardless. – M. Deinum Oct 24 '18 at 17:56
  • @M.Deinum that explains it , can you please answer the question and I will approve it – Mohammad Karmi Oct 24 '18 at 17:57
  • There is longer discussion on this topic [here](https://coderanch.com/t/714204/frameworks/Spring-Transactional-inheritance) but unfortunately there is no answer there. You can also look at the [issue](https://github.com/spring-projects/spring-framework/issues/23538) on Spring github. Maybe someone will explain it there. – Dcortez Nov 24 '19 at 20:05

1 Answers1

1

The answer you link to is for Spring 3.0 however currently we are at Spring 5.1. This is roughly 7 versions ahead and that section of the reference guide doesn’t exist anymore.

It doesn’t matter which proxy mode you use Spring will always try to find the @Transactional annotation on implementing interfaces when not found on the implementation. This is Spring behavior and specially implemented in Spring, this deviates from the default annotation inheritance rules. (Normally when doing getAnnotation this wouldn’t work, so Spring implemented this). See also this section of the Spring reference guide.

Next to that you also use Spring Data JPA, which also adds metadata and annotation processing specially for the dynamic repositories it creates.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224