A Brief Introduction to Around Metaobjects

This short introduction is targered to people who want to create one or more arounds metaobjects in Reflex. It describes what should be done in order to create and configure them, and how they could be composed when interacting at some program point.

What is an Around Metaobject?

An around metaobject is a metaobject that can replace an ocurrence of a certain operation, in other words, an “around” method in the metaobject is executed instead of that ocurrence. Reflex provides the ability to execute the original ocurrence and change (if desired) the parameters passed to it (similarly to AspectJ's proceed statement).

Around Metaobject Creation

First, we need to know how to create an around metaobject. Reflex considers a metaobject to be an around metabject if its “around” method (the name of this method can be chosen freely) takes as one of its parameters an IExecutionPointClosure (in any position). Let's see an example of a simple around metaobject:

import reflex.api.mop.IExecutionPointClosure;
 
public class AroundMO{
 
        /**
        * Around method
        */
        public Object aroundMethod(IExecutionPointClosure aClosure){
                //around code here
        }
}

In the code above, there is a simple class, which represents an around metaobject: this is because its around method takes an IExecutionPointClosure parameter. What can we do with this closure parameter?. The answer is given by the definition of the IExecutionPointClosure interface:

package reflex.api.mop;
 
public interface IExecutionPointClosure {
 
        public Object proceed();
 
        public void setArg(int aIndex, Object aValue);
}

The first method allows the metaobject to invoke the original occurrence of the operation and the second one can be used before the invocation of the former in order to change the parameters that will be passed when proceed is invoked.

Around Metaobject Configuration

At the moment, we have defined the around metaobject. Now we have to configure a link to work with the metaobject. The relevant part of the link's configuration is the specification of the CallDescriptor for the metaobject. Recall that the CallDescriptor specifies the method name (and the parameters) of the method that will be invoked in the metaobject. You can specify your own parameters (with their types and evaluation code); but in the case of the closure parameter, Reflex provides a ready-to-use parameter object: Parameter.CLOSURE. Lets see an example of how to use it:

Link theLink = ...;
theLink.setCall(new CallDescriptor(
        AroundMO.class.getName(), "aroundMethod", Parameter.CLOSURE)
);

With this code, we configure Reflex to call the aroundMethod declared in AroundMO with the Parameter.CLOSURE parameter.

Around Metaobjects Composition

In some scenarios, we may have more than one link bound to an around metaobject acting at the same program point. Such an interaction between links can't be resolved automaticaly. To solve this, Reflex provides two operators to specify the rules that dictates how those links will be composed (you can also define your own operators):

  • Seq(Link L1, Link L2): defines that L1 and L2 will be composed in such way that L1 is execute first, and then L2 (sequential composition);
  • Wrap(Link L1, Link L2): defines that L1 (L1 must be associated to an around metaobject) will wrap L2: L2 will be executed only if L1 invokes proceed (nesting composition, similar to AspectJ's precedence)

In this introduction we are interested in the second operator: Wrap. For example, if we have two links, where one wraps the other, the only way for the wrapped metaobject to be executed is that the wrapper invokes proceed on the closure parameter. Note that if the wrapper metaobject is not an around metaobject, the wrapped metaobject will NOT be executed (Reflex will warn you if this occur). Let's see the code necessary to wrap two metaobjects.

API.rules().addRule(new Wrap(L1, L2));

As you can see, API.rules().addRule(Rule) is used in order to specify the wrap rule.

Further Information

A complete (and compilable) example of all the items we have seen here (around metaobjects and composition rules) can be found in the reflex.examples.fibonacci package of the Reflex distribution.