11 Replies Latest reply on Feb 23, 2004 3:02 PM by bill.burke

    New AOP stuff going on.

    bill.burke

      After a few months of no activity, JBoss AOP development is back in full force. Between working on JBoss 3.2 performance improvements, my daughter being born, and other AOP related political issues related to a certain non-JBoss individual that I'd rather not talk about that delayed development for over 10 weeks, I'm fully back coding full throttle.

      So what are we doing within the framework? Here's what I'm doing from my notes if you can make sense of it:



      DONE * compiler, add a precompiler so control of ClassLoader is not needed
       DONE - add sys property for jboss-aop.xml classpath
       DONE - add -verbose switch
       DONE - in runtime loader make sure that if CtClass instanceof Advised then do not transform class
       DONE ant task
      DONE * Create ways of loading XML in standalone mode so that control of the ClassLoader is not needed
      DONE * constructor expressions so that we can have per-constructor interceptors, metadata definitions
      * method expressions so that we can specify parameter expressions in pointcut
      * Add more metadata to CallerInvocation
      * Bug: Need to be able to have caller pointcuts from within a constructor
       This should work:
       <caller-pointcut callingClass="foo.bar" calledClass=".*"/>
      * scoping (In original JBoss AOP spec) by able to define the
      * aspect concept
      <aspect class="org.jboss.SomeAspect" scope="perInstance"/>
      
      <pointcut-ref name="somePointcut">
       <aspect class="org.jboss.SomeAspect" advice="blah"/>
       <interceptor>...</interceptor>
      </pointcut-ref>
      
      Where an Aspect can be any java class and advices are the methods. There will be two types of advice methods
      A method that takes an invocation object
      void someMethod(Invocation invocation);
      
      and:
      
      int someMethodThatIsExactlyLikeInterceptedMethod(String param);
      
      
      
      * AspectManagerService should have switch to turn off runtime loader
      * fine grain "prep"
      <advisable includeMethods="" excludeFields=""/> etc...
      * metadata models annotations
      * metadata uses XMLBeans
      * Metadata pointcut
      
      <metadata-pointcut group(required), attr?, class?, instanceof?, methodName?, field?> All other ones can just
      
      * Overriding
      <metadata-pointcut name="JBoss Default Transaction Demarcation" group="Transaction" attr="trans-attr">
       <interceptors>
       <interceptor ...>
       </interceptors>
      </metadata-pointcut>
      
      <exclude-pointcut pointcut="JBoss Default Transaction Demarcation"
       instanceof="!..."
       methodName="..."
       field="..."
       constructor="..."/>
      <include-pointcut pointcut="JBoss DefaultTransaction Demarcation"/>
      
      Attributes (instanceof, methodName, field, etc...) are logically ANDed.
      
      * instanceof
      * Control flow
      <control-flow name="..">
       <flow class="..." methodName="..." fieldAccess"/>
       <flow class="..." methodName="..." fieldAccess"/>
       <flow class="..." methodName="..." fieldAccess"/>
      </control-flow>
      
      <something-pointcut cflow="name">
       <interceptors/>
      </somethignj-pointcut>
      <somethign-pointcut>
       <control-flow>
       ...
       </control-flow>
      </something-pointcut>
      
      * Introduction breakout
      
      <introduction name="...">
      
      <class-pointcut>
       <interceptors>
       <introduction-ref>
      </class-pointcut>
      
      * Better classloader integration (bootclasspath thingy), maybe HotSwap, but not a priority
      
      ASPECTS AOM:
      
      * Add Tx Exception configuration. What exceptions cause a rollback, which do not?
      * instnace API should support per method/field additions
      * Add Dynamic Proxy support for AOP Remoting. All interfaces of remoted class or interfaces you want to be remoted. Also wrap remote exceptions as runtime exceptions.
      * synchronized aspect to add synchronization to any instance.
      * AOP Cache should add a synchronization interceptor before preparing object for cache so that we can make sure object doesn't change while we are preparing it.* Attribute compiler (JSR-175 for JDK 1.4) Maybe, maybe not
      
      


        • 1. Re: New AOP stuff going on.
          rythos

          On the subject of control flow, don't forget cflowbelow. Aspectwerkz implemented cflow, but no below. In my limited experience cflowbelow is almost more useful than cflow. Picking out non-recursive calls to certain things is very handy. (Also, once you have cflowbelow, cflow is pretty easy to implement from there.) I did an implementation of cflow for plain java code, and once the private methods were done it looked like:

          public boolean cflow() {
           privateCFlowMethod( 1 );
          }
          
          public boolean cflowbelow() {
           privateCFlowMethod( 2 );
          }
          


          Where the numbers are where to start looking on the stack trace.

          • 2. Re: New AOP stuff going on.
            bill.burke

            can you explain control flow below more?

            • 3. Re: New AOP stuff going on.
              marc.fleury

              this is great stuff

              we need you to do a BLOG entry about this to give some visibility and order on the forums posts

              • 4. Re: New AOP stuff going on.
                rythos

                Absolutely. (I use the AspectJ terms because that's how it's easiest to explain). It's very similar to cflow. The cflow( methodCall ) is true if when you do the check, there is a call to methodCall somewhere in the stack trace. The cflowbelow( methodCall ) is true if when you do the check, there is a call to methodCall somewhere in the stack trace that *is not the top most element*. An example will help.

                public class Quicksort {
                 public static void main( String[] args ) {
                 new Quicksort().quicksort( ..... );
                 }
                
                 public void quicksort( int[] numbers, int p, int r ) {
                 if( p < r ) {
                 int q = partition( numbers, p, r );
                 quicksort( A, p, q );
                 quicksort( A, q + 1, r );
                 }
                 }
                
                 // rest of quicksort here
                }
                
                public aspect QuicksortAspect {
                 pointcut callsToQuicksort():
                 call( public void Quicksort.quicksort( int[], int, int ) );
                
                 pointcut nonRecursiveCalls():
                 callsToQuicksort() && !cflowbelow( callsToQuicksort() );
                
                 pointcut neverGetsCalled():
                 callsToQuicksort() && !cflow( callsToQuicksort() );
                
                 // this only gets called before the call to quicksort in main
                 before(): nonRecursiveCalls() {
                 System.out.println( "nonrecursive call to quicksort" );
                 }
                
                 before(): neverGetsCalled() {
                 System.out.println( "This never happens." );
                 }
                }
                


                The idea being that callsToQuicksort() picks out every time there is a call to Quicksort.quicksort(), and that !cflowbelow( callsToQuicksort() ) checks the current stack trace to see that excluding the top element, there are no other calls to quicksort having been made. If you included the top element, then you are looking for a call to quicksort which doesn't have a call to quicksort anywhere, which can't happen. I've never seen it used in any other way than to look for non-recursive calls to something, but I'm sure other uses exist.

                My apologies again for the AspectJ code, it seemed the best way :). Hope that all makes sense. Please ask away if it doesn't.

                Craig

                • 5. Re: New AOP stuff going on.
                  bill.burke

                  FYI, for above couldn't it be solved by a caller pointcut in JBoss AOP? Where withClass would be !(Quicksort)

                  ?

                  • 6. Re: New AOP stuff going on.
                    rythos

                    Yeah, you are right in this example. My motivating example wasn't very motivating. :) AspectJ best practices recommends using cflow and cflowbelow as little as possible. In fact the Sable paper I mentioned in my e-mail (http://www.sable.mcgill.ca/publications/techreports/sable-tr-2003-8.pdf) used cflow in their implementation of Quicksort, which as you just pointed out was not necessary and can be done with a static check, as opposed to the horridly dynamic cflow check.

                    public aspect DisplayUpdating {
                     pointcut move(): call(void FigureElement.moveBy(int, int)) ||
                     call(void Point.setX(int)) ||
                     call(void Point.setY(int)) ||
                     call(void Line.setP1(Point)) ||
                     call(void Line.setP2(Point));
                    
                     after() returning: move() && !cflowbelow(move()) {
                     Display.needsRepaint();
                     }
                    }
                    
                    public interface FigureElement {
                     public void moveBy( int i1, int i2 );
                    }
                    
                    public class Point implements FigureElement {
                     public void moveBy( int i1, int i2 ) {
                     }
                     .....
                    }
                    
                    public class Line implements FigureElement {
                     public void moveBy( int i1, int i2 ) {
                     p1.moveBy( i1, i2 );
                     p2.moveBy( i1, i2 );
                     }
                     ....
                    }
                    


                    In this case you have a little more complex control flow. Line.moveBy(int, int) calls Point.moveBy(int, int) for each point in contains, so trying to do a within for each different case becomes a small nightmore.

                    • 7. Re: New AOP stuff going on.
                      bill.burke

                       

                      "rythos" wrote:
                      Yeah, you are right in this example. My motivating example wasn't very motivating. :) AspectJ best practices recommends using cflow and cflowbelow as little as possible. In fact the Sable paper I mentioned in my e-mail (http://www.sable.mcgill.ca/publications/techreports/sable-tr-2003-8.pdf) used cflow in their implementation of Quicksort, which as you just pointed out was not necessary and can be done with a static check, as opposed to the horridly dynamic cflow check.

                      [snip[
                      In this case you have a little more complex control flow. Line.moveBy(int, int) calls Point.moveBy(int, int) for each point in contains, so trying to do a within for each different case becomes a small nightmore.


                      Still, I'd rather have a complex within statement rather than CFLOW any day as CFLOW's overhead is just too huge.

                      Bill

                      • 8. Re: New AOP stuff going on.

                        I have 2 questions regarding the lastest code from CVS
                        that I am currently testing.


                        1/How to define a caller pointcut as follows

                        I want to intercept every instanciation of the constructor
                        of the class A when it's called within method B or constructor B

                        2/How can I get information of the caller class within the Interceptor
                        class ?

                        Thx-Claude

                        • 9. Re: New AOP stuff going on.
                          bill.burke

                          although the grammar support call(constructor...) I haven't implemented it yet. I hope to get to it before the release. If you're interested in implementing let me know.

                          Bill

                          • 10. Re: New AOP stuff going on.

                            I have looked at how to answer to my second question (The easiest one ;-))

                            The class advised for a Caller pointcut is the calling class.
                            I didn't find a way to get a handle on this class within the implementation of
                            the Interceptor.So ,by adding the following code within the invokeCaller
                            method from the ClassAdvisor class ,I am solving my problem.

                            // New field added within the CallerInvocation class.
                            invocation.callingClass = this.clazz;

                            Then ,to get information on the calling class ,we just need to
                            call the following static method in the Interceptor implementation

                            Method callingMethod =MethodHashing.findMethodByHash(methodInvocation.callingClass,methodInvocation.callingMethodHash);

                            let me know what u think.

                            Thx-Claude

                            • 11. Re: New AOP stuff going on.
                              bill.burke

                              That is correct. I'll add this to DR3 when I get a chance.

                              Bill