Aspect-Oriented Programming (AOP) is successful to modularize crosscutting concerns such as Logging, Profiling, Security, among others. The Pointcut/Advice mechanism is the most emblematic in AOP. Pointcuts are predicates that represent join points where an advice is executed. An advice is a function that can be classified as Generic or Non-Generic. For example:

aspect Profiling{
 
  Object around(Object thiz) : execution(* *(..)) && this(thiz){ //Generic advice
    Object rt;
    float start = Utils.datetime.now();
    rt = proceed(thiz);
    Utils.out(Utils.getName(thiz),Utils.datetime.now()-start);
    return rt;
  }
}

You might notice that the above advice can work uniformly over whatever type that thiz takes. This means that the body's advice does not use any type information about thiz to work properly. So, we can say that this advice is a Generic Advice. Notice that, for now, we use the type Object as a wildcard to say for all types (This will be fix when we use types variables).

The usefulness of Generic Advice has been demonstrated and discussed in the AOP community [1], [2] . For that reason, we think that Join Point Interfaces (JPI) must support this feature in its second version. In this document, we show how we can provide Generic Advice by means of the implementation of JPI overloading and Parametric Polymorphism in our compiler extension.

  • JPI overloading: The same symbol represents different advice(function) implementations. With this feature we can define JPI definitions with the same name but with different parameter types. Notice that each JPI definition will represent a different kind of join point.
  • Parametric polymorphism: The same value can be viewed as having different forms. This means that we can define advice declarations regardless of arguments or return type. The advice's body do not need the type information of its arguments or return value to work properly.

Also, it is important to implement Invariant pointcuts designators (PCDs) in order to stay invariant when the join points are selected.

  • Invariant PCD: args, this, target are PCDs that expose the context of the selected join point. In AspectJ when an identifier is used with this PCDs, join points are selected in a covariant way (based on the type of the identifier). To follow our jpi semantic, we need to define new PCDs that select join points in a invariant way, e.g.: argsInv, thisInv, targetInv.

Motivation

In order to validate our first proposal of Join Point Interfaces, we migrate two applications: AJHotDraw and LawOfDemeter. AJHotDraw uses aspects to implement commands functionality such as: UndoCommand, PasteCommand, among others. LawOfDemeter uses aspects to capture every single activity that occurs in the base code, such as: Method call, field write, object initialization, among others.

Interestingly, those applications define a very different kind, in the sense of their generality, of pieces of advice. AJHotDraw defines very specific pieces of advice, i.e.: the body's advice definition depends completely on the type of its arguments. By contrast, LawOfDemeter defines very generic pieces of advices, i.e.: the body's advice definition does not depend on the type of its arguments.

Once the migration was finished, we come up with the conclusion that our proposal is well-behave in presence of specific advices, but it is too verbose in presence of generic advices. To show this fact we introduce the following table.

Q. of advice
Original JPI version
AJHotDraw ? ?
LawOfDemeter ? ?

This table shows the quantity of advice declarations in both scenarios: original and migrated application. Notice how the quantity of pieces of advice in the migrated version is increased by the generality of pieces of advice.

The problem with generic advice is raised due to our semantics. We constrain that each join point that is bounded with a JPI definition must be type invariant (return and arguments) respect of the JPI definition. This condition causes repeated advice definitions to implement only one desired feature. For example:

jpi Integer MyJPI(C c);
jpi Float MyJPI2(D d);
 
class C{
 
  exhibits Integer MyJPI(C c) : 
    execution(* *(..)) && this(c);
 
  public Integer doSomething(){...}
}
 
class D{
 
  exhibits Float MyJPI2(D d) :
    execution(* *(..)) && this(d);
 
  public Float doSomething(int a){...}
}
 
public class Main{
 
   public static void main(string[] args){
      C c = new C();
      D d = new D();
      c.doSomething();
      d.doSomething(5);
   }
}
 
aspect ProfilingJPI{ //JPI syntax
 
  Integer around MyJPI(C thiz){
    Object rt;
    float start = Utils.datetime.now();
    rt = proceed(thiz);
    Utils.out(Utils.getName(thiz),Utils.datetime.now()-start);
    return rt;
  }
 
  Float around MyJPI2(D thiz){
    Object rt;
    float start = Utils.datetime.now();
    rt = proceed(thiz);
    Utils.out(Utils.getName(thiz),Utils.datetime.now()-start);
    return rt;
  }
}

Consider now, that we add in main method a method invocation belonging to other class named E. To select this join point we need to define an extra advice definition. This advice definition must contain the following:

  • the same body definition of the other pieces of advices, and
  • A formal parameter called thiz with E as its type.

Related Work

  • Introduction
  • StrongAspectJ
    • types variables
    • double proceed signature
    • modification in PCDs semantics.
    • Problems with double proceed signature.
    • ClassCastException with interfaces.
  • work of Jagadeesan et al.
    • generic types
    • demonstrate that generic advice is useful

New features

In this section we show in detail how the new features solve our current problems and how we will implement them.

References

[1] R. Jagadeesan, A. Jeffrey, and J. Riely. Typed parametric polymorphism for aspects. Science of Computer Programming, 63(3):267-296, 2006.

[2] B. De Fraine, M. Südholt, and V. Jonckers. StrongAspectJ: Flexible and Safe Pointcut/Advice Bindings. Conf. on Aspect-Oriented Software Development (AOSD-2008).