1

My advice is not getting called for method getPOInvoice method from this method, but if I call it separately then advice is getting called and getPOInvoice and getPOInvoice is declared in same class.

public StreamingOutput getPDFStream(String invoiceId, String versionNumber) throws TugnavException {

   final POInvoice poInv =  getPOInvoice(invoiceId, versionNumber);
   ...
}

My advice is:

@AfterReturning(value="execution(* com.tugnav.service.facade.*.get*(..))", returning="doc")
    public TugnavBaseDocument setupTimeCreatedString(TugnavBaseDocument doc){
    ...

}

If I call this method from another class then advice is getting called.

Why is it not getting called internally?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Rahul Kale
  • 207
  • 1
  • 3
  • 7

3 Answers3

4

You need to read the documentation about proxies here.

Basically, because of the way proxies are generated, a instance method call within another instance method will not trigger an aspect (or proxy behavior).

Given:

class FooBar {
    // advised method
    public void foo() {
        bar();
    }

    // would've been advised
    public void bar() {
        // ... do something
    }
}

Say an instance of FooBar was proxied, a call to foo() will trigger the aspect because from outside you have a reference to the proxy object. When you call bar() internally, you have access to this (equivalent to this.bar()) which is a reference to the target instance, the actual object, so there is no added behavior.

There are a few ways to solve this problem, but probably not the way you want. See the answer to this question.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
0

AOP would not normally work this way.

AOP is added as an aspect through Proxies, to compiled class, so it does not have any effect on the internal class invocations.

  1. When it's an outer cal, you are actually referring to some Proxy which intercepts your call and triggers appropriate AOP calls.
  2. When it's internal cal, inside the class, it is a direct call, without any Proxy involved.

As a solution you can do following:

  1. Refactore service you are using, to exclude internal calls
  2. Alter bytecode on Class loading, with your AOP functionality :)
mavarazy
  • 7,562
  • 1
  • 34
  • 60
  • I had the habit when I used Spring of never having a public method call a public method in a DAO class. Since Spring AOP is limited to public methods, that means I can't be tempted to try for this behavior. And if the AOP is used for logging, the log viewer doesn't need to see the input of the internal method. Actually, I stuck with Service classes that called DAO classes, where Spring AOP added logging and retries to the service classes. – Eric Jablow Jun 11 '13 at 21:21
0

If you want that your advice is called for getPOInvoice method when you are invoking from method getPDFStream(..), both in the same bean, you can't use a proxy-based AOP, like Spring use by default. Instead you should use load time weaving(LTW) with AspectJ.

http://static.springsource.org/spring/docs/3.2.2.RELEASE/spring-framework-reference/html/aop.html#aop-aj-ltw