OSGi and AspectJ integration

1- Instroduction

This document base on:
  • Eclipse 4.4 (LUNA)

History:
   20-01-2014: Create document based on Eclipse 4.3 (Kepler)
   23-07-2014: Update to Eclipse 4.4 (LUNA)

1.1- Suggest

You should check your Eclipse was installed Ajdt Plugin, If it hasn't been installed, you should refer this following document :
 

2- Create Example

2.1- Download source

2.2- The Model of Tutorial

These examples are models which include 3 projects :
 
  • target-runtime  
  • osgi-define-aspectj
  • affected-osgi
  1. osgi-define-aspectj
    • is an osgi project as well as an aspectj project. This is also the definition of aspectj SumAspectj.aj
  2. affected-osgi
    • is an osgi project, but it's not an aspectj project. It relies on osgi and is affected by aspectj which has definition as above.

2.3- Project target-runtime

Create a java project, with the name "target-runtime":
New/Other
At the time I update this document to Eclipse 4.4, AJDT is being developed from 4.3 to 4.4 and it is not complete,so we use dev library.
  • http://download.eclipse.org/tools/ajdt/44/dev/update/
Finally click "Set As Target Runtime" to the runtime library affect to all project in the workspace

2.4- Project "osgi-define-aspectj"

Create project "osgi-define-aspectj":
  • org.o7planning.tutorial.osgidefineaspectj.Activator
Convert this project into aspectj project:
Result:
We will create some classes and an AspectJ to get a result as following pictures:

 
First, add aspectj "SumAspecj" and click on Eclipse:
  • File/New/Others...
package org.o7planning.tutorial.osgidefineaspectj;

public aspect SumAspectj {
   
   before() : execution(* *.sum(..)) {
       System.out.println("Before execution sum");
   }
   
}
package org.o7planning.tutorial.osgidefineaspectj;

public class MathUtils {
    
    public static int sum(int a, int b) {
        return a + b;
    }
}
package org.o7planning.tutorial.osgidefineaspectj;

public class TestSumInternal {
    
    public static void main(String[] args) {
         
        int value= MathUtils.sum(10,20);
        System.out.println("Value ="+value);
 
    }
 
}
Run class TestSumInternal, As a result. when the method with name of "sum" runs, aspectj SumAspectj will work and have text "Before execution sum"
 
Next, we declare export package and aspectj in order to use the other osgi.
 
Until now, we can create an osgi project with aspectj, and it can completely run in this internal osgi. However, every bundle osgi use its own classLoader, so aspectj can only use in this internal osgi. It need to have some configurations to affect the other osgi bundle. Work on a different project to be affected by aspectj which is declared on the project as above.

 

2.5- Project "affected-osgi"

Similarly, you can create the other osgi project with the name "affected-osgi".
 
Declare it to rely on osgi as "osgi-define-aspectj". Two bundles:
 
  • org.eclipse.equinox.console
  • org.apache.felix.gogo.shell
package org.o7planning.tutorial.affectedosgi;

public class Math2Utils {
    
    
    public static float sum(float a,float b)  {
        return a+b;
    }
     
    public static int sum(int a, int b)  {
        return a+b;
    }   
     
}
package org.o7planning.tutorial.affectedosgi;

import org.o7planning.tutorial.osgidefineaspectj.MathUtils;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

    private static BundleContext context;

    static BundleContext getContext() {
        return context;
    }

    public void start(BundleContext bundleContext) throws Exception {
        Activator.context = bundleContext;

        this.testSumAspectj();
    }

    private void testSumAspectj() {
        System.out.println("-----------------------");
        int value1 = MathUtils.sum(100, 100);
        System.out.println("Value =" + value1);

        System.out.println("-----------------------");
        int value2 = Math2Utils.sum(100, 100);
        System.out.println("Value =" + value2);

        System.out.println("-----------------------");
        float value3 = Math2Utils.sum(100f, 100f);
        System.out.println("Value =" + value3);
    }

    public void stop(BundleContext bundleContext) throws Exception {
        Activator.context = null;
    }

}
 
Now we will configure to run OSGi "affected-osgi".
 
  1. Name the configured application "Run affected-osgi project". 
  2. Check your two projects.
  3. Skip check all Target Platform
  4. Click on " Add Required Bundles" ,and Eclise can automatically calculates dependent bundles.
  5. Click Apply
After running osgi project "affected-osgi", we have a result:
As a result, aspectj "SumAspectj" which is comfimedin osgi "osgi-define-aspectj" hasn't affected the other osgi.
Next, we configure to ensure that "SumAspectj" can affect the other osgi "affected-osgi".
 
Declare more bundles which required for osgi "affected-osgi".
 
  • org.eclipse.osgi
  • org.aspectj.weaver
  • org.eclipse.equinox.weaving.aspectj
  • org.eclipse.equinox.weaving.caching
Declare the environmental parameters.
 
  • -Dosgi.framework.extensions=org.eclipse.equinox.weaving.hook  
  • -Daj.weaving.verbose=true
  • -Dorg.aspectj.weaver.showWeaveInfo=true
  • -Dorg.aspectj.osgi.verbose=true
Declare fragments to extend for osgi "org,eclipse.osgi".


 
  • -Dosgi.framework.extensions=org.eclipse.equinox.weaving.hook
You can add the following line to for to check errors (Debug):
 
  • -Daj.weaving.verbose=true
  • -Dorg.aspectj.weaver.showWeaveInfo=true
  • -Dorg.aspectj.osgi.verbose=true
You ensure that the bundle "org.eclipse.equinox.weaving.aspectj" can automatically start at Level 2.
 
Finally, you can run osgi "affected-osgi" again , and this is the expected result.