GluonJ 2005 Language References


Overview

Glue code specifies how an aspect implementation is associated with aspect targets. Aspect implementations are regular Java objects, which implement a crosscutting concern. They corresponds to an aspect instance in AspectJ. In contract to AspectJ, GluonJ separates aspect bindings from aspect implementations. Glue code is for describing the aspect binding. Here is the example of glue code.

<glue>
    <reference>
        Logger MyBusinessTask.aspect = new Logger();
    </reference>
    <behavior>
        <pointcut>
             execution(* MyBusinessTask.*(..))
        </pointcut>
        <after>
             Logger.aspectOf(this).log();
        </after>
    </behavior>
</glue>

Glue code is written in XML. The root element of glue code must be the glue tag. There are two important tags under the glue tag, which are the reference tag and the behavior tag.

Reference tag

The reference tag enables to write the field declaratation and the field intialization seperating from the existing classes.

<reference>
    Logger MyBusinessTask.aspect = new Logger();
</reference>

The statement surrounded with the reference tag specifies a connection between a MyBusinessTask object and a Logger object. It means that, when a MyBusinessTask is constructed, a Logger object is also constructed and then associated with that MyBusinessTask object.

The syntax of this statement is the same as the intertype field declaration in AspectJ except "aspect" is not a field name but a special keyword. the field which name is aspect, becomes an anonymous field, that is, a field that has no name. The anonymous fields are the language mechanism for avoiding naming conflict. When the anonymous field are weaved to target classes, the name of it is chosen automatically not to conflict the name of the existing fields. You can access the anonymous fields using special accessor method, aspectOf. The usage of aspectOf is shown at the next section.

You can write the field name except aspect. In this case, the field which has the specified name is newly added.

<reference>
    Logger MyBusinessTask.logger = new Logger();
</reference>

The reference tag also enables to initialize an existing field. If the specified field name is the same as an already existing field in the same class, a new field is never added to the class. Initializing is only done.

Behavior tag

The behavior tag enables to write the code fragment of calling methods seperating from existing classes.

<behavior>
    <pointcut>
        execution(* MyBusinessTask.*(..))
    </pointcut>
    <after>
        Logger.aspectOf(this).log();
    </after>
</behavior>

There are two tags under the behavior tag, which are the pointcut tag and the after tag. The after tag specifies the method which is called at an aspect target and the pointcut tag specifies the joinpoints when the method is called. The syntax of the pointcut tag is almost same as the pointcut of AspectJ.

The code fragment surrounded by after tag is written in regular Java except a special method "aspectOf" is available in that code fragment. aspectOf is the accessor of anonymous field. In the aspect shown above, Logger.aspectOf(this) is used to obtain the Logger object associated with the MyBusinessTask object referred to by this. The signature of aspectOf is the follows:

static <class name> <class name>.aspectOf(<object>)

This aspectOf method returns the object that is of the <class name> type and is associated with the given <object>. aspectOf method is automatically added at weaving process if the anonymous field is declared at the reference tag. aspectOf method can be accessed only from statements surrounded by the behavior tag.

Details

Reference tag

The expression which initializes the field is written in regular Java except a special variable $this is available. $this refers to the object at which declaring the field. At below example, $this refers to the Logger object.

<reference>
    Logger MybusinessTask.aspect = new Logger($this);
</reference>

Association with control flow

An anonymous field can be added to an object representing a control flow specified by the cflow pointcut designator. This mechanism is useful to obtain similar functionality to a percflow aspect instance in AspectJ. To declare such a field, the aspect should be something like this:

<reference>
    Logger Cflow(call(* MyBusinessTask.*(..)).aspect
        = new Logger();
</reference>

An anonymous field is added to an object specified by Cflow. It represents a control flow from the start to the end of the execution of a method in MyBusinessTask. It is automatically created while the program execution in that control flow. To obtain the value of this anonymous field, aspectOf must be called with the $thisCflow special variable. For example,

Logger.aspectOf($thisCflow).log();

aspectOf returns the Logger object stored in $thisCflow. $thisCflow refers to the Cflow object representing the current control flow.

Association with a group of objects

An anonymous field can be used to associate a group of objects with another object. This mechanism provides similar functionality to the association aspects. For example,

<reference>
    Logger MyBusinessTask.aspect(Session) = new Logger($this, $arg0);
</reference>

This declaration associates multiple Logger objects with one MyBusinessTask. $this and arg0 are special variables. These Logger objects are identified by a Session object given as a key. The type of the key is specified in the parentheses following aspect. Multiple keys can be specified. The associated objects are obtained by aspectOf. For example,

<after>
    Logger.aspectOf(task, session).log();
</after>

This statement calls the log method on the Logger object associated with a combination of task and session. aspectOf takes two parameters: the first parameter is a MyBusinessTask object and the second one is a Session object. aspectOf returns an object associated with the combination of these objects passed as parameters. If any object has not been associated with the given combination, aspectOf constructs an object and associates it with that combination. In other words, an associated object is never constructed until aspectOf is called.

In the case of the example above, a Logger object is constructed with parameters $this and $arg0. $this refers to the first parameter to aspectOf (i.e. the MyBusinessTask object) and $arg0 refers to the second parameter. If more than two objects are used as keys, Other variables are available such as $arg1 and $arg2.

Add a new method

The reference tag also makes possible to add a new method to existing classes. If method declaration is written in the reference tag, that method is newly added. The syntax of the method declaration is almost same as AspectJ's inter-type declaration. For example, the following reference tag adds pow method to Counter class.
<reference>
    static int Counter.pow(int i) {
       return $1 * $1;
    }
</reference>
$1 means the first parameter i. The parameter name at method signature is not available because of the limitation of GluonJ weaver.

Behavior tag

The behavior tag can have pointcut parameters like AspectJ's advices. The pointcut parameter is specified by param tags. For example, the following behavior tag uses a String parameter query . It is available in the pointcut and the code fragment under the behavior tag.

<behavior>
    <param>
        <name> query </name>
        <type> String </type>
    </param>
    <pointcut>
        execution(* MyBusinessTask.search(..)) AND args(query)
    </pointcut>
    <after>
        Logger.aspectOf(this).log(query);
    </after>
</behavior>

The body of behavior tag can be before, after and around . Any Java statement can be specified as the body although the &, < and > operators must be escaped since an advice body is written in an XML file.

In advice body, the special method aspectOf() and variables which refer to context information are available. Those variables are follows as the variables supported by Javassist. For example, $0 and $class .

In the statement of an around tag, $_ variable is available to change the return value of behavior. return statement cannot be used.

Supported Pointcuts

GluonJ supports the pointcut designators at the table below.

Name and Signature
execution(behavior-pattern)
call(behavior-pattern)
set(field-pattern)
get(field-pattern)
within(class-pattern)
withincode(behavior-pattern)
this( type or id )
target( type or id )
args( types or ids )
cflow( pointcut )

AND and OR pointcut are available instead of && pointcut and || pointcut.

The syntax of the behavior pattern and the field pattern is a little different with the syntax of AspectJ's pointcut. If you want to write the wildcard (*) at the return type or the declaring class, you must write the "%" mark between them. This is because a parser limitation of GluonJ.

execution(* % *.open(..)), execution(void % *.open(..)),  execution(* % Socket.open(..))

Pointcut-Decl tag

An pointcut-decl tag makes possible to declare a new pointcut designator by conbining existing pointcut designators. This is almost same as AspectJ's pointcut declaration. For example, the following glue code declares a new pointcut designator named execService.
<glue>
    <pointcut-decl>
        <name> execService </name>
        <param>
            <name> message </name>
            <type> String  </type>
        </param>
        <pointcut>
            execution(void MyBusinessTask.*(..)) AND args(message)
        </pointcut>
    <pointcut-decl>
    ...
<glue>

Import tag

Import tags make possible to omit the package name of classes in the pointcut expression, the body of behavior tags and the method body declared in reference tags. The omision is valid at all expressions in the glue code where the import tag is written. For example, the following glue code imports the java.util package to omit the package name of java.util.List class at the pointcut expressions in the behavior tag.
<glue>
    <import> java.util </import>
    <behavior>
        <pointcut>
            call(* List.add(..)) AND within(MyBusinessTask)
        </pointcut>
       ...
    </behavior>
</glue>

Weaver

Static Weaver

The static weaver of GluonJ is gluonj.Gjc class. gluonj.jar and javassist.jar are needed to run this. This is command line weaver.

usage: [-classdir dirs] [-injar jarfiles] [-classpath pathes] [-includes patterns] [-dest path] [-outjar jarfile] glue1 glue2 ...
Options Functions
-classdir directories directories specify the root directories where class files to be translated are. The separator of directory is File.pathSeparator.
-injar jarfiles jarfiles specify the jar files where class files to be translated are archived. The separator of directory is File.pathSeparator.
-includes patterns patterns specifies the name of classes which are to be translated. For examples, myclass/Foo, ** or test/**/Test* .
-classpath pathes pathes are used as classpath when compiling and weaveing class file and code fragments in glue codes. The separator of directory is File.pathSeparator.
-dest directory directory specifies the root directory which generated classes are written at. The default is current directory.
-outjar jarfile jarfile specifies the jar file which generated classes are archived in. If both of -outjar option and -dest option are given, -outjar option is used.

GluonJ also provides the static weaver as Ant task. The class name of the Ant Task is gluonj.tool.GjcTask. This Ant task has same options. The following example is a part of the build file which uses this Ant task.

  <taskdef resource="gluonj/tool/gluonjTaskdefs.properties">
    <classpath location="bin" />
    <classpath refid="tools.classpath" />
  </taskdef>

  <target name="compile-gj">
    <gjc classdir="./bin" includes = "*/weaver/**/A;*/weaver/Counter"
        outjar="./temp/counter_new.jar" injar="./test/test/weaver/counter.jar">
      <fileset dir=".">
        <include name="test/**/weaver/aop.xml" />
      </fileset>
    </gjc>
  <target>

Weaver for JBoss

GluonJ prvoides the load time weaver for the applications executed on Jboss application server. This weaver weaves the code in glue code to the class file in deployed Java application. This weaver makes possible to change the behavior of the application on JBoss without recompiling it because class files are changed by class loader when they are loaded. Modifying the class loader used in JBoss or using a special JVM are also not needed since this weaver uses the class file translation mechanism which is provided by class loader of Jboss. This weaver is assumed to use with JBoss 4.0.2.

If you want to use this weaver, please copy gluonj-deployer.sar to deploy directory of running JBoss and deploy it. After that, when the zip file named "*.glue" is deployed, this weaver read this file, extract the "/META-INF/glue.xml" from this archived file and set the information in it to the class loader of JBoss. "/META-INF/glue.xml" is a glue code. If you use other classes at the code fragment in glue code, please archive them together in "*.glue". After that, when the application is deployed, classes in that application are translated by the class loader of JBoss following to the information of deployed glue code.


[Last Updated: Mar. 14, 2006]

Ishikawa Rei
rei@csg.is.titech.ac.jp