Damon : a Distributed AOP Middleware on top of a p2p Overlay Network

Last Updated: 10 July 2008
P2PGRID Project Page AST Research Group Damon Sourceforge Project Bunshin   

Installation and Compilation

Damon distribution comes in the form of source code and a precompiled binary JAR package. The downloadable version consists of a ZIP file which should be extracted to any directory. Damon comes with a set of samples and JUnit testbed which can be executed to proof Damon's skills.

To execute these samples, you need at least Java5 JRE v1.6.0. You will experience problems if you use prior versions because the annotation functionalities were not available until JDK 1.5. However, for run all instrumentation capabilities, it must be work over Java6.

If you want to compile the sources, make sure you have installed Jakarta ANT. You must change to the ./bin directory in your Damon installation directory and execute the following command:

ant

The next step is to edit the damon-config.xml file located at the ./bin directory, and change the parameters concerning bootstrap host, port, aspect framework to use, etc.

 

Running the sample applications

There is a binary precompiled damon.jar file contained in the ./lib directory which you should include in the applications willing to use Damon.

Damon contains several sample applications which demonstrate and test all of the functionalities in the middleware.

The instructions for running the different included samples are as follows:

  • Direct abstraction sample (damon.tutorial.direct)

    This sample includes a simple sample. It demonstrates the activation using direct abstraction.

    1) Open a shell and run the host.

    • run damon.tutorial.direct.SimpleHost

    2) Open a shell and run the deployer.

    • run damon.tutorial.direct.SimpleDeployer

     

  • Distributed Meta-Aspect sample (damon.tutorial.metapointcut)

    This sample includes a distributed meta-aspect over the simple sample. It tests the before, after, and around distributed meta-pointcuts.

    1) Open a shell and run the host.

    • run damon.tutorial.metapointcut.SimpleHost

    2) Open a shell and run the deployer.

    • run damon.tutorial.metapointcut.SimpleDeployer

 

  • XML sample (damon.tutorial.xml)

    This sample includes a simple sample. It demonstrates the use of xml descriptor instead of annotations.

    1) Open a set of shells and run the host.

    • run damon.tutorial.xml.simple.SimpleHost

    2) Open a shell and run the deployer.

    • run damon.tutorial.xml.simple.SimpleDeployer

     

 

 

Developer's guide

If you wish to code your aspects taking advantage of Damon services, you should follow these simple steps:

  • Add the corresponding annotation to aspect's classes :
import damon.annotation.*;

 

@DistributedAspect (abstraction = Abstractions.MULTI, target = "p2p://chat.urv.cat")
public class DamonAspect {

@SourceHook(source = "damon.samples.multihost.log.SourceHooks", method = "preloadedCheck")
public Object aroundTask(JoinPoint joinPoint) throws Throwable {

...

}

Damon's annotations are explained in the next table :

Distributed Aspect and Activation

Annotation / Variable

Type

Definition

@DistributedAspect

Class

Defines the kind of Damon distributed aspect properties and activation

abstraction

Value

Determinates the abstraction type. We can choose among local, direct, hopped, any, many or multi ones.

num

Value

Only for many abstraction, where we can specify the number of involved hosts.

target

Value

peer-to-peer locator associated to specific host or group of host

@DamonRequirement Method Only in any/many abstraction, this annotation can mark methods that return boolean values. When we activate an aspect with requirements, the container uses them to determinate if the host is successful to install it.

 

  • In any/many abstraction, we can add a set of requirements to select the host to intercept using the DamonRequirement annotation:
import damon.annotation.*;

 

@DistributedAspect (abstraction = Abstractions.ANY, target = "p2p://calc.urv.cat")
public class DamonAspect {

@DamonRequirement
public boolean checkHasFreeResources() {

...

}

Source Hook

Annotation / Variable

Type

Definition

@SourceHook

Method

Defines the source hook local interception

source

Value

pointcut definition class

method

Value

local advice method

 

Remote Pointcut

Annotation / Variable

Type

Definition

@RemotePointcut

Method

Defines the remote pointcut properties and propagation

id

Value

remote pointcut unique identifier

abstraction

Value

Determinates the abstraction type. We can choose among local, direct, hopped, any, many or multi ones.

num

Value

Only for many abstraction, where we can specify the number of involved hosts.

target

Value

peer-to-peer locator associated to specific host or group of host

 

Remote Advice

Annotation / Variable

Type

Definition

@RemoteAdvice

Method

Defines the remote advice subscription

id

Value

subscribed remote pointcut unique identifier

 

Remote Invocation

Annotation / Variable

Type

Definition

@RemoteInvocation

Method

Defines the remote invocation properties and propagation

id

Value

remote invocation unique identifier

abstraction

Value

Determinates the abstraction type. We can choose among local, direct, hopped, any, many or multi ones.

num

Value

Only for many abstraction, where we can specify the number of involved hosts.

target

Value

peer-to-peer locator associated to specific host or group of host

 

Remote Method

Annotation / Variable

Type

Definition

@RemoteMethod

Method

Defines the remote method subscription

id

Value

subscribed remote invocation unique identifier

  • To use the aspect remoting services your distributed aspect must extend from AspectRemoting. Moreover, to start the invocations you can use the invoke parent primitive.

@DistributedAspect (abstraction = Abstractions.MULTI, target = "p2p://clockstation.urv.cat")
public class
SynchroImpl extends AspectRemoting {

private Hashtable<String,Long> times = new Hashtable<String,Long>();

@RemoteAdvice (id = "time")
public void valueArrived(RemoteJoinPoint rjp, Long value) {
    times.put(id,vale);
}

@RemotePointcut (id = "time", abstraction = Abstractions.MULTI)

@SourceHook(source = "damon.samples.invokation.synchro.SourceHooks", method = "getTime")
public Object aroundTask(JoinPoint joinPoint) throws Throwable {


    long time = ((Long) joinPoint.proceed()).longValue();
    invoke(Abstractions.MULTI, new Long(time));
    Collection<Long> c = new Vector<Long>(times.values());
    long avg = 0;
    for(Long l : c) {
        avg+= l;
    }
    if (c.isEmpty()) return time;
    else {
        avg = avg/(c.size());
        return new Long(avg);
    }
}

}

  • Furthermore, to use the other services, like reflection layer or persistence system, you must call the thisEndPoint static object methods.
  • The alternative, in order to allow composition in runtime, is the use of equivalent XML descriptors. As follow we present an esqueletor :

<distributed-aspect>
          <name> </name>
          <abstration> </abstraction>
          <target> </target>
          <state> </state>
          <offered>
                    <name> </name>
                    <type>remote-pointcut</type>

                    <sourcehook>remote-pointcut

                          <source></source>                   

                          <method></method>                   

                    </sourcehook>
                    <id> </id>
                    <abstraction> </abstraction>
          </offered>
          <offered>
                    <name> </name>
                    <type>remote-invocation</type>
                    <id> </id>
                    <abstraction> </abstraction>
          </offered>
          <required>
                    <name> </name>
                    <type>remote-method</type>
                    <id> </id>
          </required>
          <required>
                    <name> </name>
                    <type>remote-advice</type>
                    <id> </id>
          </required>
          <meta-pointcut>
                    <name> </name>
                    <time> </time>
                    <target> </target>
                    <id> </id>
          </meta-pointcut>
</distributed-aspect>

 

Remote Meta-Pointcut

Annotation / Variable

Type

Definition

@RemoteMetaPointcut

Method

Defines the distributed meta-pointcut hook

id

Value

subscribed remote pointcut unique identifier

type

Value

The moment of the interception : Before, After or Around.

target

Value

peer-to-peer locator associated to specific host or group of host

Remote Meta-Advice

Annotation / Variable

Type

Definition

@RemoteMetaAdvice

Method

Defines the remote invocation properties and propagation

id

Value

remote invocation unique identifier

abstraction

Value

Determinates the abstraction type. We can choose among local, direct, hopped, any, many or multi ones.

num

Value

Only for many abstraction, where we can specify the number of involved hosts.

target

Value

peer-to-peer locator associated to specific host or group of host

 



HOW TO USE Damon WITH OTHER Dynamic AOP Frameworks?

An aspect framework adaptation layer has been created in Damon, so as it can be easily adapted to different dynamic AOP frameworks. In our case, we have implemented Damon over AspectWerkz 2.0. In order to make Damon compatible with another runtime aspect engine, you must implement a series of classes, which are detailed as follows, showing Aspectwerkz's example:

 

Package Class Details
damon.aspectwerkz HotDeployment

DocumentCreator

AnnotationSwapper

org.codehaus.aspectwerkz.transform.inlining.deployer.Deployer;

org.codehaus.aspectwerkz.transform.inlining.deployer.DeploymentHandler;

org.codehaus.aspectwerkz.annotation.*;

damon.invokation.aspectwerkz AspectInvokeObserver

AspectRemoting

org.codehaus.aspectwerkz.definition.Pointcut;
org.codehaus.aspectwerkz.joinpoint.JoinPoint;
damon.metaaspect.aspectwerkz DistributedMetaAspect

MetaPointcutObserver

org.codehaus.aspectwerkz.definition.Pointcut;
org.codehaus.aspectwerkz.joinpoint.JoinPoint;

 

Finally, the package names must follow the same template. For example, in our case we wanted to support Damon on top of Aspectwerkz, we would implement the classes in packages as for example: damon.aspectwerkz or damon.messaging.aspectwerkz.

In order to use Damon with other dynamic aspect framework, you must specify the package name (aspectwerkz in our case) in the different configuration files we are using. For instance, damon-config.xml: change the line "<entry key="damon.aspect.engine">aspectwerkz</entry>". For example, messaging system needs to load (i.e. by a aop.xml file) the damon.messaging.aspectwerkz.AspectObserver that extends damon.messaging.aspectwerkz.AspectCommunicator. Note that run.bat batch file also will be changed to initiate another aspect framework.

 

 

© 2008 Ruben Mondejar <ruben.mondejar@urv.cat>