On the Footprints of Join Points:
The Blueprint Approach
Walter Cazzola,
DICo - Department of Informatics and Communication,
Università degli Studi di Milano
Sonia Pini,
DISI - Department of Informatics and Computer Science,
Università degli Studi di Genova |
 |
REFEREED ARTICLE

PDF Version |
Abstract
Aspect-oriented techniques are widely used to better modularize object-oriented programs
by introducing crosscutting concerns in a safe and non-invasive way, i.e., aspectoriented
mechanisms better address the modularization of functionality that orthogonally
crosscuts the implementation of the application.
Unfortunately, as noted by several researchers, most of the current aspect-oriented
approaches are too coupled with the application code, and this fact hinders the concerns
separability and consequently their re-usability since each aspect is strictly tailored on
the base application. Moreover, the join points (i.e., locations affected by a crosscutting
concerns) actually are defined at the operation level. It implies that the possible set
of join points includes every operation (e.g., method invocations) that the system
performs. Whereas, in many contexts we wish to define aspects that are expected to
work at the statement level, i.e., by considering as a join point every point between
two generic statements (i.e., lines of code).
In this paper, we present our approach, called Blueprint, to overcome the abovementioned
limitations of the current aspect-oriented approaches. The Blueprint
consists of a new aspect-oriented programming language based on modeling the
join point selection mechanism at a high-level of abstraction to decouple aspects
from the application code. To this regard, we adopt a high-level pattern-based join
point model, where join points are described by join point blueprints, i.e., behavioral
patterns describing where the join points should be found.
Keywords: Aspect-Oriented Programming, Join Point Selection Mechanisms, Join
Point Models.
1 INTORDUCTION
Aspect-oriented programming (AOP) is a powerful technique to better modularize
object-oriented programs by introducing crosscutting concerns in a safe and noninvasive way. Each AOP approach is characterized by a join point model (JPM)
consisting of the join points, a mechanism for selecting the join points (pointcuts)
and a mechanism for raising effects at the join points (advice) [26]. Crosscutting
concerns might be poorly modularized as aspects without an appropriate join point
model that covers all the interested elements. A pointcut definition language allows
the programmer to select all the desired join points.
In most of the AOP approaches, the pointcut definition language allows the
programmer to select the join points on the basis of the program’s lexical structure,
such as explicit program element names. The dependency on the program
syntax renders the pointcut definitions fragile [15] and strictly couples an aspect
to a specific program and language, hindering its reusability and evolvability [11].
The required enhancement should consist of developing a pointcut definition language
that supports join point selection on a more semantic way [1]. To provide
a more expressive and semantic-oriented selection mechanism requires a language
that captures the base-level program behavior and properties abstracting from the
syntactic details. Several attempts (e.g., [24,18,17,11,23,14]) in this direction have
been investigated but none of these completely solve the problem. They focus on
specific behavioral aspects such as execution trace [4] and dataflow [10] neglecting
some others. Moreover, they still rely on name conventions and on the knowledge
of the implementation code. We think that the problem could be faced and solved
by selecting the join points on an abstract representation of the program, such as
its design information.
In this paper, we present a novel aspect-oriented framework, called the Blueprint, and in particular its join point selection mechanism that allows the selection of the
join points abstracting from implementation details, name conventions and to some
extent from the base-program structure. In particular the aspect programmer can
select the join points of interest by describing their supposed location in the application
through UML-like1 descriptions (basically, activity diagrams) representing
computational patterns on the application behavior; these descriptions are called
blueprints. The blueprints are just patterns on the application behavior, i.e., they
are not derived from the system design information but express properties on them.
In other words, we adopt a sort of enriched UML diagram to describe the application
control flows or computational properties and to identify the join points inside these
contexts. Pointcuts consist of an enumeration of join points from a set of blueprints.
Thus, they are not tailored on the application syntax and structure but only on its
behavior.
The rest of the paper is organized as follows: in section 2 we investigate the
limitations of some of the other join point models, in section 3 we present the Blueprint framework and how it works whereas in section 4 we show the inner
process of selecting the join points and the aspect weaving at the join points. In
section 5 we show the framework at work; section 6 considers a few of related works. Finally, in section 7 we draw out our conclusions and discuss possible future work.
2 LIMITATIONS OF THE JOIN POINT MODELS
The join point model, in particular its pointcut definition language, has a critical
role in the applicability of the aspect-oriented methodology. The pointcut definition
language allows to determine where a concern crosscuts the code.
Pointcut definition languages have evolved to improve their expressivity, their
independence of the base code and the general flexibility of the approach. The first
generation of pointcut definition languages (please see [13]) were strictly coupled
to the application source code because they allow the selection of join points only
on the signature of the program elements (by enumeration). To reduce the coupling
problem, the use of wildcards has been introduced (as in, AspectJ [12], and
HyperJ [19]). This technique has slightly reduced the coupling problem but has introduced
the necessity of naming conventions. Unfortunately, naming conventions
raise a new problem since they are not checkable by the compilers and their adoption
cannot be guaranteed. Recently, some aspect-oriented languages (e.g., AspectJ
5, AspectWerkz [27]) adopted meta-data to identify the join points. This approach
decouples the aspects from the base program syntax and structure; the meta-data
is used as a placeholder to mark a join point to be easily selected among the others.
This technique does not solve the problem; it just shifts the coupling from the program
syntax to the meta-data syntax. Moreover, this approach breaks in an explicit
way the obliviousness [6] property2. To get obliviousness the aspect programmer
should be unaware of the base program structure and syntax to apply the aspects,
and vice versa. The coupling problem brings forth another problem, called the fragile pointcut
problem [15]. When the pointcut definition strictly depends on the base program,
any change to the program will affect the pointcut capacity of grabbing the expected
set of join points. The fragile pointcut problem is a serious inhibitor to evolution
of aspect-oriented programs. Pointcuts are deemed fragile when seemingly innocent
changes to the base program, such as renaming or relocating a method, break a
pointcut such that it no longer captures the join points it is intended to capture [3,
11]. Pointcuts are similarly considered fragile when a just introduced join point
should be captured by an existing pointcut but it fails to do so. This implies that
all pointcuts of each aspect need to be checked and possibly revised whenever the
base program evolves, since they could break because they capture a set of join
points based on some structural and syntactical properties that any change to the
base program can alter. This problem occurs independent of whether wild-card
expressions are used.
In this situation, the aspect programmer must have a deep knowledge of the base
program to be sure that his/her pointcuts work as expected. Moreover, most of the
join point selection mechanisms (e.g., in AspectJ) are suitable to select join points
that are at the object interface level but they badly fit the need of capturing join
points expressed by computational patterns, such as inside loops or after a given
sequence of statements.
Pointcut definitions heavily rely on how the software is structured at a given
moment in time. In fact, the aspect developers assume the structure of the base
program when they define the pointcuts; the name conventions are an example of
this assumption. They implicitly impose some design rules that the base program
developers have to respect when they evolve their programs to be compliant with the
existing aspects and to avoid the selection of more or less join points than expected.
We believe that aspect programmers need to be, as much as possible, unaware
of base code details and evolution — we call this extension to the obliviousness definition application syntactic obliviousness. To achieve application syntactic obliviousness
the aspect programmer should be unaware of the base program structure
and syntax to apply the aspects and vice versa. From our point of view, the base
program is seen as a gray-box, where it is possible to see the high-level information
about it, such as its behavior, its design information, and so on, but it should be
impossible to see the base code details. In this way, if an aspect needs to be applied
to a program, the lack of knowledge of its internals would prevent the use of syntactic
pointcuts. Of course, total obliviousness will drive to more reusable code but
will also increase the number of join points selected but not desired [21]. To address
this objective, we need a total separation of pointcut definition from aspects tied to
lexical properties of the source code. From the reported considerations, it is fairly evident that the main problems of
current join point models are due to the pointcut expression languages, that often
do not offer the right degree of abstraction with respect to the base program. Hence,
we think that the next step of aspect-oriented methodology consists of extending the
pointcut definition language to support join point selection on the basis of a semantic query. To solve all the previously cited problems (that is, coupling problem, fragile
pointcut problem and obliviousness reducing), we propose a novel approach to the
join point selection, called Blueprint, based on describing a portion of the base
program behavior, through a model, where to identify the join points of interest.
As stated in [1], working at the model level offers promising possibilities to start
abstracting away from the concrete syntax. This means that the model information
(such as, UML diagrams) describing a program is independent of its implementation,
both of the programming languages characteristics and of the names used at
the code level. The model-based pointcut definitions are both less fragile and less
coupled, because they are not defined in terms of syntactic description of base program
characteristics. Moreover, model-based approaches promote the application
of the syntactic obliviousness property because they do not need to know the code
details.
3 THE BLUEPRINT FRAMEWORK
In the Blueprint approach, we select the join points by providing a template (a
blueprint) of the base program behavior/computational models which describes
where the join points could be found. This approach does not only allow precise
location of where we are looking for but also of describing some context information,
such as, what happens before or after the join point: a certain point in the computation
is a join point if and only if all the specified context conditions are verified.
The Blueprint framework is based on our previous work [2] and it is completely
detailed in [20]. This section gives an overview of the Blueprint aspect-oriented
language and describes how to use it.
The Blueprint Aspect-Oriented Approach.
The Blueprint aspect-oriented language permits the selection of the join points of
interest by describing their supposed location in the application through a UML
activity diagram representing patterns on the application behavior, called join point blueprint. These join point blueprints are not subsets of the application design
information. They do not describe the application behavior, rather they describe
the desired properties and behaviors we are looking in the application.
The Blueprint framework foresees a matching and unification phase that permits
to perform queries such as "print the value of a variable used in a loop test condition
and modified in the loop body". This kind of query is expressed describing the
context we would like to get and the position where we would like to raise effects.
To carry out this kind of query we have to compare our description with the source
code of the base-program during the weaving process. The Blueprint language can
be used on the bytecode as well since it can be univocally decompiled (modulo
semantic equivalence) by appropriate tools, e.g., by Jode3.
In our approach, we do not need to use position qualifiers such as before and after advice to indicate where to insert the concern inside the base code. Because
we describe the context, we can either locate the join points exactly where we want
to insert the new code or, to highlight the portion of behavior we want to replace.
Blueprint Join Point Model
The Blueprint framework recalls the AspectJ terminology but some terms are used
with a slightly different meaning. Introductions and advice keep their usual meaning
whereas join points and pointcuts have slight deviations. The Blueprint join
points are hooks where the code may be added rather than well-defined points in the
execution of a program where effects can be raised. In AspectJ, the considered join
 Table 1: Blueprint Terminology.
points are things like method and constructor calls, method and constructor executions
and field references. That is, they are at the operation interface but a join
point could occur everywhere in the code not only at the operation interface — the Blueprint exploits this concept. This view grants a statement-level granularity to
the Blueprint join point model. In particular, we consider two different kinds of join
points: the local join points that represent points in the application behavior where
to insert the code of the concern, and region join points that represent portions of
the application behavior that must be replaced by the code of the concern.
To complete the picture of the situation, we have introduced some new concepts: join point blueprint and blueprint space. The former is a template (a blueprint) on
the application behavior identifying the join points in their context; these blueprints
describe where the local and region join points should be located in the application
behavior. The blueprint does not completely describe the computational flow but
only the portions relevant to select the join points. The latter is the set of all join
point blueprints defined on the same application. The pointcuts are a query on
the blueprint space, i.e., they select some join points imported from one or more
blueprints. Table 1 summarizes the concepts characterizing the Blueprint model.
The Blueprint is based on the idea that the description of the application behavior
cannot be strictly coupled to the application syntactic details. It permits a loose
approach to the description of the application behavior. This means that the aspect
programmer can use different levels of detail during the description of a single join
point blueprint by using any possible combinations of loose and tight elements. This
approach permits the description of a well identified behavior tightly coupled to the
application code by specifying the names of the involved elements, and a less known
behavior by using meta-information to abstract from the real application code.
The join point blueprints are the key elements of the whole approach.

Figure 1: Sample Join Point Blueprint. They graphically depict where a join point, both local and region, should be located in
the application behavior. They look like an activity diagram and to some extent
they behave similarly. Conceptually, both represent part of the computational flow
of the application. What differs is their use: the activity diagrams are used to model
the application behavior whereas the join point blueprint matches the supposed
application behavior. For this reason, some elements composing the diagram have
additional meanings and the diagram itself is accompanied by context information.
A join point blueprint depicts where a join point should be located in the application
behavior. Each blueprint is a diagram framed by a dashed rectangle. The
diagram contextualizes the join point location by describing some crucial events that
should occur close to the join point. These events will be used to recognize the join
point. The frame gives some ancillary information, such as the blueprint name (at
the top left corner), the join point names exposed by the blueprint (at the bottom
right corner) and some meta-info (see later in the section) used by the weaver to
parametrize the context and to get values from the join point. The listed join points
are only exposed to the pointcut specification. The join point location is denoted
by the «joinpoint name» stereotype (or by the pair «startjoinpoint name» and«endjoinpoint name» for the region join points).
Figure 1 shows a very simple join point blueprint that does not fully illustrate
the whole expressivity allowed by the formalism. For a detailed and exhaustive
description, please refer to [20] chapter 4. The following provides a brief overview
of all elements that can appear in a join point blueprint.
Computational Flow Description Elements. In the join point blueprint
it is possible to use a set of programming abstractions for modeling the control flow
of the described behavior: conditional construct (if), cycles and loops (for, while,
and so on) and object flow (swimlane). These flow abstractions are represented
by the standard UML decision elements and are used to describe the application
computational flow we desire. The aspect programmer can fill these flow abstractions
with details such as the checked condition; the more details are used the easier the
searched behavior can be uniquely identified. Particularly relevant is the use of the swimlanes, which permit the organization of the searched behavior in terms of the
actions that should be performed by any single actor. This better contextualizes
where to look for a specific part of the blueprint. Figure 1 has a swimlane that
separates the call of a method from the description of what happens inside the
method itself.
Loose and Tight Elements. To abstract from the application syntactic details,
the Blueprint language allows to define the blueprints in an incomplete/abstract way, i.e., it is possible to describe the computational flow by using a loose approach.
Analogously, to get more in touch with the searched behavior it is possible to specify
all the necessary details to skim among similar portions of code, i.e., it is possible
to use tight elements in the blueprint description.
The Blueprint allows the aspect programmer to use meta-information to depict
a blueprint of the searched behavior without referring to the application element
names and types. This independence has been achieved through template actions and loose transitions. A loose transition is a line with a stick arrowhead connecting
two action states in the blueprint; it indicates that the target action state follows
the source action state but not immediately, i.e., zero or more not relevant (to
the join point localization) instructions could occur before the target action state,
the number of instructions that could occur is limited by the (optional) transition
scope. A template action is a yellow action state containing a template-statement and optionally a scope indication. The template-statement is a statement defined
by the following regular expression:

where A can be either a name taken from the application code or a meta-variable
(see later in the meta-information section); B represents where the name A should be
found in the application code and can be (with the obvious meanings): booleancondition,
left, right, index, return, or statement.
All the blueprint loose elements have a scope denoted by a stereotype, which
limits the searching area of the blueprint portion inside the application code. There
are two kinds of scope: «method» and «block». The former limits the searching
area to the extent of the current method body (default behavior) whereas the latter
to the extent of the current code block.
An aspect programmer can use a template action or a loose transition when he
is not interested in a well-defined computational pattern but only on few characteristics,like the check for a condition or the use of a specific variable in a return
statement. Otherwise, he can specify all necessary details to skim among similar
portions of code through the use of actions and tight transitions.
An action is a red action state containing one or more Java statements which distinguish actions from template actions, the action is always decorated (at the top)
by the «exactmatch» stereotype. The statements inside the action can use both
meta-variables and real names. A tight transition is a line with a solid arrowhead
connecting two action states of the blueprint; it indicates that the target action state
follows immediately the source action state inside the application control flow.
Note that loose and tight elements can be mixed inside a blueprint. To avoid
ambiguities the tight elements have higher priority than the loose elements, the«block» has higher priority than the «method» scope qualifier.
Figure 1 shows three action states: an action and two template-actions; the
action describes a call to a method whose name is unknown (i.e., foo is a metavariable).
All the transitions are loose (they all have a stick arrowhead) so we are
just looking for a loose pattern with a given and incomplete sequence of statements.
Flow Operators. Complementary and alternative behaviors can be described
by using the flow operators provided by the language: and and or. These operators
resemble the UML fork element decorated, respectively, by the «and» and «or»
stereotype. The and operator allows the programmer to describe multiple behaviors
that will be searched into the application computational flow; whereas the or operator can be used to describe alternative behaviors. In the first case we have to
match all branches to consider the operator matched. In the second case, at least
one match is needed. The flow operators are useful to separately describe concerns
that can be tangled inside the application code. Figure 1 shows an or operator with
two branches.
Join Points. The Blueprint language allows the definition of a join point every
point between two instructions. Two kinds of join points are considered: local and region join point. A local join point is represented by an empty circle on transition
labeled by the «joinpoint jp_name» stereotype; it specifies the exact point where
the advice code will be inserted when the blueprint matches the application computational
flow. A region join point represents a portion (region) of the application
behavior that will be replaced by the advice code when the blueprint matches the
application computational flow. Two stereotypes «startjoinpoint jp_name» and «endjoinpoint jp_name» denote the borders of the region.
The location of the join point is not ambiguous when the join point stereotype
is attached to a tight transition since it strictly coupled the source and target action
states: the latter follows immediately the former. Therefore the join point is exactly
between the last matched statement of the source action state and the first matched
statement of the target action state. The situation is more complex when the join
point stereotype is attached to a loose transition since we do not assume anything
about where the next statement will be with respect to the join point location.
To better describe the join point location the stereotypes can be combined with
the location modifiers: «source» and «target» to express the join point vicinity
relation.
Figure 1 shows a couple of local join points: produce and consume. They
are both on a loose transition but exploit the default qualifiers: «method» and «target».
Meta-Information. Inside the frame of the join point blueprint there is a set
of meta-information associated to each swimlane useful to decouple the blueprint
from the application code and to contextualize where to look in the application code
for the blueprint.
The meta-information allows the programmer to describe the blueprint decoupled
from the application code. The weaving mechanism will provide an unification
between the meta-variable names and the variable names used in the application
code, if it will be possible.
In each swimlane, there are up to five sections containing meta-information: context, variable meta-variable, method meta-variable, type meta-variable and type
binding. The context section contains the name(s) of the class(es) where to look
for the computational flow described in the swimlane. The meta-variable sections
contain a pool of variable names that can be used in the blueprint instead of the
names coming from the code; these are called meta-variables since they contain
names and not values. The meta-variables can refer to variable and method names
or to types. In the type binding section, it is possible to express bindings among the
variable and method meta-variables and the type meta-variables. This mechanism
permits to realize polymorphisms on the variable and method meta-variables, e.g.,
given a type meta-variable named foo associated to int and String we could declare
a variable meta-variable bar of type foo that will match both strings and integers
variables in the code. The language assumes that all names present in the blueprint
but not present in the meta-information sections are real application element names.
The blueprint in Figure 1 has two swimlanes. At the top, there is a method
meta-variable (foo) — please, note that the any return type denotes any possible
return type. At the bottom, there is the Field variable meta-variable and a context
specification Buffer that confines the match for this swimlane to this class.
Blueprint Aspects
An aspect is the modular unit that crosscuts other modular units. Similar to AspectJ,
the aspect declaration looks like a class declaration.
Listing 1 covers the basics of what an aspect can contain. An aspect consists
of method and field declarations (rows 2-3), a join point blueprint import section
(rows 4-7), pointcut definitions (rows 9-11), the advice (rows 13-15), and finally the
code for the introductions (rows 16-18).
The method and field declaration section contains methods and fields local to
the aspect. These can be used in the advice section but these methods cannot access
the base-program private elements since they are in the aspect scope.
 Listing 1: An Example of Aspect Definition by using the Blueprint Language.
In the blueprint import section, introduced by the keyword joinpointblueprint,
we list the join points out of the blueprints that will be used inside the aspect. To
list a blueprint name without parameters is to import all of its join points, otherwise
only the listed ones are imported.
In the pointcut section, we associate a pointcut, i.e., a query on the blueprint
space, to the join points imported in the specific section. The association is basically
achieved by listing the desired join point names.
The advice section defines crosscutting behaviors that should be introduced at
the selected join points. An advice is associated to a pointcut or to a list of join
point names imported from a blueprint. The code of the advice runs at every join
point picked out by its pointcut.
Finally, the introductions, introduced by the introduction keyword, allow the
definition of new methods and attributes that will be added to the application code
during the weaving process. This ancillary code can assess the private information
of the application code where they are woven.
The Blueprint provides a simple reflective API (reported in Table 2) to access
context information like the join point signature4 and the meta-information specified
in the blueprint, such as variable and method meta-variables, through a special
reference: thisJoinPoint(jpname). thisJoinPoint(...) can be used both in-side advice and introductions. In the advice the parameter represents one of the
join points specified in the advice, whereas in the introduction it can refer to every
join point declared inside the aspect.
 Table 2: Blueprint Reflective API: thisJoinPoint(jp) Methods The weaving process will create a connection
between the meta-variables and the matched application elements. Therefore, by
using the meta-variables (through the reflective API) corresponds to using the real
elements. At the moment, the available reflective API is still quite limited but some
extensions are under development.
4 BLUEPRINT MATCHING AND WEAVING
One crucial component in AOP is the weaver. Given a set of target programs and
a set of aspects, the weaver introduces the code of the advice at the captured join
points in the target programs during the weaving process.
Even if the join point blueprints are language independent, the weaving process
strictly depends on the program it has to modify. At the moment, we have chosen
the Java programming language but in the future we are planning to extend the
approach to many other languages. The Blueprint weaving process consists of the
following phases:
- pre-weaving phase: the abstraction level of the join point blueprint and of the
Java bytecode is equalized;
- matching phase: the matching is performed by traversing the model/graph of the blueprint and the model/graph of the program in parallel;
- advice weaving phase: the advice code is inserted at the captured join points.
Pre-Weaving Phase. The base program and the join point blueprints are at
different levels of abstraction. To fill this gap and allow the weaving, it is necessary
to build a common representation for the base program and the join point blueprints.
The abstract syntax tree (AST) perfectly fits the problem; both source code (through
its control flow graph) and join point blueprints can be represented by AST-like
descriptions.
The AST of the base program is simply developed by using a parser and AST
generator. To generate the AST for the blueprints is more complex. Any UML
diagram can be represented as a graph because it is defined by the UML metamodel
which is a graph where the nodes are meta-classes and the edges are metarelationships,
but it is not possible to generate such kind of a tree from the join point
blueprint because of the loose elements. To overcome this problem, we have created
a graph where each transition becomes a labeled graph edge, each action becomes a
graph node containing the AST nodes generated by the Java instructions contained
in the action. This kind of graph node is called a complex node; each template action becomes a simple node that does not contain AST nodes but some information about
the scope of and the kind of statement looked for by the corresponding template
action. It is necessary to differentiate the graph nodes because we cannot define an
AST to describe a template action, because it does not contain real Java instructions.
Labels represent the scope information, join point location and so on. We call this
representation: Blueprint_Graph.
Matching Phase. After obtaining the same level of abstraction for source code
and blueprints, the next step is to find all matchings among each Blueprint_Graphs,
generated in the previous phase and the application AST.
Our matching algorithm is not a simple algorithm to match two graphs, because
we do not have the same kind of graphs but a graph and an AST representation.
To solve this, we developed a special matching algorithm, called multiple spread tree
inclusion, that looks for:
- a tree matching between portions of the application AST and the complex
nodes of the Blueprint_graph; and
- matching between the Blueprint_graph simple nodes and portions of the
application AST.
These matchings are driven by the edges connecting two Blueprint_Graph elements
in a depth-first visit and the search area defined by the context meta-information.
During the matching algorithm we have to associate the meta-variable names
used inside the blueprints to the real names used inside the application (unification process).
 Listing 2: The Blueprint Unification Algorithm
The unification algorithm used in the Blueprint framework (listing 2 shows
its pseudocode) is based on the well-known Robinson’s unification algorithm [22].
Beyond using the unification, our matching algorithm is strongly based on backtracking,
since, to find all the possible matchings it must try all the tree branches.
Every blueprint matching is called possible matching as long as the last action state
of the blueprint has not been matched, from this point the matching is a sure matching.
Turning back to the single steps of our matching algorithm, in the first point we
search a real matching between the AST nodes of a complex node and, a portion
of application AST nodes, obviously, but the unification operations. This first step is a tree pattern matching problem [8]. We use an algorithm based on tree pattern
matching presented in [16].
Advice Weaving Phase. This is the last step of the weaving phase. During
this step the advice code is inserted into the application. This final step starts
only when the previous step obtains a sure matching for the considered blueprint.
To develop this step, the framework uses all information about join points and
unifications stored during the matching phase and the advice source code.
- The meta-information are used to identify the method affected by the advice;
- the unifications are used to unify the meta-variable names used inside the
advice code, to the names used inside the application source code; in this way
the code of the advice will refer to the code elements; and
- the advice source code, after the unification, is inserted into the local copy of
the right file, in the right position, corresponding to the considered join point.
To maintain the application source code unchanged, the Blueprint framework
uses a local copy of every application source file to insert the advice code into the join
points. After the introduction, the modified files are compiled on-the-fly by using
the javac compiler. The .class files are superseded to the original application .class
files. This last step exploits a Java library, called RECODER5 to modify and parse the
original application files. This library is already used by other aspect-oriented tools,
such as EAOP [5].
A complete description of the Blueprint weaving can be read in [20] chapter 5.
5 BLUEPRINT AT WORK
To stress the Blueprint potential in this section we present three examples. The first
one is a classical tracing aspect that demonstrates how the Blueprint can carry out
all of the modularization capabilities offered by other aspect-oriented approaches.
The second example, debugging and monitoring the execution of a program, should
show the capability of the blueprints for capturing join points that the other approaches
cannot deal with. The last example shows the Blueprint reflective API at
work.
The Blueprint Tracing Aspect.
Usually during the development, programmers insert debugging messages in their
code (e.g., to notify the beginning and the end of the method or constructor execution)
to better follow and test the execution of the application.

Figure 2: A Simple Tracing Blueprint and Aspect.
Even though this is a simple debugging mechanism, it has a number of drawbacks:
- the implementation of this feature is scattered over many classes of the system,
- many classes are cluttered with the message generation code, and
- after development it is difficult to safely remove the debugging code.
In short, the implementation of this conceptually simple feature leads to severely
tangled code. To this regard, we developed a simple tracing aspect consisting of a
join point blueprint definition and an advice.
The TracingBlueprint, showed in Figure 2, describes all method calls irrespective
of their name, signature, target object and where they are called and defined.
The method meta-variable foo during the weaving process is unified to the called
method signature, and inside the advice code it is possible refer to it and, by applying
the getSignature() method, visualizing the full name of the application
method. The blueprint defines two join points: jp1 and jp2; at these join points
the computational flow will be traced (woven advice).
Debugging and Monitoring the Knapsack Algorithm Execution.
The typical debugger’s functionality, such as variable and state watching, and tracing
can be easily realized through a Blueprint aspect.
Figure 3: The Report Blueprint and the Matched Code.
The right half of Figure 3 shows part of Rolfe’s solution6 to the well known Knapsack problem. The Knapsack problem, as well as any other problem in combinatorial optimization, offers several temporary values to be monitored during the execution, e.g., the evolution of the optimal solution, the changes to the optimal value and the
number of iterations to get the optimum. It is fairly evident that these issues can be
treated as a problem of breakpoint settings and variable watching. In particular, a
change in the current optimal solution depends on finding a better approximation to
the optimum as checked at row 10. This represents a relevant context information
exploited by the blueprint in the left part of Figure 3 to contextualize the event
independently of the names used in the code; note that val and optval are variable
meta-variables that, during the unification phase, will match value0 and optValue in the code, respectively. The Blueprint aspect, shown in Listing 3, will exploit,
through reflection, the value matched by optval at the oldopt() and newopt() join point to print the optimum before and after the change. The changes to the
current optimal solution are detected and reported in a similar way. To calculate
the number of iterations to get the optimum we have to look for the recursive invocations
of the main method (packSack()), to count them and to report the total at
the end. The count() and end() join points are, respectively, where to increment
the total number of iterations and where to print it. The aspect will introduce a
new variable (counter) to the application and the advice will work on this variable,
incrementing it at the count() join point and printing it at the end() join point.

Listing 3: The DebugAspect Used to Monitor the Knapsack Algorithm.
Parallelizing the Mandelbrot Algorithm.
Another interesting example application of the Blueprint approach is the parallelization
of a method. Let’s suppose one is interested in parallel execution of a
method. By using the Blueprint region join point we can indicate which portion of
the method behavior can be executed concurrently and in another thread/process.
In [9], Isberg adopts AspectJ 5 to develop a similar idea; in particular, he uses the
annotations to mark the method (and not part of its body) to render parallel. The
Blueprint approach is more flexible that AspectJ because any portion of a method
can be parallelized, not only the whole method invocation.
We consider the classic example of paralleling the rendering of the Mandelbrot
fractals. Our scope is to draw the fractal by using four threads, one for each fourth of the drawing area.

Figure 4: The Blueprint to Paralleling a Method 
Listing 4: The Method to Calculate a Mandelbrot Fractal.
The Mandelbrot() method, reported in listing 4, computes the
fractal given a region in the complex plane (bound by the two complex numbers z1
and z2). The implemented algorithm subdivides the complex plane in four regions
(whose upper left corners are contained in the rects array), and performs the classic
Mandelbrot algorithm on each of them.
The parallelization is based on the presence of two new classes: ParallelTask and ParallelInfrastructure that we add to the system. These classes create
the necessary parallel infrastructure; the former represents a skeleton for the thread
execution with an empty run() method, that will be filled with the code extruded
by the aspect (listing 5, rows 21-23), the latter deals with a ThreadPool of four
threads, as required. These two classes are not relevant to the discussion and for
sake of brevity they are not reported, the details can be found in [20] chapter 6.
We use the blueprint and the aspect showed in Figure 4 to identify the portion
of the method and to execute it as an asynchronous method. To do this, we must
locate two join points:
- a local join point (called jp2) before the first statement will be added the
creation of a new instance of the parallelInfrastructure class, and
- a region join point (called jp1) that enclose the code portion that will be
replaced by the code to start a thread with the extruded code as the body of the run() method (see Listing 5).

Listing 5: The Paralleling Aspect.
The introduction of the ParallelingAspect aspect (see Listing 5 rows 12-23)
acts on the ParallelTask class by:
- adding six new fields (rows 13-15),
- adding a new constructor method (rows 17-20), and
- substituting the empty run() method with the run() method with the reflectively
extruded code (rows 21-23); note that introducing a method already
present in the class produce a local overriding of sorting.
6 RELATED WORK
The Blueprint framework is not the first attempt of dealing with the limitations of
the current join point selection mechanisms. In this section we report some of the
most significant attempts, without pretending to be exhaustive.
In [18], Nagy et al. propose a new approach to AOP by referring to program units
through their design intentions to answer the need of expressing semantic pointcuts.
Design intention is represented by annotated design information, which describes
for example the behavior of a program element or its intended meaning. Instead of
referring directly to the program, their approach provides a new language abstraction
to specify pointcuts based on some design information. Design information are
inserted inside the base program using annotations and they are associated manually,
derived on the presence of other design information and, through superimposition.
The key benefit of this approach is that it reduces direct dependencies between
the crosscutting concerns and the program source. Unfortunately, this approach
breaks the obliviousness [6] property. This property is broken because certain design
information has to be specified by the software engineer, and moreover the software
engineer must use a consistent and coherent set of design information for each subdomain
of an application.
In [5], Douence and Südholt propose an AO approach, called EAOP, based on the
observation of dynamic events. In EAOP, aspects are expressed by events emitted
during execution of the base program and are defined by two languages: a crosscut
language, that allows the definition of execution points where an aspect may modify
the base program, and the action language, which enables the execution of the
base program to be modified. The implemented tool supports four kinds of events:
method and constructor calls and their return events. This approach needs a prephase
to instrument the source code of the base program to generate events. We
think that new kinds of event would be necessary, since these kinds are not much
expressive. Moreover, the pointcut definition is strictly coupled with the base code,
since it contains method and constructor names. Finally, the base program must
be modified to insert the necessary events. In [4], the authors extended their work
to take into consideration the whole history of the program executions. These kind
of aspects are more expressive than those based on atomic points because relations
between execution events can be expressed. Join points may denote not only syntactic
information (e.g., instructions) but also semantic information (e.g., dynamic
values). Nevertheless, the crosscut definition is also strictly coupled to the base
code, since it contains, like in their previous work, program element names, such as
method names.
Tourwé et al. [25] have proposed an advanced pointcut managing environment,
based on machine learning techniques. They try to deal with the well-know problems
of the AOP languages by including the notion of inductively generated pointcuts in the language itself. In this way developers can specify pointcuts by using a
graphical interface, that offers a view on the source code, and an inductive logic
programming algorithm that is responsible for computing the pointcut definition.
This approach is more expressive and permits to overcome the previous problems,
but it still does not permit to identify a pointcut inside the method bodies. On the
contrary, since the inductive logic programming algorithm computes the pointcut
definition automatically, the developer no longer has precise control over this.
Gybels et al. [7] have dealt with the so called arranged pattern problem. Crosscutting
languages use pattern matching to capture join points. This is a good
technique to describe the intended semantics of a crosscut but it is still dependent
of the naming convention. Gybles et al. have proposed a more flexible linguistic
mechanism to implement crosscutting as patterns and consequently avoiding the
exposed pattern matching problem. Essentially, their crosscut language is a logic
programming language, based on Prolog. Their join point model is based on the
AspectJ one, since the join points are related to key events in the execution of an
object-oriented program. They use SmallTalk as a base language, and use the following
join points: message receptions by an object, message sends by an object, the
accessing and updating of an object’s state and the execution of code blocks. In [24], Stein et al. presented a new graphical approach to model pointcuts.
Their approach deals with modeling and graphical visualization of places and conditions
of crosscutting. At the implementation level, join points represent "hooks
where enhancements may be added", on modeling level, join points are rendered by
model elements. In particular, their approach uses UML classifiers to represent join
points in structural models, and UML messages to represent join points in behavioral
models. For the designation of join points they introduce a new graphical mechanism
called Join Point Designation Diagram (JPDD). A JPDD contains, when
fully specified, a description of structural and behavioral constraints. The structural
part is described with a notation that combines the syntax of class diagrams
and object diagrams, and the behavioral part is described by a notation based on
sequence diagrams. The approach is loosely coupled with the base program, and
follows a graphical approach like us, but by using JPDD it is not possible to identify
join points inside method body, between two instructions, since they use sequence
diagrams it is only possible to identifies join points on method calls.
In [14], Klein et al. presented a new semantics-based aspect weaving algorithm for
hierarchical message sequence charts (HMSCs). They chose HMCS as the scenario
model. Scenario languages are mainly used to describe behaviors of distributed
systems at an abstract level or to capture requirements in early development stages.
In this work, they used message sequence charts (MSC), that are very similar to UML
2.0 sequence diagrams, so the approach used in this paper could also be applied to
sequence diagrams as well. Behaviors and aspects are defined by using MSC. An
aspect defines a part of behavior that should be replaced by another one every time
it appears in the semantics of the base specification. This approach suffers from
several limitations: the matching process can only be performed if each join point
appears inside a bounded fragment of a behavior, another limitation is that the MSC
should not exhibit two non-disjoint cycles where the pointcut matches. Finally, since
it is based on sequence diagram it only possible to describe message between objects.
In [17], Mohd Ali and Rashid present a general state-based join point model.
The aim of their work is to expose high-level join points in the code, based on the
states and state transitions of the system, by providing a state-based AOP language
platform that allows such join points to be exposed. This approach turns to safety-critical systems, where to capture system states is an important part of the system.
Since a state-based pointcut construct permits to specify criteria for join points
that refer to the program’s current state (i.e., run-time values). In their notion,
a crosscutting system state is defined as an abstract state machine, and they use
the transitions of this abstract state machine that are controlled by state guards,
to identify the join points during the execution. This approach utilizes a join point
model conceptually different from AspectJ. It is very useful for safety-critical or realtime
systems, but for other kinds of applications, it is not so intuitive to use. In
addition, this approach is quite coupled to the base application, since it is necessary
to know the state models of system behavior.
7 CONCLUSIONS
Current aspect-oriented approaches suffer from well-known problems that rely on the
syntactic coupling established between the application and the aspects. A common
attempt to give a solution consists of freeing the pointcut definition language from
these limitations by describing the join points in a more semantic way.
This paper presents the Blueprint framework, a novel approach to join point
identification less coupled to the base-code and providing a finer granularity of
selection based on context description. Pointcuts are specified by using patterns
(blueprints) of the application expected behavior. More precisely, a join point
blueprint is a template on the application expected behavior identifying the join
points in their context. In particular join points are captured when the pattern
matches portion of the application behavior.
Compared to the current approaches, we can observe some advantages. First
of all, we have a more behavioral pointcut definition. In the join point blueprint
definition we identify the context of the computational flow we want to match, and
the precise point we want to capture. Notwithstanding that, we can still select the
join points by using syntactic and structural specification, which is only necessary
with a more detailed blueprint. Last but not least, our approach is quite general. It
can be applied to every programming language (at the cost of adapting the weaving
algorithm to the characteristics of the new language) and used to mimic all the other
approaches to AOP. There is also a drawback; the matching phase is quite complex
and demands time and space. Fortunately, most of the weaving phase is done once
during the compilation and does not affect the performance of the running program.
The Blueprint framework has been completely specified in [20] and a prototype
has been implemented. In the future, our plans include improving the prototype, to
realize a specific tool to draw the blueprints (at the moment we use Poseidon4UML7),
to organize the statement in class of equivalences for the actions (e.g., i++ and i=i+1 will be recognized by the same class) and to extend the reflective API. Finally, we
want to better check the scalability and robustness of the framework in the software evolution context.
ACKNOWLEDGEMENTS
The authors wish to thank Jeff Gray for his help in revising the English of this
paper and the anonymous reviewers for their help in improving the paper content
with their suggestions..
Footnotes
1 Please note, the Blueprint approach adopts a UML-like description since we use a subset of the
UML activity diagrams with some differences in their meaning and in general they have a different
role, all these differences should be clear going on in the reading.
2 Please note that the value and acceptance of "obliviousness" as a key AOP property is still
debated (e.g., [21]) but we consider it a desirable feature to some extent and therefore to b
considered.
3 Jode is available at http://jode.sourceforge.net.
4 Please note that in our case we are not concerned about the method captured by the pointcut,
but rather about the method that contains the captured join point.
5 Available at http://recoder.sourceforge.net.
6 Available at http://penguin.ewu.edu/~trolfe/Knapsack01/index.html.
7 http://www.gentleware.com
REFERENCES
[1] Walter Cazzola, Jean-Marc Jézéquel, and Awais Rashid. Semantic Join Point
Models: Motivations, Notions and Requirements. In Proceedings of SPLAT’06,
Bonn, Germany, March 2006.
[2] Walter Cazzola and Sonia Pini. Join Point Patterns: a High-Level Join Point
Selection Mechanism. In MoDELS’06 Satellite Events Proceedings, LNCS 4364,
pages 17–26, Genova, Italy, October 2006. Springer.
[3] Walter Cazzola, Sonia Pini, and Massimo Ancona. Design-Based Pointcuts
Robustness Against Software Evolution. In Proceedings of the 3rd ECOOP
Workshop on Reflection, AOP and Meta-Data for Software Evolution (RAMSE’
06), pages 35–45, Nantes, France, July 2006.
[4] Rémi Douence, Pascal Fradet, and Mario Südholt. Trace-Based AOP. In
Robert E. Filman, Tzilla Elrad, Siobhán Clarke, and Mehmet Akşit, editors, Aspect Oriented Software Development, chapter 9, pages 141–150. Addison-Wesley, October 2004.
[5] Rémi Douence and Mario Südholt. A Model and a Tool for Event-Based Aspect-Oriented Programming (EAOP). Technical Report TR 02/11/INFO, École des
Mines de Nantes, November 2002.
[6] Robert E. Filman and Daniel P. Friedman. Aspect-Oriented Programming is
Quantification and Obliviousness. In Proceedings of OOPSLA 2000 Workshop
on Advanced Separation of Concerns, Minneapolis, USA, October 2000.
[7] Kris Gybels and Johan Brichau. Arranging Language Features for More
Robust Pattern-Based Crosscuts. In Proceedings of the 2nd Int’l Conf. on
Aspect-Oriented Software Development (AOSD’03), pages 60–69, Boston, Massachusetts,
April 2003. [8] Christoph M. Hoffmann and Michael J. O’Donnell. Pattern Matching in Trees. Journal of ACM, 29(1):68–95, 1982.
[9] Wes Isberg. AOP@Work: Check out Library Aspects with AspectJ 5. January
2006. [10] Kazunori Kawauchi and Hidehiko Masuhara. Dataflow Pointcut for Integrity
Concerns. In Proceedings of the AOSD’04 Workshop on AOSD Technology for
Application-level Security, Lancaster, UK, March 2004.
[11] Andy Kellens, Kris Gybels, Johan Brichau, and Kim Mens. A Model-driven
Pointcut Language for More Robust Pointcuts. In Proceedings of SPLAT’06,
Bonn, Germany, March 2006.
[12] Gregor Kiczales, Erik Hilsdae, Jim Hugunin, Mik Kersten, Jeff Palm, and Bill
Griswold. An Overview of AspectJ. In Proceedings of ECOOP’01, pages 327–353, Budapest, Hungary, June 2001. ACM Press.
[13] Gregor Kiczales, John Lamping, Anurag Mendhekar, Chris Maeda, Cristina
Videira Lopes, Jean-Marc Loingtier, and John Irwin. Aspect-Oriented Programming.
In Proceedings of ECOOP’97, LNCS 1241, pages 220–242, Helsinki,
Finland, June 1997. Springer-Verlag.
[14] Jacques Klein, Loïc Hélouët, and Jean-Marc Jézéquel. Semantic-basedWeaving
of Scenarios. In Proceedings of AOSD’06, pages 27–38, Bonn, Germany, March
2006. ACM Press.
[15] Christian Koppen and Maximilian Störzer. PCDiff: Attacking the Fragile Pointcut
Problem. In Proceedings of the European Interactive Workshop on Aspects
in Software (EIWAS’04), Berlin, Germany, September 2004.
[16] Hsiao-Tsu Lu and Wuu Yang. A Simple Tree Pattern-Matching Algorithm.
In Proceedings of the Workshop on Algorithms and Theory of Computation,
Chiayi, Taiwan, December 2000.
[17] Noorazean Mohd Ali and Awais Rashid. A State-based Join Point Model for
AOP. In Proceedings of the 1st ECOOP Workshop on Views, Aspects and
Role (VAR’05), in 19th European Conference on Object-Oriented Programming
(ECOOP’05), Glasgow, Scotland, July 2005.
[18] István Nagy, Lodewijk Bergmans, Wilke Havinga, and Mehmet Akşit. Utilizing
Design Information in Aspect-Oriented Programming. In Proceedings of 4th
Annual International Conference on Object-Oriented and Internet-based Technologies,
Concepts, and Applications for a Networked World (Net.ObjectDays),
LNI 61, pages 39–60, Erfurt, Germany, September 2005.
[19] Harold Ossher and Peri Tarr. Hyper/J: Multi-Dimensional Separation of Concerns
for Java. In Proceedings of ICSE’01, pages 729–730, Toronto, Ontario,
Canada, 2001. IEEE Computer Society. [20] Sonia Pini. Blueprint: A High-Level Pattern Based AOP Language. PhD thesis,
Department of Informatics and Computer Science, Università di Genova,
Genoa, Italy, June 2007. [21] Awais Rashid and Ana Maria Moreira. Domain Models Are NOT Aspect Free.
In Proceedings of MoDELS’06, LNCS 4199, pages 155–169, Genoa, Italy, October
2006. Springer.
[22] J. Alan Robinson. A Machine-Oriented Logic Based on the Resolution Principle. Journal of the ACM, 12(1):23–41, January 1965.
[23] Kouhei Sakurai and Hidehiko Masuhara. Test-based Pointcuts: A Robust Pointcut
Mechanism Based on Unit Test Cases for Software Evolution. In Proceedings
of Linking Aspect Technology and Evolution revisited (LATE’07), Vancouver,
British Columbia, Canada, March 2007.
[24] Dominik Stein, Stefan Hanenberg, and Rainer Unland. Modeling Pointcuts.
In Proceedings of the AOSD Workshop on Aspect-Oriented Requirements Engineering
and Architecture Design, Lancaster, UK, March 2004.
[25] Tom Tourwé, Andy Kellens, Wim Vanderperren, and Frederik Vannieuwenhuyse.
Inductively Generated Pointcuts to Support Refactoring to Aspects. In Proceedings of SPLAT’04, Lancaster, UK, March 2004.
[26] Naoyasu Ubayashi, Genki Moriyama, Hidehiko Masuhara, and Tetsuo Tamai.
A Parameterized Interpreter for Modeling Different AOP Mechanisms. In Proceedings
of ASE’05, pages 194–203, Long Beach, CA, USA, 2005. ACM Press.
[27] Alexandre Vasseur. Dynamic AOP and Runtime Weaving for Java- How Does
AspectWerkz Address It? In Robert E. Filman, Michael Haupt, Katharina
Mehner, and Mira Mezini, editors, Proceedings of the 2004 Dynamic Aspect
Workshop (DAW’04), pages 135–145, Lancaster, England, March 2004.
About the authors

|
|
Walter Cazzola (Ph.D.) is currently an assistant professor at the
Department of Informatics and Communication (DICo) of the Università
degli Studi di Milano, Italy. His research interests include reflection,
aspect-oriented programming, programming methodologies
and languages. He has written and has served as reviewer of several
technical papers about reflection and aspect-oriented programming. He can be reached at cazzola@dico.unimi.it. |
|
|
Sonia Pini is a PhD student and research assistant at the Department
of Informatics and Computer Science (DISI) of Università degli
Studi di Genova, Italy. She can be reached at pini@disi.unige.it |
Cite this column as follows: Walter Cazzola and Sonia Pini: "On the Footprints of Join Points: The Blueprint Approach", in Journal of Object Technology, vol. 6, no. 7, Aspect-Oriented Modeling, August 2007, pp. 167-192 http://www.jot.fm/issues/issue_2007_08/article7
|