CEDRIC Research Report:
A Notation for Aspect-Oriented
Distributed Software Design

Renaud Pawlak

Laboratoire CEDRIC-CNAM, 55 rue Turbigo, 75003 Paris, France

Abstract

This research report presents a UML extension for distributed and aspect-oriented programming. It focuses on three concepts that allows the designer to express distributed applications in an aspect-oriented fashion: the groups, the aspect-classes, and the pointcut relations. Groups allow the designer to define the application at an abstract level that is independent from the application deployment or distribution scheme. The aspect-classes are new kinds classifiers that allow the designer to throw the basis of abstract protocols that reify the way a set of interfaces must be used in order to implement a given concern. Finally, the pointcut relations are used to actually add (weave) a new concern within the set of groups or objects that form the application. This notation allows the designer to express its application with improved separation of concerns and allows a direct mapping towards existing aspect-oriented languages and architectures. Introduced within a software engineering process, this notation will increase the reusability and the maintenability of software components.

1  Introduction: issues in Distributed Software Design

With the growth of the Internet and its world-wide use for business, leisure, or calculus, modern applications tend to be more and more distributed and shared by wide communities of users. Despite some standards begin to allow world-wide access of these applications (e.g. the Sun JSP), the world-wide deployment, maintenance, modification of these applications can be tricky and the programmers and architects are facing difficult issues.

First, for the same functional or business requirements, the fact that the application is distributed and used by a great deal of users makes some extra-concerns appear such as security, fault-tolerance, data-availability, or caching consistency.

Second, the design choices that are made during the development of distributed applications are more crucial than in centralized applications since design mistakes can lead to a total re-deployment of all the application's structure or concerns and make the project waste precious time.

Last but not least, most of the identified concerns inherently depend on the application final semantics and are tightly linked to the business concerns, making the modularization of distributed applications extremely difficult and leading to design dilemmas and hardly maintainable applications.

In the last few years, a new kind of software design solution is beginning to appear with the growing interest of the computer scientists community for the ideas coming from the Aspect-Oriented Programming (AOP) [4]. AOP is a neat and powerful way to modify the application semantics so that it supports several needed concerns. Neat because it ensures a very clean separation of all the application identified concerns. Powerful because it is supported at a programming level and thus does not require any extra design efforts to achieve the concerns mixins. We have been successfully experimenting these ideas on an Aspect-Oriented middleware called Java Aspect Components (JAC) [11] and several aspects have been implemented on it such as persistence, authentication, or distribution.

Lately, these programming-level ideas also tend to be applied at a design-level and many works based on UML [15] try to incorporate aspects within the application development cycle not only for the programming phase but also at the design phase [7,5]. We believe that the Aspect-Oriented Software Design (AOSD), is able to bring an homogeneous answer to the design issues that are hardly completely solved by most of the existing solutions. However, we also believe the AOSD alone is not sufficient to cope with all the issues brought by distribution. As a consequence, we couple the AO concepts with some extra abstractions that allow us to use the expressive power of AOSD for distributed applications. In this paper, we progressively describe a Distributed Aspect-Oriented Software Design (DAOSD) notation that comes from our concrete experience with JAC and show that it can be advantagely used to model and design complex distributed applications.

Firstly, section 2 focuses on the group notion, a key concept for DAOSD and shows how groups are tightly linked to aspects. Secondly, section 3 shows how aspects can be defined and used in a group-oriented world and what are the required concepts and their semantics. Finally, the last section gives a distributed application sample focusing on three aspects and showing how our notation allows the designer to define distributed applications with cleanly separated concerns.

2  Groups: a key modeling concept for DAOSD

2.1  Groups and distributed objects

As a background task, we have been working for several years on defining a Group-Oriented Paradigm (GOP) that allows the programmer to specify its applications not only with interoperating objects, but also with interoperating sets of objects [17]. Our motivation for this paradigm comes from the observation that, in an object-oriented distributed application, sets of distributed objects can often be related together by the fact that they interoperate to realize a functionality in a distributed fashion (e.g. a DNS lookup, a consistency protocol, ...). Thus, in exactly the same way the Object-Oriented Paradigm aggregates data and functions within a well-encapsulated entity, it seams very natural to group sets of distributed objects and distributed functionalities around a distributed - but well-encapsulated - entity called a group.

Despite some research projects within the distributed Operating Systems and Middleware community point out the need of a high-level language based on sets or groups of objects, for instance the Jgroup model [12]1, we think

In short, using groups as a design-level concept allows the designer to add a new point of view on the application model (which can be used as a refinement step) that defines distributed applications behaviors regardless the way they are actually distributed:

The last property allows us to distinguish client-groups and server-groups in quite the same way as client-objects and server-objects except that the interaction model can be more complex and more distributable.

Introducing a new modeling entity may seem confusing. However, the Group-Oriented Paradigm (GOP) is very natural since it is completely coherent with the Object-Oriented Paradigm (OOP). Table 1 shows the correspondence between the different concepts of the OOP and the GOP.

OOP GOP
Structuring unit object group
Functional unit object service group service
Implementation operation function evaluation (client-server) member-objects interaction
State set of encapsulated values set of member-objects
Typing implementation unit class group-class

Table 1: OOP vs GOP.

Figure 1 shows how groups abstract the distributed nature of some programs. The upper part of the figure describes a group-level specification of an abstract application that defines a viewer class that uses a document class (the used formalism is explained later in sections 2.3 and 2.4). Conceptually speaking, this viewer is able to invoke a search service on the document that returns all the locations of the given word within the given document.

*0.7!whyGOP.png

Figure 1: Centralized vs distributed implementations.

Concretely speaking, the implementation of this application can be very centralized or very distributed. The middle and lower parts of the figure show two extreme concrete implementation samples:

Thus, at an abstract specification level, groups allow the designer to express in the same way centralized and distributed program.

2.2  A simple case-study

Let us take the case-study (see figure 2) of a distributed application composed of some client front-ends using three objects (servers), each of them being instances of different classes (they provide a different subset of services). Imagine now that someone provides you a Cache class that you want to use to improve your program performances by caching some results of your objects methods.

*0.5!case_study.png

Figure 2: A simple case study: introducing a caching concern.

There are currently four different means to make the application handle this new concern.

  1. Naively modify the classes implementations to create caches and use them when needed: this solution is not good in terms of separation of concerns since the caching issue will be wired into your functional code. This tends to give poor evolving and hardly maintainable applications.
  2. Use design patterns to improve the separation between your application definition and the caching preoccupation. For instance, the designer can use the factory and the proxy patterns to make the caching policies more seamlessly used by the application objects. This solution tends to improve applications flexibility but the needs of expert designers are very expensive and it implies a very close link between analysis and design so that projects must use extreme development methodologies such as the Rational Unified Process [13], short refinement cycles, and probably reverse-engineering tools. Moreover, this approach tends to force the people re-build again and again the same application modules from scratch.
  3. Use an existing framework, i.e. a piece of operational implementation that is already designed and that uses a set of design patterns to provide a set of useful services in a seamless way. This is the case of the applications that use application servers for their development. For instance, within the component-based development environments that use the J2EE architectural specifications of SUN [9], the factory and the proxy patterns are already instantiated so that you do not need to implement them any more. However, frameworks have the important drawback to impose frontiers on what the application is supposed to do. Thus, in many cases, the framework user is not able to find a feature that really fits its needs and have to work without any help (like in the second solution). Moreover, using a new caching policy as we intend to do in our example requires the framework to be opened and highly configurable (despite this issue is a research path related to AOP, highly configurable frameworks are quite rare since they can be hard to configure and induce performances losses).
  4. Create or use a design-level meta-program that is able to transform your classes to make them use the caching features to implement this concern. This technique can be closely related to Generative Programming [8] or Model-Driven Architectures guidelines and can be very powerful since the transformation can be applied to a huge set of classes in an automatic way. These transformations can be parametrized by adding extra information on your program meta-model (in UML, this is a typical use of stereotypes and tagged values). This technique is already universally used by application designers since it is supported by most of the main UML tools such as Rational Rose or Softeam Objecteering (with the J language) [14]. However, writing a meta-program remains difficult and it explains why this technique only worths to be used for specifics requirements on huge programs (when the number of transformed classes is so important that the writing of a meta-program costs lesser than doing it manually).
As one can see, despite all the previously described solutions have some advantages regarding some criteria, none of them is entirely satisfying regarding maintenance criteria, especially when the application is distributed. Indeed, the design choices that are made during the development of distributed applications are even more crucial than in centralized applications since a conception mistake can lead to a total re-deployment of all the application's structure or concerns and make the project loose precious time. As a consequence, application designers may have to use a bunch of solutions together in order to be efficient in all cases so that the employed solutions heterogeneity makes the art of software design quite difficult and reserved to technical experts.

To work around this issue, we think that the distribution concern must be handled at the design-time and that the designer needs a suited modeling notation to express the fact that the application is distributed or not. Moreover, the notation should support separation of concerns so that an implementation change or evolution (such as adding a caching concerns) does not imply changes within the functional model of the application and does not interfere with the distribution concern. A first step to reach this goal is to abstract the distribution concern by using a group-oriented paradigm to design the application.

2.3  Groups definitions with UML

Regarding the GOP definition, it is quite straightforward to define groups in a high-level modeling language like UML. Indeed, since groups are the projection of the objects within an object-interaction based universe through an homomorphism, the same modeling language can be used for the groups. All we need is a way to distinguish the group-level elements from the regular ones. This can be easily done in UML by using a << group >> stereotype to mark the group-classes.

However, this is not sufficient since the designer should also be able to tell which objects are members or not of the group. This can be done by using a relation between the group and the members. The UML relation that is the closest from the membership semantics is the aggregation/composition (depending if members can be removed or added to a group during its life-time). Thus, we use a aggregation relation that is stereotyped with << membership >> to define what are the members of the groups.

One problem still remains when the group needs to exclude some instances of a given class regarding some criteria. Indeed, at a class-level, UML can only tell the number of instances that are related to the group but not which particular ones. We could solve this issue by using an object diagram but this solution is poorly supported by code generators and it is too static (the instances are chosen at design-time and cannot evolve). For this reasons, we choose to let the designer to tag the relation in order to filter the instances of the related class that must be members. This tagged value should be understood by the code generator and the generated code must be compliant with the target environment (for instance, the tagged value may be a regular expression on the name of the object as it is registered within the naming service if any).

*0.4!UMLgroup.png

Figure 3: Groups representation in UML.

2.4  Group interfaces

A group offers to its client(s) a set of functional services. These are the sum of the accessible group-level services of all the members of the group. By group-level service, we mean that an object that is not member of this group can access the service through the group interface. As explained in section 2.1, what is interesting with group-level services is that their locations are transparent for the client (the client do not know within which member-object(s) the service is implemented). It is the group-level service implementation role to decide which member is used, depending on the current interaction.

Discovering groups and group-classes is done exactly the same way objects and classes are discovered during a regular modeling process. For instance, all the caches form a group that provides a group caching interface that can be used by some other groups to implement caching. Figure 4 shows the definition of the Cache group-class for our example. It is composed of three members, all instances of the Cache class and provides group-level services that dispatch client group requests to the member-objects.

*0.25!UMLgroupInterf.png

Figure 4: Groups representation in UML.

2.5  Relating groups to aspects

In the caching sample explained in section 2.2, the semantics modification introduced by the caching concern into the application is quite symmetric. Concretely, it means that all the objects that are modified to implement caches (the server objects) can be seen as modified by the same abstract transformation rule. However, these objects are functionally heterogenous (in other words, they are not instances of the same type). Thus, another designation mechanism is needed to express the fact that a set of well-defined objects implements the same concern (here the caching one).

This need for a new kind of structured elements brings us to focus on the group notion. If we look at the group notion very carefully, we can notice that it is tightly linked to aspects. Indeed, contrary to a class that abstractly represents a set of instances realizing the same functional characteristics, a group is, in our definition, an abstract representation of a set of instances that do not necessary have homogeneous functional types but that are logically grouped together because they implement the same service (server-groups) or use the same one (client-groups).

*0.65!groupsnaspects.png

Figure 5: Relating aspects to group.

Figure 5 naively represents the application of the caching aspect on a group of servers that implements the server part of a simple client-server application. We use an instance diagram so that it becomes obvious that the group on the top of the figure is a non-uniform set of instances (the three instances a, b, and c belong to three different classes A, B and C). As shown on this figure, the application of the caching aspect creates a new group that contains instances of a Cache class that provides the caching functionality. In other words, we can say that these Cache instances belong to a server group that provides a caching functionality for the client group formed by the a, b, and c servers.

3  Modeling aspects in a group-oriented world

3.1  A group-based definition of aspects

Once the GOP is introduced as an entire part of the modeling language, the modeling of aspects becomes straightforward. In fact, if we take again the caching concern presented in sections 2.2 and 2.5, modeled through a GOP, it appears that the introduction of the caching concern within the original client-server application is abstractly done by the use of the services the Cache group interface provides to the servers group. This can be easily represented in UML by using the << use >> relation as represented in figure 6. In the general case, implementing a new concern may require the use of several group-level interfaces. In these cases, several clients can be related to several servers through some << use >> relations.

Finally, a simple but sufficient definition of an aspect within this context is the following.

Definition:
an aspect is the implementation of one or many use-provide relationship(s) between one or many client-group(s) and one or many server-groups.

*0.75!tot.png

Figure 6: The use relationship between a client-group (the base program) and a server group (the aspect program).

The model of figure 6 clearly brings up a use-provide relationship between a client-group (the servers), and a server-group (the caches) that defines the group-level services getValue(), setValue(Object) and invalidate(). This relationship implementation requires the application to modify the client-group member-objects implementation to introduce the caching concern within the application. If this concern implementation is modularized (i.e. if the code that implements the caching concern introduction is locally defined), then the implementation technique follows the AOP guidelines and we can call the obtained module an aspect.

To express the fact that a use-provide relationship is implemented in an aspect-oriented fashion, the application designer must add a tagged value ''aspect:aspectName'' to all the << use >> relationships implemented by the aspect called aspectName (see figure 6).

Thus group-oriented modeling allows the designer to explicit in a comprehensive way what parts of the distributed application are aspects and what parts are not2. In fact, for each modeled group-level use-provide relationship, aspect-oriented techniques can be used to separate concerns within the final implementation.

We now show how we model the use-provide relationship in our next step of refinement. Accordingly to Aspect-Oriented guidelines, this modeling phase preserves the separation of concerns and do not modify the client-group definition. Therefore, to precisely define the relation semantics, we need to introduce new modeling concepts.

3.2  Aspect-Oriented refinement of the group use-provide relationship

3.2.1  Aspect diagrams

The main difference between aspect-oriented design and other classical design is that the first furnishes some concepts to allow the designer to externalize the dependencies that inherently exist when a client uses a set of services for its implementation.

We recommend to model related use-provide relations within separated diagrams. Since these diagrams use the aspect-oriented design features, we call it an aspect-diagram.

3.2.2  Aspect-classes

Aspect-diagrams central elements are aspect-classes. An aspect-class is like a regular class (with attributes and regular methods), except that it can contain methods that may have particular semantics. Globally speaking, the ideas of all these semantics is to enable a semantics extension on a given client-group implementation point so that it actually uses a server-group (such as a cache group). In other words, an aspect-class is the definition of an abstract protocol that throws the basis and generic rules on how to use a set of services in order to implement a concern.

Aspect-methods parameters have special semantics. Some optional Meta-Object Protocol [16] (MOP) arguments can be defined to dynamically access some information on the client-group interaction point within the aspect-method implantation. The MOP arguments depends on the target aspect system and can be of different nature depending on the employed implementation technique. In addition to MOP arguments, aspect-methods can also define and use special kind of arguments called contextual arguments. Contextual arguments do not need to be explicitly passed by the client but can be dynamically set by any object implementation. When a contextual argument is defined at a point of the execution flow, then it is valid for all the subsequent object interactions and passed to all the aspect-methods that need it.

The designer can explicit one of the aspect-method extending semantics by using one of the furnished stereotypes on the methods of the aspect-class. Here are the possible stereotypes and the meanings of the method typed with them.

Note that the before, after, around, and replace methods modify interaction points (i.e. method invocations or executions). They actively change the client-group semantics. Note that even if the targeted aspect-oriented environment does not support exactly these extensions means, some equivalent possibilities should be provided.

On contrary, role method is an extension means that does not modify any execution point but adds some properties to existing objects (the modified point is here more structural). The role mechanism can be related to the specialization mechanism but in an aspect-oriented fashion.

*1!aspectClass.png

Figure 7: The aspect-class defines an abstract use protocol of one or several interfaces.

Figure 7 shows the caching aspect-class (with the << aspect >> stereotype) of our example. It defines a whenWrite << after >> method that sets the value of the cache (using setValue) and a whenRead << around >> method that reads the value from the cache (using getValue) except if the contextual parameter forceInvalidate is defined. As any class, an aspect can handle an association towards other classes, here the Cache group class.

3.2.3  Pointcut relations

A pointcut relation allows the designer to link some aspect-methods to some points of the client-group. Depending on the target aspect-system, a pointcut can be of different nature such as a class, a set of objects, or a set of methods. In our methodology, the pointcut can be associated to a group to express the fact that the modification implemented by the aspect not only crosscuts the program locally, but also on a set of distributed objects that can be located on different physical hosts.

The pointcut relation is an oriented association from an aspect-class towards a class or a group. It particularizes how the aspect-class methods actually modify the base-class or group implementation (i.e. the client-side of the AO use-provide relation). The association is stereotyped with << pointcut >> and the roles have very special semantics since they are used to tell which methods of the client-group are extended and by which aspect-methods.

*0.85!pointcut.png

Figure 8: The pointcut association: relating aspects to base-entities.

Here is the detailed semantics (refer to figure 8):

Keyword Points out
ALLall the methods of I
CONSTRUCTORSall the constructors instance methods of I
SETTERSall the methods of I that are setters
GETTERSall the methods of I that are getters
SETTER(attrname)the setter of a given attribute
GETTER(attrname)the getter of a given attribute
MODIFIERSall the methods of I that modify some instances states
MODIFIERS({attrnames})all the methods of I that modify the instances fields contained in the {attrnames} list

Table 2: Allowed keywords within the ! and ? locations

Notes:
Regarding table 2, if you need to point out methods that are located in other classes, then you can use the notation: className.methods. For instance, !myClass.SETTERS points out all the setters invocations of the class myClass.
By default, all the methods are instance methods (except constructors). To change this and work on static methods, you may add a modifier such as ''static:'' before the expression (!static:ALL denotes all the static methods invocations).
Figure 9 shows the use of two pointcut relations to finalize our caching aspect (implementation of the group-level use-provide relation shown in figure 6).

*1!useProvideImpl.png

Figure 9: Implementing the use-provide relationship in an AO fashion.

3.3  Implementation locations

3.3.1  Client or server pointcuts?

When a group uses another group to extend its functional or non-functional characteristics, (in our example, the server group becomes a cached server-group by using the cache group), the location where the server services (here the cache services) are implemented is not always clearly specified at a group-level. However, within distributed environments, these implementations locations may be crucial for the final willed semantics.

For instance, if we take the cache example, it is quite obvious that the resulting effects of the cache services implementation are not the same if they are located on the server sites or if they are located on the client sites. In the first case, caches allow the servers to avoid heavy calculus if several read accesses are performed from the clients (thus reducing the CPU usage). In the second case, the caches avoid network traffic by enabling local accesses on the read data. Both implementations are valid and can be used separately or together depending on the application.

Thus, when using our methodology to model aspect-oriented applications within distributed environments, the designer should be aware of this issue and locate the pointcuts at the client-side, or at the server-side.

3.3.2  Using located pointcuts

*0.5!clientNserverCache.png

Figure 10: Locating the pointcuts at client-side.

If we look again at figure 9, we can say that it is a server-side caching policy since the members of the group are the a, b, and c servers (the pointcut is defined on the group Server).

If we now want to design a caching policy that implements some caches at client-side, we can process as depicted in figure 10. First we define the client and the server groups. The client-group uses the server-group through a << use >> relationship which means that it exists some group-level interaction between them. Then, we precise that the cache group is used by the client-group and not by the server one (upper part of the figure). The lower part of the figure shows the refinement of this model with a caching aspect. Note that the pointcut relationship ends to the Client group-class (and not to the server anymore) and that the pointcut denotes the client-side invocations (the ! symbol) of the Server services (and not the server-side execution (the ? symbol)).

Notice also that in our client-side cache implementation, we only use the whenRead role for applying the caching aspect. In fact, when the caches are located on the clients, we assume that they can not write any data to the servers since it would bring some consistency issues3. If some writing accesses are actually performed, then the application programmer must add a consistency aspect that defines the whenWrite role and, for instance, invalidate all the clients caches when such an event occurs.

3.3.3  Samples of located aspects

We have been tested our modeling on several aspects. Most of them are fully implemented within the JAC [11] platform. Table 3 sums up the locations of their pointcuts.

AspectLocationTask
authenticationclient-pointcutasks the user to login
server-pointcutchecks the validity of the user informations
sessionclient-pointcutlinks the user informations to the session id, saves them locally if needed
server-pointcutnone
persistenceclient-pointcutnone
server-pointcutsaves the data that is written within a storage
GUIclient-pointcutasks for the parameters of the invoked services if needed
server-pointcutupdates the objects views if their states change
crypting (not implemented yet)client-pointcutencodes the data
server-pointcutdecodes the data

Table 3: Pointcut locations of a bunch of aspects.

4  A case study: three complementary aspects for a simple distributed application

4.1  Modeling the authentication aspect

4.1.1  Find out the groups and their dependencies

Within a simple distributed application, we assume that some servers located on several sites implement a set of services for a set a clients that are located on other sites. The servers form a group Server with an interface that is known from the clients. At a group-level, we do not have to represent the way the group services are accessed and where they are implemented. Symmetrically, the clients that access the servers from a group Client that can be formed of an undefined number of members located on remote sites. All the actual distribution information of the group will be defined in further refinement steps. At this level, the only interesting information is that the client-group uses some services of the server-group. This is materialized by a << use >> relationship (see the lower part of figure 11).

*1!authenticationAspect1.png

Figure 11: Modeling the authentication aspect, step 1.

Regarding the authentication concern, the choice is up to the designer. A quite classical choice is to define the authentication as follows:

At the client-side, the needed service is provided by the showInput of the Display interface. At the server-side, the needed service is provided by the checkAuthInfos of the Authentication interface. The use of the << group >> stereotypes implies that we abstract the location of the used services. Indeed, the display and the authentication services may be implemented on other sites than the clients or the servers that use them. At this specification level, two simple << use >> relationships are sufficient (see the upper part of figure 11).

Once the dependencies are made between the different identified groups, the designer must choose which of them may be implemented in an aspect-oriented fashion (as depicted in section 3.1). Figure 12 shows the aspect:authentication tagged relationships that pose the bases of the authentication aspect specification.

*0.6!authenticationAspect2.png

Figure 12: Modeling the authentication aspect, step 2.

4.1.2  Define the aspect and the pointcut relationships

Once the dependency diagram is made, all the dependencies that handle the authentication concern can be defined as an aspect. Deciding which relationship is part of an aspect or not is domain dependent and it is the designer, helped by a domain expert that decides which set of relationships must be modularize in an aspect depending on their logical understanding and experiences.

*0.5!authenticationAspect3.png

Figure 13: Modeling the authentication aspect, step 3.

Figure 13 shows a possible modularization of the authentication aspect that we consider to be relevant to our experience. Note that each pointcut defined by an aspect is most of the time the same as the number of << use >> found in the previous step.

The two << before >> methods of the aspects define behavior to add before a server service invocation or execution. Each one of the pointcut relationships corresponds to a method and thus defines to which member objects the aspect methods must be applied and the location of these applications. The diagram can then be read as follows.

Also note that the << use >> link towards the authentication group can be replaced by a more concrete relation that expresses the fact that the aspect handles a group reference on the authentication. In further refinement steps, this reference may allow the server to perform local authentication or remote authentication on shared but secure authentication server(s).

4.1.3  Programming the aspect-methods

The programming of the aspect-methods can be done in several general-purpose aspect-oriented languages such as AspectJ [3] or JAC [11].

The following code is the JAC version of the client-side and server-side aspect-methods.

public Object askAuthInfos() {

  // get the display reference from the context

  // note that this contextual attribute must be set by the 

  // client program or by another aspect such as a GUI aspect

  Display display = (Display)attr("display");

  if (display==null) throw new InvalidDisplayException();

  String[] authInfos = new String[2];

  // open an input box to ask the infos (this is a 

  // thread-blocking call)

  display.showInput(authInfos);

  // put the user answer in the context

  attrdef("user", authInfos[0]);

  attrdef("password", authInfos[1]);

  // proceed the invocation

  return proceed();


  

public Object checkAuthInfos() {

  // get the authentication information from the context

  String user = (String)attr("user");

  String password = (String)attr("password");

  // ask the authentication server to authenticate this 

  // user (a false return value means that the access 

  // is not granted for this user)

  if( ! authentication.authenticate(user, password) )

    throw new AccessDeniedException();

  return proceed();

}

4.2  Short models for privacy and session aspects

In this section, we define two other useful aspects. Since the authentication aspect has been detailed and that we now want to focus on the composition issues, we just furnish the final UML model.

4.2.1  The privacy aspect

Within a distributed environment, having an authentication aspect alone is not sufficient to bring a fully trustable security. Indeed, the user and the password data are private and must not be compromized. Consequently, a privacy aspect should also be used so that the application is secure.

Figure 14 shows the fully modeled privacy aspect that uses a encryption algorithm based on public host certificates and private keys. It works in both directions, i.e. it encrypts/decrypts the parameters and the returned value when a remote service is invoked.

*1!privacy.png

Figure 14: Modeling the privacy aspect.

4.2.2  Modeling the session aspect

One detail still needs to be handled by the distributed applications when the clients use the remote services. Indeed, for the moment, the two over-depicted aspects are working on each interaction independently. This means, for instance, that the system asks the client to authenticate each time it accesses a remote service. Thus, the system should be able to handle a sequence of interactions (coming from the same client host) as part of the same client's session.

Figure 15 shows how we implement this feature. In fact, the sessions can be described as client-side persistence features. The two aspect methods are used to save the sessions related informations within a storage (that can be volatile in some cases). The session data are related to the current user context and can be various private informations depending on the other aspects that are woven in the system (for instance, it can be a user, a password, or a crypting private key). Once the session information are saved, they are restored before any other manipulations so that the other aspects do not have to fetch them anymore (by asking to a remote server or by interactively requesting the user to fill the missing data through an input/output device).

*0.6!session.png

Figure 15: Modeling the session aspect.

4.2.3  Composing the aspects

The use of before, after, or around aspect methods implies that the aspects are potentially able to compose well together since all the extensions that are provided by the aspects consists in adding some extra behavior to the existing programs. The aspect-oriented technology provides the mechanisms and the support to compose the extensions in a controlled and secure way. However, these composition mechanisms may depend on the target system. Thus, the best way to configure the aspect composition is to allow the user to add a set of composition rules on the classes of the base application (the one that support the aspects). These composition rules are tagged values that are platform dependent.

If the target platform is JAC (or AspectJ), then the composition rules can be expressed as a list of precedence rules between all the aspect methods. By expressing these precedence rules, the designer avoids conflicting semantics that could arise when aspects are composed together. By the time, there are no other means than the natural language to really explain why an aspect method must be called before or after another one since it sometimes depends on the appreciation and experience of the designer4.

*0.8!composition.png

Figure 16: Tackling the composition issue.

 

At the client-side, the compRule tagged value showed on the diagram of figure 16 can be detailed as the following.

  1. We first try to restore the session data (so that, if we are actually part of a given session, we do not open a new one and we restore its context if needed).
  2. Then we ask the authentication informations to the user by opening a popup. Of course if the authentication informations are already in the context (i.e. restored by the session aspect), we do not open a popup see the code of the aspect method given in section 4.1.3.
  3. We ask for the server host certificate (note that this aspect method is called only once and that it could be called before the authentication).
  4. We save the session parameters in a client storage so that the certificate, and the authentication information are memorized and can be restore if further invocations are performed to this service.
  5. We then encode the parameters with the privacy aspect so that the data of the call and the context (i.e. the user and the password) are safely remotely transmitted.
  6. Here we proceed the invocation of the server method since all the before aspect method has been called.
  7. Note that the decoding of the result (privacy.decodeResult) is not mentioned since its order regarding the other aspect methods is not important. Indeed, it is the only after method and there are thus no possible semantical conflicts with other aspects.
At the server-side, the compRule tagged value showed on the diagram of figure 16 can be detailed as the following (note that it is more simple since the user cannot interact.

  1. We decode the encoded parameters.
  2. We check the authentication information to ensure confidency (privacy + authentication => confidency).
  3. Here, if the previous operations did not failed, we proceed the server method execution since all the before aspect method has been called.
  4. We encode the result (same remark as the result decoding at the client-side).
Note that tricky composition issues may arise when a lot of aspects are composed together. Especially, some performance and reusability problems eventually have to be solved in complex systems and precedence rules may not be sufficient in these cases. The JAC system proposes a reification of the composition issues to handle this and proposes a special aspect called a composition aspect. Details on this are available in [10].

5  Conclusion and future works

This paper proposes a UML notation to design applications in an Aspect-Oriented fashion that is also valid for distributed applications. Our effort is bottom-up and all the presented concepts are extracted from a practical programming approach and are thus concretely linked to the actual problems encountered when achieving separation of concerns. However, we also tried to be as independent as possible from low-level paradigm and we believe that this notation can be successfully applied to several target AO platforms or languages such as AspectJ and even to regular ones. In this last case the transformations achieved to map the UML design towards the concrete implementation are more complex.

In this paper, we lack some place to explain how distributed applications are refined. However, in [1] we present an Aspect-Oriented refinement model that allow the designer to deploy and distribute its application in an Aspect-Oriented fashion. With this architecture implemented in JAC, Aspect-Oriented applications defined in our notation can be refined towards an actually running distributed application.

In the future, this notation should be supported by UML tools such as Rational Rose or ArgoUML, so that advanced separation of concerns is support for all the steps of the software development. To us, this full support should greatly enhance the software specifications and implementations quality.

References

[1]
An Aspect-Oriented Architecture for Distribution and Deployment. R. Pawlak, L. Duchien, G.Florin, L.Martelli, and L. Seinturier. Submitted for publication.
[2]
An Automatic Aspect Weaver with a Reflective Programming Language. R. Pawlak, L. Duchien, and G. Florin. In Proceedings of Reflection'99.
[3]
AspectJ Home Page. http://aspectj.org.
[4]
Aspect-Oriented Programming. G. Kiczales, J. Lamping, A. Mendhekar, C. Maeda, C.V. Lopes, J.M. Loingtier, and J. Irwin. Proceedings of the European Conference on Object-Oriented Programming (ECOOP'97).
[5]
A UML Profile for Aspect Oriented Modeling. O. Aldawud, T. Elrad, and A. Bader. Workshop on AOP, OOPSLA 2001.
[6]
Design Patterns: Elements of Reusable Object-Oriented Software. E. Gamma, R. Helm, R. Johnson, and J. Vlissides. Addison-Wesley, 1995.
[7]
Extending UML with Aspects: Aspect Support in the Design Phase. J.Suzuki and Y. Yamamoto. 3rd AOP Workshop at ECOOP'99.
[8]
Generative Programming: Methods, Tools, and Applications. Krysztof Czarnecki and Ulrich Eisenecker. Addison-Wesley, 2000.
[9]
J2EE web page at SUN. http://java.sun.com/j2ee/.
[10]
JAC: A Flexible Solution for Aspect-Oriented Programming in Java. Renaud Pawlak, Lionel Seinturier, Laurence Duchien, and Gérard Florin. In Procedings of Reflection 2001, LNCS 2192, p. 1 ff.
[11]
JAC Home Page. http://jac.aopsys.com.
[12]
Jgroup Tutorial and Programmer's Manual. A. Montresor. Technical Report UBLCS 2000-13, September 2000. http://www.cs.unibo.it/projects/jgroup.
[13]
RUP web page at Rational. http://www.rational.com/products/rup/.
[14]
UML Profiles and the J Language: Totally Control your Application Development using UML. White Paper, Softeam 1999. http://www.softeam.fr/.
[15]
UML Resource Page. http://www.omg.org/technology/uml/.
[16]
The Art of the Metaobject Protocol. G. Kiczales and J. des Rivieres and D.G. Bobrow. MIT Press, 1991.
[17]
Towards a Language for Groups of Distributed Objects. R. Pawlak, Lionel Seinturier, L. Duchien, G. Florin, and Laurent Martelli. Reflective Middleware 2000.


Footnotes:

1Jgroup proposes a very interesting programming platform over Java where the programmer can use and manipulate groups of distributed replicas to construct reliable applications

2Note that this model is also valid for regular classes. Groups are here used as an abstraction to get rid of the distribution issues at this specification step.

3This kind of implementation is typically used by Internet navigators such as IExplorer or Netscape.

4However, some automatic rules can be valid if we restrain the possible semantics of the aspect-method. A first explanation on these rules have been presented in [2] and is still being investigated in more detailed research.


File translated from TEX by TTH, version 3.06.
On 3 Apr 2002, 19:58.