Aspect Oriented Programming In Java ME

Do you want to structure your Java ME applications better? Aspect Oriented Programming is a cool technology that can modularize your applications and separate the verbose infrastructure code from the application logic. The only catch is that it doesn’t exist for Java ME. Or does it?

Introduction

Aspect Oriented Programming (AOP) is gaining popularity within the Java SE/EE communities. There are many advantages of AOP especially as it provides a clear separation of concerns. The code becomes much more modular than with
traditional object technology. It’s not the intent of the article to explain all AOP
concepts and if you’re new to AOP you can find a couple of introduction sites in the
references section. Instead we will show how AOP can be used in CLDC enabled
devices such as mobile phones.
In Java ME applications there haven’t been much use of AOP. In fact, there
haven’t been any AOP frameworks available at all! Until now that is. AspectME
is a new open source project that delivers an AOP framework mainly targeted at
CLDC devices. Maybe most importantly, AspectME adds a reflection API. Reflec-
tion makes it possible to invoke methods and access fields dynamically. Advanced
frameworks use reflection to enable non-intrusive and modular mechanisms. Reflec-
tion is needed in AOP frameworks since we need information about where in the
code the aspect is executing.

What’s in the box?

AspectME consists of a runtime jar file that needs to be packaged together with
your Java ME application. Then we have an aspect weaver that is used to weave the
aspects into the compiled classfiles. During the weaving process necessary reflection
information is also added. What aspects to apply and extra reflection information is
controlled by a configuration file. And that’s all. To conclude, to use AspectME you’ll
need the following:

1. Add aspectmeruntime.jar to your Java ME project.
2. Write a configuration file that defines your aspects.
3. Run the aspect weaver after you’ve compiled your source code.

The assembly and deployment of your application is the same as before. AspectME
doesn’t change or remove debugging information so you can debug your application
as usual. Now, lets look at a small example.

Logging example

The first example is the classic logging example where we want to write enter/exit
outputs to the console around certain methods. Consider the following code:

public class Foo {
  public int bar(String s) {
    return Integer.intValue(s);
  }
}

It would be easy to add System.out statements when we enter and exit the method.
However, it would clutter the code, especially if we want to print out if we exit from
an exception:

public class Foo {
  public int bar(String s) {
    System.out.println(”Enter bar()”);
    try {
      int rv = Integer.intValue(s);
      System.out.println(”Exit bar()”);
      return rv;
    } catch (Exception e) {
      System.out.println(”Exit bar() from exception ” + e);
      throw new RuntimeException(e.getMessage());
    }
  }
}

Instead we can use AspectME and write an advice that can be used to weave logging
functionality into the code:

import org.aspectme.api.MethodInterceptor;
import org.aspectme.api.MethodInvocation;

public class LoggingAdvice implements MethodInterceptor {
  public Object invoke(MethodInvocation mi) {
    // Create a pretty string
    String methodSignature = mi.getMethod().getName() + ”()”;

    System.out.println(”Enter ” + methodSignature);

    // Continue the method invocation
    Object rv = mi.proceed();

    System.out.println(”Exit ” + methodSignature);
    return rv;
  }
} 

Now we need to define the pointcut where we want to apply the advice. In this case
it’s only one joinpoint, the bar() method, but we could apply the advice to many
joinpoints, e.g. all public methods in a package. AspectME uses the AspectJ pointcut
language because it’s powerful and de-facto standard within the AOP community.
We do this in a XML file:

 <?xml version=”1.0”?>
<aspectme>
  <pointcut id=”barMethod” expression=”execution(* org.aspectme.example.Foo.
bar())” />

  <advice id=”log” class=”org.aspectme.example.aspects.LoggingAdvice” />

  <aspect advice-ref=”log” type=”around” pointcut-ref=”barMethod” />
</aspectme>

Note that combining the parameters from the aspect definition actually describes
in “plain english” what the aspect does, “log around barMethod”. Now we’re ready
to weave everything together into the final executable. We do this with the weave
command from a shell:

weave -in classes -f aspectme.xml -out weaved_classes

The weave command will analyze all classes from the classes folder and weave in the
advices according to the definition in the aspectme.xml file. All modified classes will
be written to the weaved_classes folder.
But hey, didn’t we want to write to the console if we leave the method from an
exception? With AOP this becomes a breeze:

public class LoggingAdvice implements MethodInterceptor {
  public Object invoke(MethodInvocation mi) {
    // Create a pretty string
    String methodSignature = mi.getMethod().getName() + ”()”;

    System.out.println(”Enter ” + methodSignature);

    // Continue the method invocation
    try {
      Object rv = mi.proceed();

      System.out.println(”Exit ” + methodSignature);
      return rv;
    } catch (Exception e) {
      System.out.println(”Exit ” + methodSignature + ” with exception ” + e);
      throw e;
    }
  }
} 

Note that we have totally separated the concern of logging in our example. We can
easily change the logging mechanism by editing a single file, even though it’s applied
in hundreds of joinpoints.

Persistence example

Figure 1

The previous example was simple but showed the basics of AspectME. Now lets
concentrate on a more interesting example. Imagine we have an application that will
manage contact information. If designed properly we would have a domain model
consisting of two classes, ContactList and Contact. The ContactList contains zero or
more Contact objects.
The MIDlet would create the ContactList at startup and pass the model to the views.
The views would use the ContactList to add and remove Contact elements. In tradition-
al application design we would add a ContactListDAO that manages the persistence mechanism. The DAO object would be used from the controller whenever a contact is added or removed. Nice design? Not really since the DAO clutters the code and adds unnecessary infrastructure code into our application.
Using the AOP approach we would intercept the execution at certain joinpoints
as shown in the picture. We start by writing a persistence advice:

public class PersistenceAdvice implements MethodInterceptor,
                                          ConstructorInterceptor {

  /**
   * Stores the target object after invocation.
   * @param invocation The joinpoint of the method invocation.
   * @return The return value from the method invocation.
   */
  public Object invoke(MethodInvocation invocation) throws Throwable {
    // Run the target method
    Object result = invocation.proceed();

    // Store the object
    store(invocation.getThis());

    // Return the result
    return result;
  }

  /**
   * Loads an object from the record store instead of creating it.
   * @param invocation The joinpoint of the constructor call.
   * @return The created object.
   */
  public Object construct(ConstructorInvocation invocation) throws Throwable
{
    Object obj = load();
    // If this is the first time we load the object we’ll get a null object.
    // In that case we need to create the object, i.e. proceed with the
    // normal execution.
    if (obj == null) {
      obj = invocation.proceed();
    }
    return obj;
  }

  private void store(Object obj) throws IOException {
    // Store the passed object into the record store by serializing it
    // to the record store
  }

  private Object load() throws IOException {
    Object obj = null;
    // Load the specified object from the record store
    return obj;
  }
}

The advice implements both the MethodInterceptor and ConstructorInterceptor.
The MethodInterceptor is used to intercept methods that changes the object and
store them in the record store. In our case the ContactList. The ConstructorIn-
terceptor is used to intercept the creation of ContactList objects, so rather than
creating them it will load them from the record store. This means that anywhere in
the code we execute “new ContactList()” we would load the object and return the
loaded object instead of creating it.
The serialization of objects can be made using the reflection API in AspectME.
An ObjectOutputStream reads the field values from the written object and primi-
tive fields are written to the DataOutputStream. Objects are written recursively.
Counterwise we have an ObjectInputStream that reads objects by writing the field
values by reading them from a DataInputStream. The result is very similar to Java
SE serialization mechanism as shown in the code example below.

public Object storeAndLoad(Object obj) {
  // Write object to byte array
  ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
  ObjectOutputStream objOut = new ObjectOutputStream(byteOut);
  objOut.writeObject(obj);
  objOut.close();
  byteOut.close();
  byte[] bytes = byteOut.toByteArray();

  // Read object from the byte array
  ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes);
  ObjectInputStream objIn = new ObjectInputStream(byteIn);
  return objIn.readObject();
}

If you’re interested in the implementation of the classes you can find them in the
code examples on the AspectME home page (see References).
All that’s left is to define our aspects in an aspectme.xml file:

<?xml version=”1.0”?>
<aspectme>
   <pointcut id=”addRemoveMethods”
             expression=”execution(*
*..domain.ContactList.addContact(..)) ||
                         execution(*
*..domain.ContactList.removeContact(..))” />
   <pointcut id=”newContactList”
expression=”call(*..domain.ContactList.new())” />
   <advice id=”persist”
class=”org.aspectme.example.aspects.PersistenceAdvice” />
   <aspect advice-ref=”persist” type=”around”
pointcut-ref=”addRemoveMethods” />
   <aspect advice-ref=”persist” type=”around”
pointcut-ref=”newContactList” />
   <!-- This will add reflection information for all objects
in the specified package. -->
   <reflect include=”org.aspectme.example.contact.domain.*” />
</aspectme>

After the weaving process our application will store the ContactList object into the
record store whenever a contact is added or removed. When the application is run
again the ContactList object is loaded from the record store. The application can
still run without the persistence aspect but all contact information will be lost when
the application closes. A good example of how crosscutting concerns creates total
transparency of an application mechanism.

Summary

AspectME is a promising AOP framework that can be used to take advantage of
AOP in CLDC enabled devices. The reflection capabilities add new dimensions to
CLDC applications such as object serialization. We have seen how advices can be
built and reused over many applications since it crosscuts the concern of persist-
ence. The performance impact is acceptable when dealing with large concerns such
as persistence. The bytecode footprint increases a couple of KB but that is a small
price to pay for the increased modularity. Often the footprint becomes smaller as we
gather all copy’n’paste like infrastructure code into small advices.

Originally published in JayView.

Leave a Reply

Close Menu