Jonas Bonér bio photo

Jonas Bonér

Specialist at Large.
Entrepreneur.
Hacker.
Public Speaker.
Powder Skier.
Obsessive Learner.
Jazz Addict.
Wannabee Musician.

Twitter LinkedIn Github
Using the new techniques of AOP and the AspectWerkz framework there is actually pretty easy to implement transparent persistence for Plain Old Java Objects (POJOs). This example has been implemented using JISP as persistence engine and can be checked out along with the AspectWerkz distribution from the CVS. (Please note that the documentation is not all up to date). First we have to write a PostAdvice similar to this one:
public final class DirtyFieldCheckAdvice extends PostAdvice {

    public DirtyFieldCheckAdvice() {
        super();
    }

    // is being executed when a field has become dirty
    public void execute(final JoinPoint joinPoint) {
        FieldJoinPoint jp = (FieldJoinPoint)joinPoint;
        try {
            PersistenceManager.store(jp.getTargetObject());
        } catch (PersistenceManagerException e) {
            throw new WrappedRuntimeException(e);
        }
    }
}
So, what did we just do? Well, we created a field advice that extended the PostAdvice class. The PostAdvice abstract base class guarantees that the void execute(final JoinPoint joinPoint) will be executed after that a field has been set (modified). The second step is to tell the AspectWerkz system which fields we want to monitor. This is specified in the XML definition file:
<aspectwerkz>

    <introduction name="persistable"
        interface="aspectwerkz.extension.persistence.Persistable"/>

    <advice name="makePersistent"
        class="aspectwerkz.extension.persistence.DirtyFieldCheckAdvice"
        deploymentModel="perJVM"/>

    <aspect class="domain.*">
        <introduction-ref name="persistable"/>
        <pointcut type="setField" pattern=".*">
            <advice-ref name="makePersistent"/>
        </pointcut>
    </aspect>


</aspectwerkz>
In this file we first define an Introduction for the "marker interface" aspectwerkz.extension.persistence.Persistable (that will be used by the persistence engine to select which objects that should be treated as persistent and which should be treated as transient). Next we define our Advice by giving it a name, mapping it to the full class name of the advice and specifying the deploymentModel, (which can be seen as the "scope" for the advice). There are four different deployment models available:
  • perJVM - one sole instance per Java Virtual Machince. Basically the same thing as a singleton class.
  • perClass - one instance per class.
  • perInstance - one instance per class instance.
  • perThread - one instance per thread.
Then we have to specify where to apply the Introduction, i.e. which objects we want to mark as persistable and which fields we want to monitor using our Advice. This is done by by defining an Aspect with a pattern matching the classes we want to make persistable. In this Aspect we added a reference to our Introduction (which tells the system that it should apply this Introduction to all classes matching the pattern for the Aspect) and defined a Pointcut for the fields we are interested in (in this case all fields in all classes matching the pattern). The Pointcutb is defined by specifying the type of the Advice (in this case setField since we want to know when a field has been modified), the pattern for the fields we want the monitor (as a regular expression) and last but not least a reference to to the Advices we want to apply to this Pointcut. The only thing that is left for getting the whole thing to work is to implement the persistence manager class. This example is based on JISP but the implementation is made pluggable so it would be a simple task to add support for RDBMS, JDO or whatever. If you choose to check out the example, you can run it using Maven by executing maven aspectwerkz:samples:transparentpersistence.