Previous article

Next article


User-Defined Join Point Selectors
An Extension Mechanism for Pointcut Languages

Cristiano Breuel, CS Department, University of São Paulo, Brazil
Francisco Reverbel,
CS Department, University of São Paulo, Brazil

 

space REFEREED
ARTICLE


PDF Icon
PDF Version

Abstract

One of the main issues in contemporary AOP languages and frameworks is the expressiveness of the pointcut language. This paper proposes an extension mechanism for enriching pointcut languages with constructs that play the role of "new primitive pointcuts" and allow the creation of pointcuts with greater semantic value. Join point selectors are a generalization of the primitive pointcuts of current pointcut languages. Existing languages, however, do not allow users to create new join point selectors. We present a simple architecture for supporting user-defined join-point selectors as an extension mechanism implemented atop an existing AOP framework. We show examples of user-defined selectors that enhance the quality of pointcuts and make aspect development easier. Moreover, we show that our extension mechanism supports framework-specific selectors, which let aspects cross the boundary of a given framework while still respecting the modularity of that framework.


1 INTRODUCTION

As programming languages and paradigms evolve, they tend to provide better support for modularity and to let programmers work at higher levels of abstraction. By a ording the separation of crosscutting concerns, aspect-oriented programming (AOP) increases modularity. Nevertheless, programmers still need to deal with lower-level concepts in order to specify the so-called pointcuts — the sets of points at which those concerns crosscut the basic functionality of a program. This work aims at raising the level of abstraction of pointcut specifications. Our proposal allows programmers to define pointcuts in terms of higher-level concepts. It also improves the resiliency of pointcut definitions against changes in the base program. The present text is an updated and extended version of our previous paper [5].

Motivation

The AspectJ language [15] introduced a model for AOP that has been widely accepted and adopted by other aspect-oriented languages and frameworks, including open-source projects such as JBoss AOP [12], Spring AOP [13], and AspectWerkz [2]. In spite of di erences in syntax and in implementation approach, all such tools have similar capabilities and semantics [14] and o er similar pointcut languages.

Two significant limitations have been identified in current pointcut languages. The most frequent concern is that a pointcut may be "broken" by changes to the base program [10, 7, 19]. This limitation is known as the fragile pointcut problem [18]. Another issue is the difficulty or impossibility of expressing some pointcuts clearly and accurately [16].

Pointcut Quality

It is useful to set forth a criterion for comparing pointcut definitions. We define pointcut quality as the extent to which a given pointcut meets the following requirements:

  • Resilience: Changes in the base program should not a ect the pointcut negatively. More specifically, when a new join point is added to the program or an existing one is modified, the join point should be included in the set selected by the pointcut if and only if it matches the conditions intended by the pointcut author.
  • Clarity of purpose: A pointcut definition should make its intent clear to whoever reads it, and should be expressed in terms that are as close as possible to the problem at hand. In other words, it should be easy to understand and to modify a pointcut definition.

Example. One of the most frequent examples of AspectJ usage, the figure editor [15], has also been commonly used for exposing the shortcomings of that language [7, 8, 17]. It consists of a graphical editor, with several types of elements (squares, circles etc.), whose display must be updated whenever the state of some element changes. The program manages elements in the display as instances of class FigureElement and its subclasses (Figure 1). We want to create a "display updating" aspect that calls the Display.redraw() method in response to element modifications.

Figure 1: UML diagram for the figure editor example

The classic solution is an aspect that selects methods based on a naming convention, e.g. picking all methods whose names start with "set" defined in class FigureElement and its subclasses. A pointcut based on such a naming convention is a low-quality one, because it is not quite resilient (if someone implements a new method that alters some element but does not start with "set", the new method will not be selected) and does not clearly express its intent (which the reader must guess from the method prefix).

Another solution is to create an annotation that must be associated with updater methods, for example, @FigureUpdater. This solution improves the clarity of the pointcut, but still does not meet the resilience requirement (one can forget to use the annotation or accidentally remove it). Therefore, the quality of this pointcut is intermediary.

If we could specify a pointcut that explicitly selected all methods that alter fields read by the Display.redraw() method, then such pointcut would be of high quality. First, because it would state exactly what we intend to capture, and second, because it would be fully tolerant to changes in the base program. This kind of pointcut is what we wish to support.

Problem Statement

Our goal is to provide programmers with the means for defining pointcuts that have high quality, according to the definition in section 1. We want to allow pointcuts that are defined at a higher level of abstraction (closer to the problem at hand) and have greater semantic value (in the sense that they reflect their authors' intents in a more precise way).

Proposed Solution

Since the expressiveness of the pointcut language limits the ability of creating high quality pointcuts, an enrichment to pointcut languages is needed. We propose userde fi ned join point selectors as a simple extension mechanism for enhancing pointcut languages with constructs that play the role of "new primitive pointcuts".

Contributions of this Work

The major contributions of this work are the concept of user-definable join point selector (section 2), a prototype implementation of that concept on an existing AOP framework (section 3), and a set of examples of selector usage (section 4). These examples show that user-defined join point selectors allow aspect programmers to create high-quality pointcuts that were not previously possible. The paper also contains a discussion of related work (section 5) and our concluding remarks and future work ideas (section 6).

2 JOIN POINT SELECTORS

A join point selector is a function that, for a given set of arguments and a join point, determines whether the join point should be part of a pointcut. Selectors are intended to be used as boolean elements of pointcut expressions. Their evaluation starts at weave time and may proceed at run time. Accordingly, a join point selector has a weave-time part, which is activated by the weaver, and a run-time part, which may or may not act (at the discretion of the weave-time part) when the execution of the aspectized program reaches every candidate join point. Figure 2 shows the operation of a selector. If the weave-time part is unable to reach either a positive decision (the join point should be included in the pointcut) or a negative one (the join point should be excluded from the pointcut), then it specifies that the run-time part should be activated at the appropriate occasions. In other words, the run-time part acts if the information available at weave time is not enough to complete the decision.

Figure 2: The operation of a selector

In current aspect-oriented languages and frameworks, the concept of selector is represented by the so-called primitive pointcuts: \call", \execution", etc. Nevertheless, the programmer cannot define new selectors, as the algorithms that select join points are hard coded into the weaver. We consider that our proposed naming is important because it makes clear the distinction between a selection algorithm and its usage in pointcut expressions. The examples below illustrate that distinction:

  • call and within are selectors.
  • call(void *->setSize(..)) AND within(com.acme.*) is a pointcut expression.

In a pointcut language, join point selectors play a role similar to the one of procedures in a procedural language, methods in an object-oriented language and advice in an aspect-oriented language. The core characteristics that define join point selectors, and distinguish them from other extension mechanisms, are the following:

1. They can receive arguments. When used in pointcut expressions, a selector can receive arguments that are taken into account by its algorithm to make a decision.

2. They can form composite expressions. Boolean operators can be used to combine multiple selector occurrences within a pointcut expression.

They operate both at weave time and at run time. A simple and uniform scheme allows selectors to use weave-time information, run-time information, or both, and to complete the selection decision as early as possible.

These features make selectors a basic unit of functionality. Some of them are found in previous proposals (such as the proposals that we will discuss in section 5), but the combination of all three features makes join point selectors more expressive and easy to use.

3 AN IMPLEMENTATION OF USER-DEFINABLE SELECTORS

As a proof of concept, we have implemented support to user-defined join point selectors as an extension to the JBoss AOP [12] framework. The choice of JBoss AOP as a basis for the implementation was due to practical factors only. Since we had no conceptual reason to employ that specific framework, our approach is not limited to JBoss AOP and could be implemented in other aspect-oriented languages or frameworks that have similar concepts.

Selector Programmer's View

Users of join point selectors (pointcut programmers) view selectors as boolean functions that are applied to candidate join points and take such a join point as an implicit argument. From the viewpoint of a selector programmer, however, the selector is a Java class that implements the interface org.jboss.aop.selector.Selector shown in Listing 1. We defined that interface after an existing JBoss AOP interface: org.jboss.aop.pointcut.Pointcut, implemented by objects that internally represent pointcuts in that framework. Thanks to the similarity between both interfaces, we were able to consistently integrate selector functionality into the framework without changing a lot of JBoss AOP code.

There are two groups of methods in the Selector interface. Each of these groups has a method for every kind of primitive join point supported by the framework1: method calls, attribute reads and writes, etc. Therefore, a single selector can be applied to di erent kinds of join points. One may create a selector that picks heterogeneous join points, in case such a selector is needed.

Weave-time and run-time selector methods. The first group of methods is called by the weaver and corresponds to the weave-time part of the selector. Each of those methods performs selector evaluation at weave time, for a specific kind of join point. It returns a value of the enumeration type SelectionValue, which defines three constants: TRUE (the join point matches the selector criteria and should be included in the pointcut), FALSE (the join point does not match the selector criteria and should be excluded from the pointcut) and CHECK AT RUNTIME (a decision is not possible without run-time information). If a weave-time method returns this last constant, the weaver instruments the join point shadow [11] by inserting into the base code a call to the corresponding run-time method.

Listing 1: The Selector Interface

The second group of methods is the run-time part of the selector. If a call to a method of the first group determines that the selection decision can only be reached with run-time information, then the corresponding method of the second group will be called at run-time. The run-time calls happen as a result of the code instrumentation performed at weave time.

All selector methods receive a set of parameters that represent the join point upon which the selector is being evaluated. In the weave-time methods, that set contains a single parameter, which reifies the corresponding joint point shadow in the base code. The types of the weave-time parameters that reify join point shadows (CtMethod, CtConstructor, MethodCall, NewExpr, and CtField) are part of the Javassist API. Javassist [6] is a framework for structural reflection that reads and manipulates Java bytecode, but provides a high-level API that allows programmers to deal with elements of the Java language rather than with bytecode details. Javassist is the basis for all the bytecode manipulation in JBoss AOP. Through its API, selector developers have access to the program structure in a way that is much more e ective than standard Java reflection. The power of Javassist makes it possible to create selectors with weave-time methods that examine the internal structure of constructs such as classes or methods. An example of such a selector will be presented in section 4.

Run-time selector methods do not see Javassist types. In those methods, the set of parameters that represent the current join point comprises an instance of a class in java.lang.reflect (a Method, Constructor, or Field) that reifies the corresponding join point shadow in the base code, plus additional objects associated with the joint point at run-time (e.g., the target and the arguments of a method call).

Base class for selectors. To avoid the need for implementing all methods of the Selector interface when only some of them will be actually used, the convenience class SelectorBase implements that interface in a default (and trivial) way. Each selector method has in SelectorBase a default implementation that simply returns a constant value, which is either SelectionValue.FALSE (in the case of a weavetime method) or false (in the case of a run-time method). Selector programmers will typically create classes derived from SelectorBase, instead of writing classes that directly implement the Selector interface.

Selector declarations. Selectors must be declared in order to be recognized by the weaver. A selector declaration consists of metadata and takes one of the following forms: (i) an annotation in the selector class itself, or (ii) an XML element in a descriptor file. JBoss AOP already supported both declaration styles for all of its features, so we followed the same design choice. Listings 2 and 3 exemplify the two declaration styles by showing alternative declarations for the same selector.

Listing 2: A selector declaration through a Java annotation

Listing 3: A selector declaration through an XML element

In both declaration styles there is a name attribute, which specifies the selector name to be used in pointcut expressions. The XML version also has a class attribute, which specifies the fully qualified name of the selector class.

Pointcut Programmer's View

Selectors are used as boolean clauses in pointcut expressions. A selector clause has the same syntax as a method call: the selector name, followed by a commaseparated list of arguments, which is enclosed by parentheses. Selector clauses may be combined via boolean operators.

Listings 4 and 5 exemplify the usage of the selector named parameterTypeIs declared in the previous section. Listing 4 shows a pointcut expression defined in a Java annotation; Listing 5 shows an XML element that defines the same expression. These examples intend to select all executions of methods in class MyPOJO (execution clause) whose first parameter is an Integer (clause that starts with parameterTypeIs).

Listing 4: Selector clause in a pointcut expression defined by a Java annotation

Listing 5: Selector clause in a pointcut expression defined by an XML element

In our current prototype, the arguments of selector clauses must be strings. We plan to support other argument types in a future implementation. Note that the arguments of a selector clause appear within an attribute of an annotation or XML element. Since both the attribute and the selector argument (a string) are enclosed by quotes, the inner quotes must be escaped and thus they appear as “\"” within the annotation attribute and as \"" within the XML attribute.

Internal View

Our extension to JBoss AOP consists of the following modifications: (i) changes in the pointcut grammar of JBoss AOP to recognize selectors within pointcut expressions, (ii) the addition of new elements to the XML and annotation bindings to allow for selector declarations, and (iii) changes in the JBoss AOP weaver to add calls to run-time selectors where necessary.

4 EXAMPLES OF USER-DEFINED SELECTORS

This section presents examples that demonstrate how our proposal can improve pointcut quality. These examples are meant as a sample of the anticipated uses of join point selectors. Due to the open nature of selectors, it is not possible to anticipate all of their practical applications.

Parameter Type

This example was borrowed from [7], with a slight generalization. It consists of a selector that picks executions of methods with a parameter of a specified type in a specified position. (The pointcut examples of section 3 used such a selector to pick all methods whose first parameter is an Integer.) The purpose of this example is to show a very simple use of selectors to solve a problem that is not motivated by a realworld application, but nevertheless does not have an elegant answer in conventional aspect-oriented languages. We consider our solution simpler and more elegant than the one in [7], thanks to the clear separation between the static (weave-time) and dynamic (run-time) parts of the selector.

Declarations for the selector parameterTypeIs appeared in Listings 2 and 3. Listing 6 shows the selector class, which is derived from SelectorBase and implements two selector methods: the weave-time matcher that picks method executions and the corresponding run-time matcher.

The weave-time matcher looks at the declared type of the parameter at the specified position. If the declared parameter type is the same as the desired type or is a subtype of the desired type, it returns "join point matched". Otherwise, if the declared parameter type is a supertype of the desired type (for example, if the declared type is Object when we want an Integer), it defers the decision to run time. In all other cases, it returns "join point not matched". The run-time matcher is even simpler. It looks (via standard Java reflection) at the type of the actual parameter passed to the method at run time and checks if that type is compatible with the desired one. Note that there is no run-time penalty unless a dynamic check is truly needed.

Recall our comment on the possibility of creating a selector that picks heterogeneous join points. The selector parameterTypeIs could be easily modified to pick not only method executions, but also method calls, constructor executions, and constructor calls, whenever a method/constructor receives a parameter of a given type in a given position. The enhanced selector would simply have additional weavetime/ run-time matcher pairs, which would be implemented similarly to the pair of matcher methods in Listing 6.

Listing 6: A selector to pick methods with a parameter that is compatible with a specified type

Figure Editor

Let us revisit the figure editor scenario and create a selector that solves the pointcut quality problem identified in section 1. The new selector takes two parameters (a class name and a method name) that specify a reader method2. It picks all the executions of methods that can possibly update some field read by the reader method. Given such selector, a high-quality pointcut for the figure editor would simply use the following selector clause:

updatesStateReadBy("Display", "redraw")

With the new selector, the DisplayUpdating aspect (Figure 1) runs only after the executions of methods that alter fields read by the Display.redraw() method. Pointcut quality is high, because the pointcut is fully resilient to code changes and its intent is more clear to the reader than a naming pattern. Listing 7 shows an skeletal implementation of the new selector. The selector class is derived from SelectorBase and implements a single selector method: the weavetime matcher that picks method executions. In other words, the entire decision is based on static (weave-time) analysis.

Listing 7: A selector to pick join points that update fields read by a given method

By using the Javassist API, the weave-time matcher performs a recursive search to build the set of all fields that may be read by some control flow of the reader method. It then performs a similar search and builds the set of all fields that may be written by some control flow of the join point method (i.e., the method whose execution is the candidate join point that is being matched). If the intersection of those sets is not empty, it returns "join point matched". Otherwise (empty intersection), it returns "join point not matched".

Even though the selector performs static analysis only, its implementation is not simple. Both recursive searches take into account the subclasses of any types that may be reached by some sequence of nested calls from the root method (the reader method or the join point method). This is a conservative approach that presumes the worst-case scenario with respect to conditional statements and inheritance. It ensures that no correct match will be left out, but may also produce false matches.

Reflective Calls

Method calls performed via reflective techniques are becoming more and more used by infrastructural software such as frameworks and middleware, which often needs to invoke methods on application objects but has no prior knowledge of the interfaces of those objects. Conventional aspect-oriented languages do not currently offer a simple way of adding caller-side advice to reflective calls. Caller-side advice is important in scenarios that disallow the instrumentation of callee code.

JBoss AOP even provides a helper aspect for intercepting reflective calls to a specified method. That aspect actually intercepts all reflective calls and uses advice code to select just the calls to the specified method. Nevertheless, we think that a solution entirely based on pointcuts would be more appropriate for the following reasons: (i) the interception of reflective calls should be performed similarly to the interception of plain (non-reflective) calls, which is based on pointcuts, (ii) an additional aspect just to pick reflective calls is unwarranted complexity, and (iii) pointcuts are meant for join point selection, so using advice for that purpose is a departure from the intended usage of these AOP constructs.

We propose a specific selector, reflectiveCall, which takes two parameters (a class name and a method name) that specify a method3 and picks the reflective calls to that method. Listing 8 shows the implementation of the reflectiveCall selector. Again, the selector class is derived from SelectorBase and implements two selector methods: the weave-time matcher that picks method calls and the corresponding run-time matcher. When a call is performed through reflection, the called method can be determined only at run time. Thus the weave-time matcher simply flags every call to the invoke() method of java.lang.reflect.Method as requiring a run-time check. For any other method calls, it returns "join point not matched". The runtime matcher looks at the invoke() target, which is a java.lang.reflect.Method, and checks if this object represents the method specified by the selector parameters.

Listing 8: A selector for reflective method calls

Selector for Web Services

Various domain-specific languages (DSLs) have been proposed to tailor aspectoriented programming to specific problem domains. One such language is Doxpects [20], a DSL for processing XML documents in messages exchanged via SOAP. Doxpects allows the definition of pointcuts that specify XML elements within SOAP messages. Moreover, it exposes those elements to advice so that the elements can be processed in a convenient way. Essentially, the language introduces two new kinds of pointcuts: header and body, which match the header and the body of a SOAP
message. A header or body pointcut takes as argument an XPath query that selects a set of elements from the corresponding section (head or body) of the message.

In addition to the new pointcuts, the language also introduces two qualifiers for advice: request and response, which indicate if pointcut (header or body) evaluation will be performed on a request message or on a response message. The authors of Doxpects make a parallel between those qualifiers and AspectJ's before and after modifiers. Even so, a request or response qualifier can be regarded as a part of the pointcut definition, because it helps to determine the join point (the processing of a message, which is either an outgoing request or an incoming
response) that will be a ected by the advice.

We believe that specific selectors can be used as a substitute for a DSL in some scenarios. A selector-based solution for the processing of SOAP messages would include a selector for SOAP requests and another for SOAP responses. Listing 9 shows a skeletal implementation of a simple selector for SOAP requests.

Listing 9: A selector for XML elements in Web Services requests

This selector takes a single parameter, which is an XPath expression, and selects the outgoing requests that contain the XML elements specified by that expression. The selector class implements two selector methods: the weave-time matcher that picks method calls and the corresponding run-time matcher.

Let us assume that the underlying Web services framework has one or more sender methods, which take the actual responsibility for sending out SOAP requests. The weave-time matcher flags every call to a sender method as requiring a run-time check. For any other method calls, it returns "join point not matched". Let us also assume that a sender method receives as a parameter the SOAP request (an XML document) to be sent out. When the run-time matcher intercepts a call to the sender method, it has access to that parameter. It evaluates the XPath expression against the outgoing SOAP request. If the XPath evaluation produces a non-empty set of XML elements, the run-time matcher returns "join point matched". Otherwise, it returns "join point not matched". Note that our WsRequestSelector is specific to a given SOAP framework. In order to intercept sender methods and access the outgoing requests, it needs knowledge on certain details of that framework. The methods isWsRequestMethod and getWsDocument encapsulate that knowledge.

Framework-Specific Selectors

Pointcuts that use framework-specific metadata are a promising application area for selectors. It is often desirable to use framework metadata to decide which elements of a program should be a ected by an aspect. In many cases, a selector is the only way for a pointcut to employ framework metadata. Such situations arise, for instance, when the metadata is external to the Java code (e.g., metadata in XML files). In other cases, it would be possible to define a pointcut that accesses framework metadata without resorting to a selector, but the aspect programmer would need framework-specific knowledge in order to write the pointcut. This need would be a burden on the programmer and would generate excessive coupling.

We propose framework-specific selectors that let the programmer use framework concepts and metadata to define pointcuts in a modular way. Such selectors would encapsulate the framework details and would expose to the programmer high-level concepts. In this approach, framework-specific selectors would better be provided as parts of the framework upon which they rely, as a selector library that applications could use as they use the class and procedure libraries distributed with the framework. Such an arrangement respects the modularity of the framework and shields the application/aspect programmer from framework-specific details.

With the goal of validating the proposal outlined above, we have implemented a selector library for Hibernate [4], a popular framework for object/relational mapping. Our library has selectors that pick executions of persistent attribute getters, persistent attribute setters, primary key getters and primary key setters. It also has a withinPersistent selector, which picks classes that represent persistent entities. Listing 10 shows a selector for persistent attribute setters. The selector uses the framework itself to load the metadata.

Listing 10: A selector for Hibernate property setters

To show how the hibernateSetter selector can improve pointcut quality, we will compare two definitions for a pointcut intended to pick setters of persistent attributes of type java.util.Date.

The first pointcut definition, shown in Listing 11, uses a naming pattern to match the setters. This pointcut works under two assumptions: (i) that all classes under the package com.acme.someapp are mapped for persistence, and (ii) that all methods starting with "set" in those classes are setters for persistent attributes. If any of these assumptions fails, the pointcut will fail. Another drawback is that a programmer looking at this pointcut will not immediately know that its intent is to capture setters for persistent attributes. A comment would have to be added for that to become clear. Therefore, the pointcut has low quality: it has low tolerance to changes in the base program and does not communicate its intent clearly.

Listing 11: A pointcut based on naming conventions

In the second pointcut definition (Listing 12) we use the hibernateSetter selector to choose only the methods that are setters for persistent attributes. We still have a clause to filter execution of methods in a specific package and with specific parameter and return types, but we do not rely on a naming convention anymore. Additionally, it is clear to the programmer that we are picking only methods that are setters for persistent attributes managed by Hibernate. Therefore, we have enhanced the pointcut quality considerably. A major advantage of this approach is
that the access to framework-specific metadata is encapsulated inside the framework classes that are used by the selector. This way, artifact boundaries are crossed in a way that is transparent to the aspect programmer.

Listing 12: A pointcut based on the hibernateSetter selector

5 RELATED WORK

Several approaches have been proposed for improving the expressiveness of pointcut languages. Some authors have used logic languages as a basis for pointcut languages. In [9], a new aspect-oriented language, called Andrew, is proposed. It uses a logic language, similar to Prolog, for the definition of pointcuts. The base language over which the aspects are applied is Smalltalk, and this language's meta-information facilities are used as a basis for the join point model. In [10], the authors explain what features of their language make it a good fit for defining pointcuts.

In [17], the authors propose the aspect-oriented language Gamma, which is based on a simplified version of Java, for the base program, and on Prolog for pointcut definition. The main focus of this approach is on dynamic pointcuts. It uses a join point model that is based on a trace of the program execution, with timestamps associated with each point of the execution. This allows very easy definition of pointcuts that depend on the order of events, like cflow. However, this approach has serious limitations for practical use, and the authors regard the overcoming of these as future work. Alpha [19] is a logic-based language related to Gamma. It uses a less elegant model, but is more tractable in practice. Alpha works with four sources of information: a representation of the program's abstract syntax tree, a representation of its heap, the static type of every expression in the program, and a representation of the program execution trace.

In our view, logic languages are good for expressing the types of pointcuts that are most commonly used today: the ones that use only the basic join point model. However, they would be very hard to use in situations like the one we presented in section 4, when other sources of data are necessary besides the basic join point model. By using an imperative language, preferably the same in which the base program is written, users can take advantage of practically any data source they need.

In [8], the authors propose the use of the functional language XQuery as a replacement for current pointcut languages. They run XQuery on an XML representation of Java bytecode. The main shortcoming of their approach is that it employs only weave-time information. It also adds to the weaving process one more step, which builds the XML representation of the bytecode.

Josh [7] has a lot in common with our approach. It proposes an extension mechanism that is based on the same language as the base program, just as ours. It also uses the Javassist bytecode manipulation framework to obtain weave-time information about the program. The main di erence is that it does not deal with run-time information. If a run-time check is necessary, it must be explicitly inserted into the program through the bytecode manipulation framework. Such a task, which can be difficult and error-prone, is not needed in our approach.

The AOP part of the Spring framework [13] defines all of its pointcuts through Java classes. It has a mechanism for the combination of weave-time and run-time checks that is very similar to ours. However, it does not provide a language to easily combine pointcuts. Instead, it relies on verbose XML definitions. Moreover, Spring AOP does not give access to a powerful API for structural reflection that could be used for join point selection: it relies exclusively on standard Java reflection. That makes it difficult to use Spring AOP for implementing more powerful selectors, such as the one described in section 4.

The AspectBench Compiler (abc) [3] is a framework for experimentation of novel language features and implementation techniques in AspectJ. It supports extensions on the syntax of AspectJ, on its type system, and on the set of possible join points. abc also lets language researchers create new kinds of pointcuts and advice, as well as new semantic checks and optimizations. Its back-end pointcut language partitions the pointcuts in four categories: lexical pointcuts, shadow pointcuts, dynamic pointcuts, and compound pointcuts. This categorization makes it easier to compile
new primitive pointcuts into existing ones. abc also has a notion of dynamic residue, which in our terminology would correspond to the run-time part of a selector. Albeit powerful, abc is a complex framework. The complexity of abc may be an overkill for users, but that framework could certainly be used as the basis for a simpler extension mechanism, such as ours.

SCoPE [1] is an AspectJ compiler that supports user-defined analysis-based pointcuts. Rather than extending the language, SCoPE lets the programmer write pointcuts that analyze the base program by using a plain if pointcut with introspective reflection libraries. It introduced a novel compilation scheme based on a back-patching technique. Unlike our work, SCoPE does not deal with user-defined dynamic pointcuts. Nevertheless, its sophisticated static techniques could be applied to user-defined join point selectors in order to enhance weave-time matching.

6 CONCLUSION AND FUTURE WORK

Our work shows that extension mechanisms for pointcut languages can increase pointcut quality. It also enables the creation of new types of pointcuts that were not previously possible, such as those that depend on external metadata sources. Moreover, it lets framework implementors define framework-specific selectors, which allow aspects to cross the boundaries of a given framework and of its di erent artifacts, while still respecting the modularity of that framework.

A feature that will make user-defined join point selectors even more useful is the possibility of aggregating metadata and making such information available to advice implementors. That feature would be especially useful to selectors that take advantage of external metadata. This extension would also make it possible to implement a feature of the Doxpects DSL that the example in section 4 does not provide: the transformation of XML elements into Java objects, which are made available to advice programmers.

Finally, the combination of selectors could be easier if we made the following changes to the selector semantics:

  • Instead of receiving one join point as an argument, a selector would receive a set of join points;
  • Instead of returning a boolean, it would return a subset of the set of join points received as an argument.

These changes would make it possible to use the result of one selector as an argument to another one. For example, the updatesStateReadBy selector (section 4) could be divided in two selectors: the first one would select all fields read by a given method and the second would select all methods that update any of a given set of fi elds. Both selectors could then be reused independently.

Footnotes

1 Even though the Selector interface has methods for all kinds of join points, the vast majority of selectors implements just a few of these methods (typically one or two) in a non-trivial way. There are pros and cons to this approach, but its main motivation was coherence with the internal structure of JBoss AOP.

2 For simplicity, we are not dealing with overloaded methods.

3 For simplicity, we again disregard the case of overloaded methods.


REFERENCES

[1] Tomoyuki Aotani and Hidehiko Masuhara. SCoPE: an AspectJ compiler for supporting userde fi ned analysis-based pointcuts. In Proceedings of the 6th International Conference on Aspect-Oriented Software Development (AOSD 2007), pages 161-172. ACM Press, 2007.

[2] AspectWerkz Project. http://aspectwerkz.codehaus.org/, 2005.

[3] Pavel Avgustinov et al. abc: An extensible AspectJ compiler. In Proceedings of the 4th International Conference on Aspect-Oriented Software Development (AOSD 2005), pages 87- 98. ACM Press, 2005.

[4] Christian Bauer and Gavin King. Hibernate in Action. Manning, 2005.

[5] Cristiano Breuel and Francisco Reverbel. Join point selectors. In Proceedings of the 5th Workshop on Software Engineering Properties of Languages and Aspect Technologies (SPLAT 2007), pages 14-21. ACM Press, 2007.

[6] Shigeru Chiba. Load-time structural reflection in java. In Proceedings of the 14th European Conference on Object-Oriented Programming (ECOOP 2000), volume 1850 of Lecture Notes in Computer Science, pages 313-336. Springer, 2000.

[7] Shigeru Chiba and Kiyoshi Nakagawa. Josh: an open AspectJ-like language. In Proceedings of the 3rd International Conference on Aspect-Oriented Software Development (AOSD 2004), pages 102-111. ACM Press, 2004.

[8] Michael Eichberg, Mira Mezini, and Klaus Ostermann. Pointcuts as functional queries. In Proc. 2nd Asian Symposium on Programming Languages and Systems (APLAS 2004), volume 3302 of Lecture Notes in Computer Science, pages 366-381. Springer, 2004.

[9] K. Gybels. Using a logic language to express cross-cutting through dynamic joinpoints. In Second Workshop on Aspect-Oriented Software Development of the German Information Society. Institut für Informatik III, Universität Bonn, February 2002. Technical report IAI-TR-2002-1.

[10] Kris Gybels and Johan Brichau. Arranging language features for pattern-based crosscuts. In Proceedings of the 2nd International Conference on Aspect-Oriented Software Development
(AOSD 2003)
, pages 60-69. ACM Press, 2003.

[11] Erik Hilsdale and Jim Hugunin. Advice weaving in AspectJ. In Proceedings of the 3rd International Conference on Aspect-Oriented Software Development (AOSD 2004), pages 26- 35. ACM Press, 2004.

[12] JBoss AOP Project. JBoss AOP Reference Documentation (v1.3), 2005. http://docs.jboss.com/aop/1.3/aspect-framework/.

[13] Rod Johnson et al. Spring - Java/J2EE Application Framework Reference Documentation, 2006. http://static.springframework.org/spring/docs/2.0.0/reference/index.html.

[14] Mik Kersten. AOP@Work: AOP tools comparison, Part 1: Language mechanisms. Technical report, IBM Developer Works, February 2005.

[15] G. Kiczales et al. An overview of AspectJ. In Proceedings of the 15th European Conference on Object-Oriented Programming (ECOOP 2001), volume 2072 of Lecture Notes in Computer Science, pages 327-353. Springer-Verlag, 2001.

[16] Gregor Kiczales. The fun has just begun. Keynote at AOSD 2003, March 2003.

[17] Karl Klose and Klaus Ostermann. Back to the future: Pointcuts as predicates over traces. In Proc. 4th Workshop on Foundations of Aspect-Oriented Languages (FOAL 2005), 2005.

[18] Christian Koppen and Maximilian Störzer. PCDi : Attacking the fragile pointcut problem. In Kris Gybels, Stefan Hanenberg, Stephan Herrmann, and Jan Wloka, editors, European Interactive Workshop on Aspects in Software (EIWAS), September 2004.

[19] Klaus Ostermann, Mira Mezini, and Christoph Bockisch. Expressive pointcuts for increased modularity. In Proc. 19th European Conference on Object-Oriented Programming (ECOOP 2005), volume 3586 of Lecture Notes in Computer Science, pages 214-240. Springer, 2005.

[20] Eric Wohlstadter and Kris De Volder. Doxpects: aspects supporting XML transformation interfaces. In Proceedings of the 5th International Conference on Aspect-Oriented Software Development (AOSD 2006), pages 99-108. ACM Press, 2006.

About the authors



  Cristiano Breuel has a Computer Engineering degree from the University of São Paulo, Brazil, and a M.Sc. degree in Computer Science, also from the University of São Paulo. He can be reached at cmbreuel@ime.usp.br.


  Francisco Reverbel is a Professor of Computer Science at the University of São Paulo, Brazil. He has E.E. and M.Sc. degrees from the University of São Paulo and a Ph.D. from the University of New Mexico. He can be reached at reverbel@ime.usp.br. See also http://www.ime.usp.br/~reverbel/.

Cristiano Breuel, Francisco Reverbel: "User-Defined Join Point Selectors", in Journal of Object Technology, vol. 7, no. 9, Special Issue: SPLAT, December 2008, pages 5-24, http://www.jot.fm/issues/issue_2008_12/article1/

Previous article

Next article