5

The problem is simple

@Around("execution(* package.*Repository.save(..))")
public Object saveInterupt(ProceedingJoinPoint joinPoint) throws Throwable {
// This gets called whenever repository save is called
}

@Around("execution(* package.*Repository.findAll(..))")
public Object findInterupt(ProceedingJoinPoint joinPoint) throws Throwable {
// This IS NOT GETTING called whenever repository findAll is called
}

Breaking head here!

Edit: A small break through. I printed the target , it returns SimpleJpaRepository instead of the Actual repository.

madhairsilence
  • 3,787
  • 2
  • 35
  • 76
  • Brief as the question, fail to solve after a day debug. Headache! – Lebecca Dec 05 '19 at 05:20
  • The method `findAll` and `save` from `CrudRepository` is implemented default in `SimpleJpaRepository`. So `*Repository` is a jdk dynamic proxy that in honour of `SimpleJpaRepository` in runtime. – Lebecca Dec 05 '19 at 05:26
  • @Lebecca so how do I log the actual calling class? – madhairsilence Dec 05 '19 at 12:19
  • You can set a breakPoint in the `SimpleJpaRepository save() or getAll()` methods, and run the application in debug mode to prove my words. The key point is not the inner object, it's the invocation chain that the proxy executes before the inner object method gets called. Spring uses some cache for building the chain makes it a mysterious for me why `findAll` not get enhanced. – Lebecca Dec 05 '19 at 12:58
  • @Around("execution(* org..*Repository.save(..)) and @Around("execution(* org..*Repository.findAll(..)) works for me all the time. If you want to intercept at a package level , pointcut designators within && execution could be combined. – R.G Dec 05 '19 at 17:16
  • Could you please provide clarity on the "package" used within @Around("execution(* package.*Repository.save(..))") . – R.G Dec 05 '19 at 17:17
  • @R.G There is a [demo](https://github.com/LangInteger/spring-aop-demo) where I face the same problem with madhairsilence. – Lebecca Dec 06 '19 at 01:46
  • @Lebecca On a quick look , you are setting @EnableAspectJAutoProxy(proxyTargetClass=true) . This enables CGLIB-style 'subclass' proxies and not the default interface-based JDK proxy. This is the primary and most important difference between our testcases. You may set it to false or remove the attribute which is equivalent to setting it to false and rerun the testcases. – R.G Dec 06 '19 at 04:49
  • @R.G Thanks for your suggestions. The abnormal config is just a try, but CGLIB/JDK proxy doesn't make a difference in my test. – Lebecca Dec 06 '19 at 05:23
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/203726/discussion-between-lebecca-and-r-g). – Lebecca Dec 06 '19 at 06:54
  • @Lebecca , adding for future reference : https://github.com/spring-projects/spring-framework/issues/24207 – R.G Dec 15 '19 at 03:09
  • The main issue is your pointcut. The method isn't defined on your interface, rather a super interface. You should write a pointcut on that hierachy something like `org.springframework.data.jpa.CrudRepository+.save(..)`, notice the `+` which is key here. If you want to limit within your own package then add an `within('your.package)` to the expression. – M. Deinum Dec 16 '19 at 11:51
  • @M.Deinum so why does it work for one method but not for other – madhairsilence Dec 16 '19 at 13:20
  • Did you override/added the `save` method to your own interface? – M. Deinum Dec 16 '19 at 13:24
  • No. I have additional methods but no requirement to override default save/find method – madhairsilence Dec 17 '19 at 09:26

2 Answers2

0

Assuming the repository is of the following construct

public interface JpaEmployeeRepository extends CrudRepository<JpaEmployee, Long> {..}

following pointcut works on both the cases

@Around("execution(* org..*Repository.save(..))")

and

@Around("execution(* org..*Repository.findAll(..))")

If I understand the question correctly the requirement is to intercept on the execution of a particular method within a specific package.If yes, More details on the same can be read here. @AspectJ pointcut for all methods inside package

R.G
  • 6,436
  • 3
  • 19
  • 28
-1

Are you using Spring-BOOT ? Aspecting in Spring-BOOT only calls the advice on a single method in the class the first time it is called. If you want Spring-BOOT to respect your @Around advice in all cases for multiple methods in any given class -- you need to access the class as a bean (SB's @Bean)...

Spring-BOOT's AOP is not 100% the same as aspecting using AspectJ -- the main difference is AspectJ modifies the byte-code where Spring uses a dynamic proxy.