Sunday, October 30, 2005

Generating Sequence Diagrams Using AspectJ

Over the past couple weeks a few people have inquired about a demo I wrote a few years ago named jAdvise SEQUENCE. It combined my old AOP framework with SEQUENCE, Alex Moffat's sequence diagram generator. In the demo, a simple method interceptor generated a SEQUENCE data file. The idea is you need runtime information to generate complete sequence diagrams. Rather than perpetuate retired code, I've implemented a more robust version using AspectJ. Pardon me as I go out on a limb here and risk confusing you by using two AOP frameworks at once. As an example, we'll generate a sequence diagram for a Dynaop mixin method invocation. The following code mixes a Bar implementation into Foo and invokes a couple methods on the resulting object. We'll generate a sequence diagram of the last invocation.
import dynaop.*;

public class MixinExample {

  public abstract static class Foo implements Bar {
    public void foo() {}
  }
  
  public interface Bar {
    void bar();
    void tee();
  }
 
  public static class BarMixin implements Bar {
    public void bar() {}
    public void tee() {}
  }
  
  public static void main(String[] args) {
    // configure proxy factory.
    Aspects a = new Aspects();
    a.mixin(
      Pointcuts.singleton(Foo.class),
      BarMixin.class,
      null
    );
    ProxyFactory pf = ProxyFactory.getInstance(a);

    // create an instance of Foo that
    // delegates to BarMixin.
    Foo foo = (Foo) pf.extend(Foo.class);
    foo.foo();
    foo.bar();
    foo.tee();

    Sequence.start();
    foo.tee();
    Sequence.stop();
  }
}
The Sequence aspect hooks every method and dumps the SEQUENCE diagram data to standard out. Simply capture the output and open it in SEQUENCE.
import org.aspectj.lang.*;
import dynaop.*;

public aspect Sequence {

  static boolean running;
  
  pointcut traceMethods()               
    : (execution(* *.*(..))
        || execution(*.new(..))) 
      && !execution(* *.*$*(..)) 
      && !within(Sequence)
      && if(running)
      
      // omit problematic inner classes.
      && !within(Pointcuts.*)
      && !within(ProxyFactory.*)
      && !within(ClassProxyCreator.*);

  before() : traceMethods() {
    Signature s = 
      thisJoinPointStaticPart.getSignature();     
    String methodName = s.getName();

    // use "new" for constructors.
    if (methodName.equals(""))
      methodName = "new";
    
    System.out.println(
      s.getDeclaringType().getSimpleName() 
        + "."  + methodName + " {");                    
  }
  
  after() : traceMethods() {
    System.out.println("}");
  }

  public static void start() {
    running = true;
  }
  
  public static void stop() {
    running = false;
  }
}
To include or exclude classes and methods from the diagram, tweak the pointcut accordingly. Our example generates this diagram:
If Alex adds support for notes or diagram annotations to SEQUENCE, this could put an interesting twist on log file analysis. I used Dynaop 1.0 beta for this example. It will be interesting to compare the before and after diagrams when I release the upcoming performance enhancements and refactorings.

8 Comments:

Blogger paul browne said...

Another Killer Application for Aspects!

Aspects are strange in that you can get along most of the time without them , but when you really need them you're glad that they are there. This is one of those times - ideal for an application that is too 'heavy' to profile but you need to see the internals better.

For info, the other 'killer' app for Aspects is Security code, but I'm bound to be corrected on this...

Paul
FirstPartners.net

12:54 PM  
Anonymous Anonymous said...

When I compiled and ran this example. I only got following:

MixinExample$BarMixin.tee {
}

The only change I made was to
s.getDeclaringType().getSimpleName()
with s.getDeclaringTypeName() because
getDeclaratingType() returns Class and
it has getName(), but not getSimpleName() method.

Thanks in advance.
Regards,
Shahzad

5:19 PM  
Blogger Bob said...

You have to run the Dynaop jar through the AspectJ compiler, too.

If you use the beta release like I did, you have to remove the dynaop.remote package from the jar manually (or maybe you can exclude it in the pointcut?) because it has an errant import.

Go ahead and run it on your own program. It's much more interesting. ;)

5:28 PM  
Anonymous Anonymous said...

Thanks Bob! As you know, we have released our first commercial product using AOP that provides transparent auditing for J2EE applications. So, hopefully it will also be a killer app :) Check out www.intelliprints.com for more info.

6:01 PM  
Blogger Swetha said...

hello sir,
i am a final year Computer Science and Engineering student doing my project on "Reverse Engineering of Aspect Oriented Programming".My aim is to bring the static(class) diagram and dynamic(sequence)diagram from the aspectJ code.I am half way through the process of developing a parser which generates the class diagram by using the aspectJ syntax and semantics and i am writing the code in Java.It would be of great help if you could give me some ideas for generating the sequence diagram.

9:03 AM  
Blogger Bob said...

You have all the source code. What more do you need?

9:43 AM  
Blogger JiMe εїз said...

hi.. i was trying to find a way to do the evaluation of a sequence diagram.. and well.. I found your page.. and i see you are an expert on this ASPECTJ ... could you tell me if it can make any king of evaluation or review to a sequence diagram??or maybe you know any program who can make it ??... i will really apreciate your help!

8:13 PM  
Blogger Unknown said...

Can we make this work on binaries.. i.e., without touching any java files. From whtever i understood we need to create instances like to make this work ?
ProxyFactory pf = ProxyFactory.getInstance(a);
Foo foo = (Foo) pf.extend(Foo.class);
Am I right ? Suppose if i want to create the sequence diagrams all the methods in my application do i need to create the objects as above. IS there anyway to make this work withou altering the current code i have ?

1:45 AM  

Post a Comment

<< Home