1. A Framework for the Development of Multi-Level
Reflective Applications
Federico Valentino, Andrés Ramos, Claudia Marcos and Jane Pryor
ISISTAN Research Institute
Fac. de Ciencias Exactas, UNICEN
Pje. Arroyo Seco, B7001BBO Tandil, Bs. As., Argentina
Tel/Fax: +54-2293-440362/3
E-mail: {fvalenti,aramos,cmarcos,jpryor}@exa.unicen.edu.ar
URL: http://www.exa.unicen.edu.ar/~isistan
Abstract. Computational reflection has become a useful technique for developing
applications that are able to observe and modify their behaviour. Reflection has
evolved to the point where it is being used to address a variety of application
domains. This paper presents a reflective architecture that has been developed as a
framework that provides a flexible reflective mechanism for the development of a
wide range of applications. This architecture supports many meta-levels, where
each one may contain one or more planes. A plane groups components that deal
with the same functionality, and so enhances the separation of concerns in the
system. The reflective mechanism permits different types of reflection, and also
incorporates the runtime handling of potential conflicts between competing system
components. The design and implementation of this framework are described, and
an example illustrates its characteristics.
1. Introduction
Reflective architectures provide a degree of flexibility that allows designers to adapt
and add functionality to software systems in a transparent fashion. Since its onset,
computational reflection has been proposed and used for the solving of many different
problem domains in software engineering: aspect-oriented programming [PDF99,
PBC00], multi-agent systems [Zun00], concurrency programming [WY88, MMY93],
distributed systems [Str93, OI94, OIT92], and others.
A reflective system has the ability to reason about and act upon itself and adjust to
changing conditions [Mae87]. Reflection is a technique that has gained applicability
with the increasing use of object-oriented languages.
In an object-oriented reflective architecture a system has more than one level: a
base level consisting of the application itself, and a reflective level or meta-level that
observes and introduces additional functionality that is dependent on the state of the
program during execution. A reflective architecture therefore promotes the separation
of concerns [Par72] by distinguishing and organizing the software components
according to their functionality.
2. However, the separation of concerns offered by most reflective architectures is
limited to the base and meta levels. The meta or reflective level may contain
metaobjects with very different functionality, such as synchronization, logging,
exception handling, and so on. In consequence the benefits of an adequate separation
of concerns – greater comprehension, reduced complexity, adaptability,
customisability, reuse, etc. - is lost.
Another limitation arises when more than one metaobject is associated to the same
object, as problems of ordering, exclusion, and other conflicts may arise between
them. This may be solved in a static way by following the order in which they are
associated, but in some cases this will not be sufficient as their activation may depend
on more complex issues.
It is also important to support different reflective capabilities in order to offer
greater flexibility to the developer. This would permit the design of systems where the
types of reflection are applied in accordance to the functional requirements.
Current reflective systems do not provide the means to adequately handle these
issues. This paper describes a framework for the development of reflective systems
that include flexible reflective mechanisms for the separation of concerns and for the
solving of conflicts between competing metaobjects.
The framework supports a multi-level architecture where groups of components
that share the same basic functionality are grouped together in planes that observe and
interact with each other, supporting the separation of concerns down to the code level
in cases of crosscutting functionality.
Different types and levels of conflicts between metaobjects have been studied and
identified in this work. The framework supports the declaration and the handling of
the above-mentioned categories of conflicts.
The following section provides a brief description of computational reflection.
Section 3 describes the concept of planes in a reflective architecture, and the next
section consists of a description and categorisation of conflicts. The reflective
architecture is covered in section 5, followed by an example of an application. The
implementation is described in section 7, and the conclusions presented in section 8.
2. Computational Reflection
Computational reflection permits a system to observe and modify the properties of its
own behaviour, specially those properties that can be observed externally. Reflection
is a solution to the problem of creating applications capable of maintaining, using or
changing the representation of their own designs [Mae87, DS84, Coi88]. Reflective
systems are therefore capable of extending, modifying or analysing their behaviour.
In conventional systems, the data that is computed represents entities that are external
to the computational system. On the other hand, in reflective systems, the
computation is carried out on data that represents structural and computational aspects
of the same system.
In an object-oriented reflective architecture, the components that represent the
application and those that represent the system itself reside on two different levels: the
base level and the meta level (Figure 1).
3. • The base level contains the objects that solve a problem and return information
about the domain of the application or the external domain.
• The meta level contains objects that carry out computation about the system that
resides on the base level. The objects on the meta level are called metaobjects.
metaobjects
Meta Level
Association between base level
and meta-level.
Base Level
Objects at the Communication
base level between objects
Fig. 1. Reflective architecture.
This two level hierarchy can be generalised to include many meta-levels, becoming
an N-level architecture. In this type of architecture, each level carries out different
computation on the previous level.
As the functionality of the meta-level is orthogonal to the base level - i.e. it
crosscuts the basic functionality of the system - an association between the base and
the meta-level is defined in order to determine the points at which these levels interact
with each other. This association is established between the corresponding metaobject
of the meta-level and one or more elements (classes, methods and/or objects) at the
base level. At runtime, when an object at the base level receives a message, the
reflection mechanism redirects the control to the associated metaobject.
Four different reflective strategies which make up a reflection taxonomy have
been identified: class reflection, method reflection, object reflection, and method-
object reflection [Mar01]:
− Class reflection is that which is used when all instances of a class interact with an
orthogonal functionality.
− When only one method or set of methods of the class needs to incorporate this
functionality, method reflection is used.
− In some cases it is necessary to analyse a particular object of a class, where only
this object is associated to a metaobject of the meta-level: object reflection is then
used.
− It is also possible to combine method and object reflection when reflective
behaviour is added to a particular method of a specific object. This is known as
method-object reflection.
Another important characteristic in a reflective system is that which permits the
designer to determine when and how the meta-level is invoked: before the base
4. object, after the base object, and omitting the invocation of the method of the base
object.
The framework described in this work supports the different types of reflection
specified in the taxonomy. It also permits invocation of the meta-level before and/or
after the base method, with or without the invocation of the base method.
3. Planes in a Reflective Architecture
The architecture of a reflective application varies according to the reflection
requirements that are to be considered. In some cases it may be convenient for the
architecture to have various levels, where each level observes and interacts with the
others. Additionally, as there may be multiple functions at each level, the concept of
planes is introduced in order to obtain a clearer separation of concerns.
A plane is a set of metaobjects which carry out a specific functionality, as for
example logging or synchronisation of the system. Planes will ease the handling of
these groups of metaobjects, their re-use, their interaction with the rest of the system,
their maintainability, and so on.
The concept of plane is not to be confused with the concept of level or hierarchy of
levels. A level is a more abstract entity which may contain one or more planes which
observe other planes at inferior levels; this would be the case in a hierarchical
structure.
blo
BaseLevelObserver
dbo META LEVEL 2
so DBObserver
StatisticObserver
LOGGING PLANE
dbr META LEVEL 1
DBReader
pStore
stud collect ProfessorStore
StudentObserver
DataCollector sStore STORAGE PLANE
STATISTIC PLANE StudentStore
BASE LEVEL
Metaobject Nicholas Anderson
Advisor Mitchel Message
Student Metaobject
association
Professor Peter Collins
Invocation
John BASE PLANE
Fig. 2. Reflective Architecture with Planes
5. The architecture supported by the framework presented in this paper may have
many levels and planes organised in a heterarchical fashion, where a plane at one
level may observe planes at different levels. Thus, observation and interaction
between planes is not restricted.
Figure 2 shows an example of a three level architecture, where Meta Level 2
contains a plane which carries out the logging of the two inferior levels, Meta Level 1
and the Base Level. Meta Level 1 contains two planes: one that implements the
functionality necessary to carry out statistic calculations, and the other which is in
charge of storing data in a secondary storage medium. It is to be noted that the
organisation of the levels is not strictly hierarchical as one level observes more than
one inferior level.
The example shows that when an object at the base level receives a message, e.g.
John, there are three metaobjects - stud (Statistic), sStore (Storage) and blo
(Logging) – which are associated with it. This generates a potentially conflicting
situation as the associated metaobjects may be competing as to the order of execution,
and a different ordering renders different results.
Situations such as this one lead to the need to handle potential conflicts between
metaobjects. The following section describes categories and levels of conflicts and
their handling by the proposed system.
4. Conflicts between Metaobjects
An object at the base level may be associated to more than one metaobject, each of
the latter having their own behavioural objective. If the task to be carried out by each
metaobject is totally independent of the rest, the system will execute without any
problems. However, there may be problems or conflicts if two or more of these
metaobjects compete for activation.
For example, a specific metaobject may have to be executed before others, or the
execution of two metaobjects may produce an inconsistency and so the designer will
require that only one of them be executed. In these and other cases the designer can
specify the situation and the desired execution according to the type of conflict and/or
the application domain, and determine the priorities and activation policy of the
metaobjects.
The conflicts may be classified as static or dynamic. Static conflicts can be
considered as system restrictions, as they are detected when the association between
the base and meta level is declared by the user. This would be the case when the same
metaobject is associated twice to the same base object, or when the user wishes to
declare an association between two objects of the same plane (i.e. with similar
functionality).
On the other hand, dynamic conflicts are detected at runtime. The designer must
specify what actions must be undertaken when a given conflict arises. In the case of
dynamic conflicts it is possible to describe situations that are not problematic at
certain moments of execution but may be at others. For example, one may define a
conflict between two metaobjects that are not yet associated to the base level (or not
6. associated to the same base object), and therefore do not yet present a conflictive
situation but may do so in the future if they are associated to the same object.
The designer must explicitly specify the conflicts it wishes the system to handle
and the activation policy to follow in each case.
4.1. Categories of conflicts
The actions to be taken when a conflict is detected depend on the characteristics of the
application to be developed. In some cases it will be necessary to indicate a specific
order of execution of the metaobjects involved; in others, the detection of a conflict
may require that one or both of the metaobjects not be executed.
We have identified five different categories of activation policies to be
implemented when a conflict is detected: of order, optional, exclusive, null, and
context dependent. These categories constitute a taxonomy of conflicts which is
described as follows:
− of Order: in this type of conflicts an order of execution is established for the
metaobjects involved.
− Optional: in some cases it may be necessary for the system itself to decide which
metaobject to execute, either according to some pre-established system of priorities
or simply in a random fashion.
− Exclusive: when only one particular conflicting metaobject is to be executed.
− Null: for those cases in which neither of the metaobjects are to be executed.
− Context Dependent: when none of the above cases satisfy the desired solution to
the conflict, the designer adds code which would specify the activation of the
metaobjects, and which may include an evaluation of the current context of the
system.
4.2. Conflict Levels
In systems of a limited size the declaration and handling of conflicts between specific
metaobjects may be sufficient. However, in more complex and large systems this may
become very tedious and difficult to maintain. It is therefore important to abstract the
concept of conflicts to a higher level of granularity, permitting their declaration at a
level of functionality and not only between specific metaobjects. With the
introduction of planes, this reflective architecture supports a more flexible handling of
conflicts, easier to define and maintain.
The following levels of granularity between conflicts are defined and subsequently
supported by the framework:
− Metaobject – metaobject: this determines a conflict between two specific
metaobjects.
− Metaobject - plane: it establishes a conflict between a metaobject and a plane (all
the metaobjects belonging to that plane). As the structure of a plane is dynamic
(the metaobjects belonging to a plane may vary), it is necessary for conflicts of this
level to be verified at runtime.
7. − Plane - plane: this specifies a conflict between two planes, i.e. between all the
metaobjects of one plane with respect to all the metaobjects of the other. As with
the previous level, the conflict must be dealt with at runtime.
− Metaobject - all: this permits the specification of conflicts “one to many”, where a
specific metaobject has a conflict with all other metaobjects. The conflicts of this
level are dealt with dynamically, as the creation or elimination of metaobjects
varies the structure of the conflict.
5. Design of the Reflective Architecture of Planes
The two main components of the reflective architecture of planes are the Application
and the Reflection Mechanism. The Application Mechanism contains the
implementation developed by the designer: on the one hand of the functionality
corresponding to the external domain (base level), and on the other hand the extended
functionality that crosscuts the base level and which has the basic application as its
domain (meta level).
The Reflection Mechanism is the component which provides the creation and
administration of associations between the different levels, together with the
administration of the planes and with the handling of conflicts.
Reflection Mechanism Application
2-1, 6
Reflection (4,8) Meta
Taxonomy
Level
2-2, 5
1, 7
Conflict-
(
Taxonomy
2,6)
(5,9)
3, 4 Base
Plane Manager Level
Fig. 3. Reflective Architecture
Figure 3 shows the main components of the reflective architecture of planes and
with handling of conflicts:
8. − Reflection Taxonomy: it administrates the associations between the levels (base /
meta or meta / meta). It is also in charge of intercepting the messages that are sent
to objects and of activating the corresponding associated metaobjects.
− Conflict Taxonomy: it controls and administrates the activation of metaobjects and
planes when a conflict is detected.
− Plane Manager: it administrates the different planes and so offers a greater level of
abstraction for the handling of components with a specific functionality.
The basic control flow of the architecture is the following (as seen in Figure 3):
1. An object of the base level receives a message which is intercepted by
Reflection Taxonomy.
2. The component Reflection Taxonomy verifies if the base level object
has associated metaobjects, and then makes up the list of all the
metaobjects that should be activated. It then carries out two activities:
2.1. It verifies if the associated metaobjects are to be activated
before, after, or before and after the base level method.
2.2. It sends the list of metaobjects to be activated to the Conflict
Taxonomy component.
3. Conflict Taxonomy identifies the conflicts between those metaobjects
and invokes the Plane Manager.
4. Plane Manager returns to Conflict Taxonomy the information on the
planes corresponding to the metaobjects to be activated.
5. Conflict Taxonomy reorganises and returns to Reflection Taxonomy
the ordered list of metaobjects, after identifying and solving the
conflicts.
6. Reflection Taxonomy invokes each metaobject according to the
established order.
7. Reflection Taxonomy returns the control to the base level.
6. Example
An example is described in order to illustrate the proposed architecture. This example
has different types of conflicts and of of reflection, it uses various planes and is
organised on three levels. Figure 2 shows the positioning of the planes and their
interaction.
The application consists of part of the functionality of an educational
establishment. This establishment has students and a staff of professors. Statistical
information on the students is to be calculated, and for this reason a sample was taken.
The application has three levels, where the first level (base level) contains
instances of STUDENT, PROFESSOR and ADVISOR classes.
Two planes can be seen at Meta Level 1. One is in charge of storing students and
professors in a data base. The second plane carries out the statistics according to the
behaviour of the base level, having to interact with the data base in order to obtain
certain information.
The objective of Meta Level 2 is to log the activities of the inferior levels.
9. This example requires different types of reflection. The LOGGING plane carries out
class reflection on the other planes, as it has to observe everything that occurs. The
STATISTIC plane does class reflection on some of the students due to the fact that it is
only interested on a sample of them. The STORING plane carries out method reflection
on the respective set and get methods of the STUDENT and PROFESSOR classes.
Figure 2 only shows part of the contents of the planes; not all the objects of a plane
observe or are observed by others. At the base level we can see three instances of the
Student class: John, Peter and Nicholas, where the first two are part of the sample
used for the statistics. The figure also shows two instances of the Professor class,
Collins and Anderson, and one instance of the Advisor class, Mitchell. The
STATISTIC plane contains the metaobject stud (StudentObserver), which observes the
students selected for the sample. The STORING plane has two metaobjects, sStore that
observes students and pStore for professors. Lastly, the LOGGING plane has three
metaobjects - blo, so, and dbo – where each one observes one of the planes at inferior
levels.
Figure 4 shows the code which carries out the reflective associations and the
handling of the planes of the example architecture.
1
2
Fig. 4. Reflective associations and the handling of the planes
First of all, the metaobjects and planes of the application are declared (1). The
PlaneManager has been designed based on the Singleton pattern in order to permit
global access to an object and to make sure there is only one instance of it.
The necessary reflective associations are then declared; the example uses class,
object and method reflection. The associations require the following parameters: the
object to be observed, the metaobject that will observe it, and the moment in which
the metaobject will be activated (2) (i.e. if the meta level is to be activated before,
after, or before and after the invocation of the original base method).
An evident conflictive situation is when an instance of the Student class which has
been selected for the statistic sample receives a message to set or get the value of a
variable. In this case, three metaobjects compete in the activation order. The
metaobject stud (STATISTIC) is active because the instance is one of those selected for
the sample; the metaobject sStore (STORING) is active because it carries out method
10. reflection on the set and get methods of the Student and Professor classes; and the
metaobject blo (LOGGING) is active because it carries out class reflection on all classes
of the base level.
A design decision is that logging is to be carried out lastly, and that the statistical
calculations are to be done after the data are stored in the data base. This is in order to
work with up-to-date information.
Figure 5 shows the declaration of the order conflicts which correspond to the order
of activation of metaobjects which must be followed, when the above conflictive
situation occurs.
1
2
Fig. 5. Conflict Declarations.
In order to make sure that the conflict described is valid for all metaobjects of the
LOGGING plane, a conflict is declared for the plane. As it is necessary for the LOGGING
plane to execute after all other planes, a one-to-many conflict between planes is
declared in inverse order (1).
So that all metaobjects of the STORING plane are executed before any metaobject of
the STATISTIC plane, a conflict at the plane level is declared. In this case the relation is
one-to-one (2).
The previous situation can also be represented by means of the following reverse
order conflict:
ReverseOrderConflict.between(“Statistic”,“Storing”);
Lastly, figure 6 describes the sequence of execution of the metaobjects associated
to the base object John (Student@a38f21) when it receives the message setAdress();
this is the order after the designer has declared the reflective associations and the
above-mentioned conflicts.
Section A contains the messages which confirm the creation of planes, reflective
associations and conflicts between metaobjects.
Section B shows the order of activation of the metaobjects when the method
setAddress() of object John is invoked. In this case all the metaobjects are executed
11. before the base object method, because all the reflective associations used the before
parameter (see Figure 4). The metaobject sStore (StudentStore@a7c18993)
belonging to the STORING plane is activated first, then the metaobject stud
(StudentObserver@a6cd5372) belonging to the STATISTIC plane, and lastly the
metaobject blo (BaseLevelObserver@d5c43332) from the LOGGING plane, according
to the order pre-established by the conflicts declared by the designer.
A
B
Fig. 6. Execution Sequence
7. Implementation
The reflective architecture described in the previous sections can be materialised in
any programming language that supports metaobjects. However, as current wide-
spread programming languages do not provide metaobject support, they must be
extended in order to do so. In order to add reflective characteristics, some changes
must be carried out in the kernel or language compiler. The modified language must
provide the infrastructure for the interception of messages, for the activation of the
metaobjects that administer those messages, and for continuing the normal execution
of the object that received the original message.
The traditional manner in which compiled languages such as C++ or Java are
extended is by means of the pre-processing of source code. This pre-processing adds
the interception mechanism to the original code, such that the metaobjects are notified
of the messages sent at the base level and they then carry out their specific
computation. This implies, for example, the substitution of class, method and variable
names with names that the reflection mechanism can handle. When a new association
between the base and meta level is declared, the original class is modified and
recompiled, with the consequent transformation of the original source code.
12. Additionally, this type of extension limits the runtime handling of situations and the
flexibility of the system which reflective techniques aim to achieve.
The reflective architecture has been implemented in Java, using JMOP [Zun00] to
introduce the reflective mechanism, and extending the design of RefPat [Mar01] in
order to introduce the concept of planes and treatment of conflicts [PBC00]. Each
time an application class is loaded JMOP creates a new class which has access to the
original one. The new class redefines the methods by adding a prefix, and the content
of the original methods is simply an invocation to the reflection manager.
Consequently, each time a base level object receives a message, the reflection
manager is invoked. This manager verifies if the message (object / class) is to be
reflected, and in that case it provides the list of associated metaobjects to be activated.
This list is sent to the conflict manager.
The conflict manager administers the conflicts declared by the designer
(represented by a directed graph), and it reorganizes and returns the ordered list of
metaobjects to the reflection manager. The latter invokes the metaobjects according to
the established order, and returns control to the original base method.
When the designer declares a reflective association, the system verifies and solves
the static conflicts. In order to carry out this verification, it may require the
collaboration of the plane manager, e.g., to control that the conflict being declared
does not involve metaobjects of the same plane.
The limitation that metaobjects on the same plane cannot be associated, is based on
the fact that only different planes which each implement an independent functionality
actually crosscut each other. Interaction between metaobjects on the same plane
should be programmed by means of traditional invocations.
The implementation of the framework in Java described above has been used for
the development of the application mentioned in section 6, and can be instantiated in
order to develop a wide variety of reflective applications.
8. Conclusions
This paper has described a framework that supports the development of systems with
a multi-level reflective architecture. The main characteristics of this architecture are
the flexibility of its reflective mechanism and the heterarchical structure of meta-
levels. Additionally, it supports planes as groups of components that share the same
basic functionality, permitting a wide range of interaction between planes and their
components.
As the architecture supports association of objects with multiple metaobjects which
may therefore compete for activation, different categories and levels of conflicts have
been studied and defined. Subsequently, the system supports the declaration and
runtime handling of these types of conflicts.
The framework is currently being documented in order to allow a more wide-
spread use in the development of applications. A tool for the instantiation of the
framework is being developed in order to facilitate this process, and to permit its
implementation in different programming languages.
13. Additionally, different applications are being developed in order to test and
evaluate the framework in different domains.
9. References
[Coi88] P. Cointe. A Tutorial Introduction to Metaclass Architecture as provided by Class
Oriented Languages. Proceedings of the International Conference on Fifth Generation
Computer Systems, ICOT editor, pages 592-608, 1988.
[DS84] J. Des Riveres and B. Smith. The Implementation of Procedurally Reflective
Languages. Proc. of the 1984 ACM Symposium on Lisp and Functional Programming,
pages 331-347, August 1984.
[Mae87] P. Maes. Concepts and Experiments in Computational Reflection. In N.K.
Meyrowitz, pages 147-155.
[Mar01] C. Marcos. Patrones de Diseño como Entidades de Primera Clase. PhD. thesis.
Universidad Nacional del Centro de la Provincia de Buenos Aires (UNCPBA), Facultad de
Ciencias Exactas, Instituto de Sistemas ISISTAN, Abril 2001.
[MMY93] H. Masuhara, S. Matsouka, and A. Yonezawa. Designing an OO Reflective
Language for Massively-Parallel Processors. Proc. of Workshop OOPSLA'93.
[OI94] H. Okamura and Y. Ishihawa. Object Location Control using Meta-Level
Programming. In M. Tokoro and R. Pareschi.
[OIT92] H. Okamura, Y. Ishikawa, and M. Tokoro. AL-1/D: A Distributed Programming
System with Multi-Model Reflection Framework. Proc. of the IMSA'92. International
Workshop on Reflection and Metalevel Architecture. November 1992.
[Par72] D.L.Parnas. On the criteria to be used in decomposing systems into modules.
Communications of the ACM, 15(12):1053-1058, December 1972.
[PDF99] R.Pawlak, L.Duchien and G.Florin. An Automatic Aspect Weaver with a Reflective
Programming Language. In the Second International Conference on Metalevel Architectures
and Reflection. St-Malo, France. July 1999.
[PBC00] J.Pryor, N.Bastán and M.Campo. A Reflective Approach to Support Aspect
Oriented Programming in Java. In Proceedings of ASSE’2000, 29 JAIIO. Buenos Aires,
Argentina, September 2000.
[Str93] R. Stroud. Transparency and Reflection in Distributed Systems. ACM Operating
Systems Review 27(2), April 1993.
[WY88] T. Watanabe and A. Yonezawa. Reflection in an Object Oriented Concurrent
Language. In N.K. Meyrowitz, pages 306-315.
[Zun00] A.Zunino, Brainstorm/J: un framework para agentes inteligentes. Master's Degree
Dissertation. Universidad Nacional del Centro, Instituto de Sistemas ISISTAN. April 2000.