28
SOFTWARE—PRACTICE AND EXPERIENCE Softw. Pract. Exper. 2001; 31:1237–1264 (DOI: 10.1002/spe.412) An architecture for extensible middleware platforms Eric Bruneton 1, ,†,‡ and Michel Riveill 2 1 SIRAC Project (INPG-UJF-INRIA) INRIA, 655 avenue de l’Europe, 38334 Saint-Ismier Cedex, France 2 Ecole Sup´ erieure en Sciences Informatiques, 930 route des Colles, 06903 Sophia Antipolis, France SUMMARY This article presents a middleware platform architecture whose goals, motivated by the needs of a real- world application, are the following: separation of functional and non-functional code in applications, composition of non-functional properties, and modularity and extensibility of the middleware platform itself. This architecture is inspired by the Enterprise Java Beans platform, and uses a new object composition model to separate and compose the non-functional properties. In order to evaluate this architecture, we have implemented the JavaPod platform which we have used to implement a prototype of the application that motivated our goals. The results of these experiments show that our goals can indeed be achieved with our architecture. Copyright 2001 John Wiley & Sons, Ltd. KEY WORDS: middleware platform; non-functional properties; separation and composition of non-functional properties; modularity; extensibility 1. INTRODUCTION This section presents a real-world distributed application in order to explain the problems we are trying to solve. This application is also used in Section 4 in order to evaluate our proposition with respect to the goals presented in this section. The goal of the Baghera project [1] is to build a distributed application for computer-aided learning, in the field of elementary geometry. More precisely, the main goal is to use artificial intelligence techniques, such as multi-agent systems, to automate the learning process as much as possible, and to adapt it automatically to each student’s level. In order to focus on the distributed systems aspect, we defined a simplified version of the Baghera application, by removing all artificial intelligence aspects. The resulting application, called baghera, can be described as follows. Correspondence to: Eric Bruneton, SIRAC Project (INPG-UJF-INRIA) INRIA, 655 avenue de l’Europe, 38334 Saint-Ismier Cedex, France. E-mail: [email protected] In collaboration with France Telecom, 38–40 Rue Gal Leclerc, 92794 Issy Moulineaux, France. Copyright 2001 John Wiley & Sons, Ltd. Received 12 January 2001 Revised 23 April 2001 and 9 July 2001 Accepted 10 July 2001

An architecture for extensible middleware platforms

Embed Size (px)

Citation preview

Page 1: An architecture for extensible middleware platforms

SOFTWARE—PRACTICE AND EXPERIENCESoftw. Pract. Exper. 2001; 31:1237–1264 (DOI: 10.1002/spe.412)

An architecture for extensiblemiddleware platforms

Eric Bruneton1,∗,†,‡ and Michel Riveill2

1SIRAC Project (INPG-UJF-INRIA) INRIA, 655 avenue de l’Europe, 38334 Saint-Ismier Cedex, France2Ecole Superieure en Sciences Informatiques, 930 route des Colles, 06903 Sophia Antipolis, France

SUMMARY

This article presents a middleware platform architecture whose goals, motivated by the needs of a real-world application, are the following: separation of functional and non-functional code in applications,composition of non-functional properties, and modularity and extensibility of the middleware platformitself. This architecture is inspired by the Enterprise Java Beans platform, and uses a new objectcomposition model to separate and compose the non-functional properties. In order to evaluate thisarchitecture, we have implemented the JavaPod platform which we have used to implement a prototypeof the application that motivated our goals. The results of these experiments show that our goals can indeedbe achieved with our architecture. Copyright 2001 John Wiley & Sons, Ltd.

KEY WORDS: middleware platform; non-functional properties; separation and composition of non-functionalproperties; modularity; extensibility

1. INTRODUCTION

This section presents a real-world distributed application in order to explain the problems we are tryingto solve. This application is also used in Section 4 in order to evaluate our proposition with respect tothe goals presented in this section.

The goal of the Baghera project [1] is to build a distributed application for computer-aided learning,in the field of elementary geometry. More precisely, the main goal is to use artificial intelligencetechniques, such as multi-agent systems, to automate the learning process as much as possible, andto adapt it automatically to each student’s level. In order to focus on the distributed systems aspect, wedefined a simplified version of the Baghera application, by removing all artificial intelligence aspects.The resulting application, called baghera, can be described as follows.

∗Correspondence to: Eric Bruneton, SIRAC Project (INPG-UJF-INRIA) INRIA, 655 avenue de l’Europe, 38334 Saint-IsmierCedex, France.†E-mail: [email protected]‡In collaboration with France Telecom, 38–40 Rue Gal Leclerc, 92794 Issy Moulineaux, France.

Copyright 2001 John Wiley & Sons, Ltd.Received 12 January 2001

Revised 23 April 2001 and 9 July 2001Accepted 10 July 2001

Page 2: An architecture for extensible middleware platforms

1238 E. BRUNETON AND M. RIVEILL

StudentAgent

ProfessorAgent

VirtualSchool Mailbox(es)

ElectronicCase(s)

ExerciseRepository

AdminAgent

required interfaceprovided interfacecomponent

Figure 1. Architecture of the baghera application.

• The application is organized around a virtual school concept. A virtual school has students,grouped into classes according to their level. A virtual school also has professors, who areassigned to a class, propose exercises to their students, and correct their solutions. Finally, thevirtual school administrator manages the list of students and professors, and the distribution ofstudents to classes.

• Each student has an electronic case, which contains the geometry exercises solved by thisstudent, as well as the exercises that still need to be solved. It also contains the messagesexchanged with other students and professors. Similarly, each professor has a mailbox, whichcontains the messages exchanged with his or her students and with other professors.

• An exercise repository contains a list of geometry exercises (together with their solution) whichcan be used by professors to propose exercises to their students.

• Each student uses the application through a graphical user interface (GUI) which displays thecontent of his or her electronic case, and allows him or her to propose a solution to an exercise,and to send messages to other users.

• Each professor uses the application through a GUI which displays the list of his or her studentsand, for each student, the content of his or her electronic case. This GUI allows professors to addexercises in an electronic case or in the exercise repository, to correct a solution proposed by astudent, and to send messages to other users.

• Finally, the administrator uses a GUI which allows him or her to add and remove students andprofessors, and to modify the assignment of students to classes.

This application can be decomposed into a set of components, as shown in Figure 1 (the linksrepresent remote references between components). The components can be deployed arbitrarily: forexample, the non-GUI component can be deployed on one host, and the GUI component each on its

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 3: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1239

own host. The interesting point, for us, is that this application needs to be adapted differently dependingon the following three environments in which it is used.

• The VirtualSchool, Mailbox, ElectronicCase and ExerciseRepository components need to bepersistent: their data must not be lost between two uses of the application by a student, aprofessor or an administrator. One way to ensure this is to keep a copy of these componentson stable storage. However, the stable storage to be used may depend on the environment: withfew students, each component can be stored in its own file; with many students, a relational orobject database is probably more efficient.

• By default, the previous persistent components are not protected. For example, it would bepossible for a student to use the exercise repository to get the solution of an exercise. However,this requires programming skills, because the GUI used by students does not allow access to thesolutions. If students are believed not to have these skills, and if professors can be trusted, thenit is acceptable not to protect the persistent components. In the opposite case it is necessary toprotect them, for example to ensure that only professors can get the solution of an exercise fromthe repository.

• The application can be used in a real school, in which case it can be deployed on hosts thatare always connected to the school’s local area network (LAN). But the application can also beused, as in the Baghera project, by students who may need to stay in hospital. These studentswill probably not have a permanent connection to the school’s LAN. In this case, the applicationmust be adapted so that students can still work while disconnected. For example, they should beable to propose solutions for their exercises, and to ‘send’ messages. Upon reconnection, thesesolutions and messages should automatically be integrated with the persistent components.

In summary, since these three environments can be mixed, the persistent components need to beadapted to use a different stable storage, to be protected or not, and to be usable in disconnected modeor not, depending on the environment§. In order to satisfy these needs, we postulate that the middlewareplatform used to implement the application should satisfy the following three requirements.

• Adaptation code should be separated from application code, so that the application code neednot be changed when adapting the application to a new environment. In other words, and sinceproperties such as persistence and protection are usually called non-functional properties, we cansay that the middleware platform should allow the separation of functional and non-functionalcode.

• The middleware platform should also allow several non-functional properties to be associatedwith an application (as described in the above adaptation environments).

• Finally, the middleware platform should be modular and extensible. For example, it should bepossible to change the persistency service (to use a database instead of files), without changingthe other system services. It should also be possible to add a system service if it is missing, andto ensure that new system services will work properly when composed with existing ones.

§This set of non-functional properties is of course not exhaustive. However, we limited ourselves to this set to validate ourproposition.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 4: An architecture for extensible middleware platforms

1240 E. BRUNETON AND M. RIVEILL

We propose in this article a middleware platform architecture to try to achieve these goals.This architecture is presented in Section 2. In order to evaluate it with respect to the above goals,we implemented a prototype middleware platform, called JavaPod, presented in Section 3. We thenimplemented the baghera application with this prototype platform. This implementation, and the resultswe obtained with it, are presented in Section 4. Section 5 presents related work, and Section 6 concludesthis article.

2. THE PROPOSED MIDDLEWARE PLATFORM ARCHITECTURE

This section presents the middleware platform architecture we propose to achieve the goals presentedin the previous section.

2.1. Programming model

Before presenting the middleware platform architecture, we must the define its programming model,i.e. the concepts offered to programmers to build their applications. The Common Object RequestBroker Architecture (CORBA) uses a client–server model. Message oriented middlewares use messagebased models. Our platform offers a very general model inspired by the Open Distributed Processing(ODP) model [2].

2.1.1. Components, connectors and interfaces

According to our model, applications are made of components, linked together through connectors (seeFigure 2).

• A component encapsulates data and code, like an object in object-oriented languages. However,unlike an object, a component can have multiple access points, called facets in the CORBAcomponent model [3], and that we call interfaces¶.

• An interface has a type, which is a list of method signatures. It also has a direction: an inputinterface is used to call methods inside a component, while an output interface is used to callmethods outside a component, i.e. on a connector. A component can have several interfaces withthe same type and direction.

• A connector is a special component that links together two or more interfaces, not necessarily ofthe same type. The role of a connector is to allow communication between ‘normal’ components.

A connector can represent any type of interaction, such as client–server, publish–subscribe, groupcommunications or broadcast. The examples below show that connectors can implement any type ofinteraction between components (see Figure 3).

• A client–server connector links the output interfaces of one or more client components to aninput interface of a server component. The output interfaces are used to call methods on theconnector, which transmits them over the network, and executes them by using the server’s inputinterface.

¶Here, as in ODP, an ‘interface’ does not designate a type, as in Java or CORBA IDL, but ‘a place at which independent systemsmeet and act on, or communicate with, each other’.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 5: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1241

I

I

Connector

Connector J

J

Component

Input interface of type I

Ouput interface of type IComponent

K

K

Con

nect

or

Component

Figure 2. The concepts of our programming model.

• A publish–subscribe connector is symmetrical: it links an output interface of a publishercomponent to one or more input interfaces in other components. When the publisher posts anevent (by calling a method of its output interface), the connector broadcasts it to the subscribers,and notifies them of this new event by calling the corresponding method of their input interface.

• A stream between a video server and one or more clients can be implemented by a connectorsimilar to a publish–subscribe connector. Indeed, the video server is similar to a publisher, andthe video stream packets are similar to events posted by a publisher.

• A connector can also represent interactions based on object sharing, i.e. where componentscommunicate by modifying the state of a shared object (such as a calendar or a text document),and where components are automatically notified when this state changes.

Although we implemented, with our prototype platform, client–server, stream and ‘shared data’connectors, we restrict ourselves, in this article, to client–server connectors (because they are simple,and because most of the non-functional properties we experimented with required a client–servermodel).

2.1.2. Interface references

In order to be able to designate components and connectors, a reference concept is needed. This sectionpresents the reference concept used in ODP, and shows that it is not practical when non-functionalproperties are taken into account. The next section presents how we solved this problem.

The ODP model uses interface references, together with binding factories. An interface referencedesignates an interface, i.e. an access point of an ODP object. A binding factory, given two ormore interface references, creates a connector to bind these interfaces together. Each binding factorycreates connectors of a given category. For example, a CORBA binding factory creates client–serverconnectors using the Interoperable Inter ORB Protocol (IIOP), a Java Remote Method Invocation(RMI) binding factory creates client–server connectors using the Java Remote Method Protocol(JRMP) protocol, and a Real-time Transport Protocol (RTP) binding factory creates stream connectorsbased on the RTP protocol.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 6: An architecture for extensible middleware platforms

1242 E. BRUNETON AND M. RIVEILL

I

I

Client

Client

Server

Publish-subscribe connector

J

J

J

Subscriber

Subscriber

Publisher

‘‘Shared object’’ connectorClient-server connector

I

I

I

INotify

Notify

Not

ify

consistency managedby the connector

shared object’s copy

Figure 3. Connector examples.

The advantage of this solution is that it is possible to have several connector categories, unlikein CORBA. The disadvantage is that there must be one factory per connector category. This isnot a problem if the number of categories is small, but it becomes one if this number can growexponentially. Unfortunately, this is precisely the case when non-functional properties are taken intoaccount. For example, if compression, cryptography and mobility aspects are taken into account, thereare at least 16 possible categories of client–server connector (including IIOP, IIOP + compression,IIOP + compression + cryptography, JRMP, and JRMP + mobility). More generally, with n non-functional properties, each having m possible implementations, there are (m + 1)n variations for agiven ‘base’ category. It is clearly impossible in practice to manually define so many binding factories.

2.1.3. Connector references

To avoid this problem, the idea is to store the information contained in binding factories (essentiallya list of protocol names) in the references themselves. Binding factories are then no longer needed.This led us to define the connector reference concept.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 7: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1243

• A connector reference contains identification data that designates a unique connector.For example, a client–server connector reference designates a client–server connector byidentifying its main part, i.e. the server’s input interface (typically with an IP address, a TCPport and a key). Likewise, a publish–subscribe connector reference contains identification datathat designates the publisher’s output interface.

• A connector reference also contains construction data, which describes how to build newinterfaces for the designated connector (depending on their type and on their direction).For example, a client–server connector reference contains data that describes how to buildan output interface for a new client (of the server designated by this reference). Likewise,a publish–subscribe connector reference describes how to build an input interface for a newsubscriber.

The precise format of connector references is explained in Section 3.2.4, because it cannot beunderstood before the middleware platform architecture we propose is explained.

According to the above definition, the interfaces created by using the construction data of a connectorreference ref belong to the connector designated by ref. Therefore, all the client interfaces of aserver interface, and the server interface itself, belong to a single connector. In other words, we do notconsider, as is usually the case, a client to have its own connector to the server, unless this client usesspecific protocols.

Since a connector reference contains construction data, in addition to identification data, a connectorreference is bigger than an interface reference. This is the price to pay to avoid binding factories.A possible tradeoff would be to use both interface and connector references, since they are probablynot exclusive. However, we restricted ourselves to connector references only.

2.1.4. Reference passing

From the programmer’s point of view, components are made of one or more language level objects‖,interfaces are represented by normal objects, and connectors are invisible. Figure 4 illustratesthese correspondences. Moreover, connector references are transparently managed, like CORBAinteroperable object references. This management is based on two symmetric operations.

• An object o can be exported out of a component. The result is a reference to a connector thatgives access to o. This connector is created if it does not yet exist.

• A connector reference ref can be imported into a component. The result is an object thatrepresents an interface attached to the connector designated by ref, or an object to which thisconnector gives access.

Consider for example the components depicted in Figure 4, and let us suppose that C sends t to S,as an argument of a remote method call. Since t represents an interface, it is automatically replaced,during the marshaling of the request, by the reference of the connector attached to this interface,i.e. by ref. Symmetrically, during unmarshaling, connector references are automatically recognizedand replaced by ‘appropriate’ objects. In the previous example, ref is automatically replaced by o.

‖Components are intended to be programmed with an object-oriented language.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 8: An architecture for extensible middleware platforms

1244 E. BRUNETON AND M. RIVEILL

ref

Application’s architecture

Connector

Component C

I I

Component S

object

reference Connector

repr

esen

ts

C S

ost

references

Application’s implementation

Figure 4. Correspondences between the application’s model and implementation.

2.2. The middleware platform architecture

In order to execute distributed applications programmed according to the above model, we propose touse an architecture inspired by the Enterprise Java Beans (EJB) model, because the EJB platformpartially fulfills one of our goals (namely the separation of functional and non-functional code).Our architecture is therefore based on servers, containers, and stubs and skeletons.

2.2.1. Servers

A server is an execution environment for containers. It provides memory, CPU and network resources,as well as communication protocols and system services (such as a persistency service and a transactionmanager) that are shared between containers. It can also provide management services such asmonitoring and deployment.

2.2.2. Containers

In the EJB model, a container encapsulates several components and manages their non-functionalproperties. This is done, principally, by means of interposition objects, called EJBObjects. As itsname implies, an interposition object intercepts all remote method calls to a given component∗∗.An interposition object can, for example, authenticate the caller, load the called component fromdisk, and launch a transaction before effectively calling a method on its associated component.An interposition object can therefore manage non-functional properties such as persistence andprotection, and the component no longer needs to contain non-functional code for that.

∗∗An EJB interposition object is similar to a server-side, request-level interceptor in CORBA.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 9: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1245

In our architecture, a container encapsulates a unique component and manages its non-functionalproperties. A container also contains interposition objects, that we call skeletons (because they canplay the roles of CORBA skeletons and of EJBObjects).

2.2.3. Stubs and skeletons

A stub represents (see Section 2.1.4) an output interface: it allows a component to call methods on aconnector. Symmetrically, a skeleton represents an input interface: it allows methods to be called in acomponent. Stubs and skeletons are also called gates.

As mentioned in the previous section, a skeleton, in our architecture, can play the roles of a CORBAskeleton and of an EJBObject (or one or more CORBA server-side interceptors). Likewise, a stub,in our architecture, can play the roles of a CORBA stub and of one or more CORBA client-sideinterceptors. However, stubs and skeletons do not necessarily play these roles. Indeed, the marshalingand interception functions of a client–server connector’s skeleton would be meaningless for a streamconnector’s skeleton (which communicates through data packets instead of remote method calls).

Since a stub (respectively a skeleton) is at the interface between a container and a connector, itbelongs to both (as suggested in Figure 5). For example, when a container is moved, its encapsulatedcomponent and its stubs and skeletons move with it. Another consequence is that a connector can beviewed as a set of stubs and skeletons.

2.3. Composition model

Since the architecture so far is very similar to the EJB model, it should have, a priori, the samecapabilities. The architecture should therefore be able to separate the functional and non-functionalcode of applications, which was our first goal. Unfortunately, it will presumably also have, a priori,the same limitations as the EJB platforms, such as unextensibility. In current EJB platforms, thislimitation is mainly due to the fact that containers, stubs and skeletons are monolithic, and generated bya monolithic code generator. In order to avoid this problem, we propose to build the previous elementsin a modular way, by composing several ‘sub-elements’. This section presents our composition model.

2.3.1. Requirements

This section shows that, in order to be able to compose non-functional properties ‘easily’ anddynamically, a composition mechanism should be able to simulate class inheritance mechanisms,without their disadvantages.

Let us consider an (imaginary) stub of a client–server connector, and let us suppose it has thefollowing methods. The invoke method implements a remote method call mechanism. It takesas argument the name of a method and the method’s arguments, and returns the result of theremote execution of this method. This generic method uses the marshal and unmarshal methodsto marshal and unmarshal the arguments of the call. Finally, the stub implements the ‘businessmethods’, i.e. the application-level methods provided by the server object (such as withdraw andgetBalance for a bank account). These methods, automatically generated by a stub compiler,delegate their task to the invoke method.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 10: An architecture for extensible middleware platforms

1246 E. BRUNETON AND M. RIVEILL

Server Server

Container

Stub

Stub

Skeleton

Skeleton

Skeleton

Stub

Component

Component

Component

Connector

Connector

Figure 5. The concepts of our middleware platform architecture (this example corresponds tothe application example of Figure 2).

It is now easy to show that the composition mechanism we are looking for should be able to simulatemethod overriding and should allow new methods to be added to objects.

• To use application-specific marshaling rules, the natural way is to override the marshal andunmarshal methods. Likewise, to monitor remote method calls, the natural way is to overridethe invoke method, in order to print messages before and after calling the default invokemethod.

• The marshaling methods are specific to client–server stubs. For example, they are useless ina stream connector stub, which communicates through data packets instead of remote methodcalls. Therefore, it would be useful to be able to add these specific methods to a generic stub,which could then be specialized into a client–server or a stream stub.

An obvious solution would therefore be to use class inheritance. However this mechanism istoo static: there must be one class per combination. With n optional non-functional properties, thisrequires at least 2n classes! Moreover, this mechanism does not allow non-functional properties tobe dynamically modified (for example to dynamically turn monitoring on and off). In summary, thecomposition mechanism should be able to simulate the class inheritance mechanisms, without theirdisadvantages (combinatorial explosion and inability to be used dynamically).

2.3.2. Definition

Our composition model is defined precisely in order to achieve the previous requirements.This mechanism is an object composition model. This means that it allows objects to be composed intocomposite objects. As its name implies, a composite object is an object: its methods are, by definition,

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 11: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1247

composite object execution pathextensible object extension

(client)

(1)

dsuper.withdraw(amount); throw new Exception();

dsuper.addPoints(points);if (getPoints() > 100) { deposit(10); resetPoints();}

dsuper.withdraw(amount);

getPointsaddPoints

withdraw

addPoints

depositwithdrawgetBalance

resetPoints

withdraw

(2)

(3)

g

h

f

e

if (amount > 1000)

addPoints(amount/10);

Figure 6. A composite object.

the union of the methods of its members. In order to simulate method overriding, these methods havethe following semantics.

• First of all, the members of a composite object are ordered in a list. The first member (i.e. thehead of the list) is called an extensible object, and the others are called extensions. The extensibleobject can not be removed or replaced, but extensions can be dynamically added, removed andreplaced.

• A call to a method m on a composite object is executed by the last member of the composite inwhich m is defined. In extensions, a special form of method call is available, noted dsuper.m.A call to dsuper.m in an extension e is executed by the last member in which m is defined,and that is strictly before e in the extension list.

The composite-object example of Figure 6 illustrates these definitions. The extensible object eis a minimal bank-account object. It is extended by an extension f that manages fidelity points.This extension overrides the withdraw method, and adds three new methods. It is itself overriddenby two other extensions: g modifies the management of fidelity points, and h checks the amount ofwithdrawals. When a client calls the withdraw method on e, the call is in fact executed by extensionh and then, through explicit calls to dsuper, by f and e.

This example shows that our mechanism simulates class-inheritance mechanisms. It is howevermuch more flexible than class inheritance. For example, the bank account’s behavior can be changeddynamically, by adding and removing extensions at runtime. Moreover, the six possible ways tocompose the three extensions of Figure 6 do not need to be explicitly defined, as would be the case withclass inheritance. In other words, there is no combinatorial explosion (there are 2n ways to compose n

independent extensions).In order to complete the above definition, it should be noted that composite objects are subject to

the following restrictions. The first restriction is that object fields are supposed to be accessible only

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 12: An architecture for extensible middleware platforms

1248 E. BRUNETON AND M. RIVEILL

Server

extensions

extensibleobject

Server

Connector

ContainerContainer

Stub Skeleton

object object reference composite object

Figure 7. Summary of our middleware platform architecture.

through methods. This is why we said nothing about the composition of composite object members’fields. The second restriction is that composite object members cannot be composite objects themselves(this constraint simplifies the implementation of our composition mechanism, without restricting itspossibilities††), and cannot be shared between composite objects. Finally, for consistency reasons, athread should not be able to add, remove or replace some extensions in a composite object whileanother thread is executing a method on this composite object.

2.4. Summary

In order to execute applications based on components, interfaces and connectors (see Figure 2), wepropose a middleware platform architecture inspired by the EJB model: components are encapsulatedin containers, component interfaces are implemented by (generalized) stubs and skeletons, andcontainers are included in servers (see Figure 5). Finally, in order to obtain a modular and extensibleplatform, we propose to build servers, containers, stubs and skeletons as composite objects, by using anew composition mechanism (see Figure 7).

3. THE JAVAPOD PLATFORM

In order to evaluate our proposal, we implemented a prototype middleware platform, called the JavaPodplatform [4,5], by following the previous architecture. We then implemented the baghera application

††Hierarchical composite objects can be flattened without modifying their semantics.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 13: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1249

public extensible interface Account {int getBalance ();void deposit (int amount);void withdraw (int amount);

}public extensible class BasicAccount implements Account {private int balance;public extensible int getBalance () { return balance; }public extensible void deposit (int amount) { balance += amount; }public extensible void withdraw (int amount) { balance -= amount; }

}public extension class FidelityAccount dextends Account {private int points;public extensible void withdraw (int amount) {

dsuper.withdraw(amount);addPoints(amount/10);

}public extensible int getPoints () { return points; }public extensible void addPoints (int pts) { points += pts; }public extensible void resetPoints () { points = 0; }

}Account a = new BasicAccount();a.deposit(1000);a.withdraw(100);a.setExtensions(new Object[] {new FidelityAccount()});a.withdraw(100);System.out.println(a.FidelityAccount::getPoints()); // prints "10" (and not "20")

Figure 8. A simple ejava program.

with this platform, to see if we were able to achieve our goals. This section presents the JavaPodplatform. The experiments with baghera are presented in Section 4.

3.1. The ejava language

The ejava language is a superset of Java in which our composition mechanism is ‘native’, i.e. can beused without needing to be simulated. The precise definition of the ejava language, and the way it isimplemented, would be out of the scope of this article. However, since the code samples presentedin Section 4 are written in ejava, this section gives a brief overview of this language. More precisely,Figure 8 gives the ejava source code of the composite object of Figure 6.

• The BasicAccount class is declared as extensible, which means that instances of thisclass are extensible objects (objects are not extensible by default).

• The FidelityAccount class declaration uses the extension modifier, which means thatinstances of this class can be used as extensions.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 14: An architecture for extensible middleware platforms

1250 E. BRUNETON AND M. RIVEILL

• The BasicAccount and FidelityAccount methods are declared as extensible toindicate that they can be dynamically overridden by extensions (methods are not extensible bydefault).

• The dextends clause, in the FidelityAccount class, means that FidelityAccountextensions can be added only to composite objects in which the Account’s methods areimplemented.

• The setExtensionsmethod, added to the Object class, sets the extensions of an extensibleobject. Here, this method adds a FidelityAccount extension to a.

• a.FidelityAccount::getPoints() calls the getPoints method, specified in theFidelityAccount class, on the composite object to which a belongs. This notation is usedto call an extensible method by using a composite object member in which this method is notimplemented.

The ejava language has been implemented by modifying the Kopi Java compiler [6], written in Java.This modified compiler, called ejavac [7], produces Java bytecode which can be executed on anyJava Virtual Machine.

3.2. The JavaPod kernel

The JavaPod platform is made of a small kernel and of several extension ‘layers’. The kernel onlydefines a framework, corresponding to the architecture presented in Section 2.2, while the extensionlayers provide all the functionalities of the platform (such as connectors and non-functional properties).This section presents the main classes of the JavaPod kernel, implemented in ejava.

3.2.1. The Server class

The Server class is almost empty. Its main extensible method is the createContainer method,to create a container for a component.

3.2.2. The Container class

The main methods of the Container class are related to the management of the container’s stubsand skeletons. For example, this class contains methods to create stubs and skeletons for existingconnectors, as well as for new connectors. It also contains methods to get the container’s list of stubsand skeletons, and to import and export connector references (see Section 2.1.4).

3.2.3. The Stub and Skeleton classes

The main method of the Stub and Skeleton classes is the invoke (Method m, Object[]args) method, whose role is to return the result of a call to m(args[0],. . .,args[n]). In theStub class, this extensible method does nothing, since its precise semantics depends on the connectorto which the stub belongs. It must therefore be overridden by stub extensions. In the Skeleton class,this method invokes the given method on the application component, by using the Java Reflection API.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 15: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1251

public class ReferenceImpl implements Reference {private Hashtable stubExts; // String -> ExtensionDescription[]public ExtensionSet getStubExtensions (String itf) {// constructs and returns the extensions described in ’stubExts.get(itf)’

}// ...

}public class ExtensionDescription { // describes how to build an extension

String className; // name of the class to instantiateObject[] arguments; // arguments for the class’s constructor

}

Figure 9. A generic implementation of the Reference interface (simplified). The className field correspondsto construction data (see Section 2.1.3), while the arguments field corresponds to identification data (it can

contain IP addresses, TCP ports etc.).

The JavaPod kernel also includes a stub compiler which, given a Java interface I, generates aStub’s sub-class implementing I (I’s methods are implemented by a call to the invoke method,with appropriate arguments). This stub compiler is generic: the stub classes it produces can be used forany connector categories.

3.2.4. The Reference interface

A connector reference (see Section 2.1.3) must be transmitted over the network as a serializedJava object whose class implements the Reference interface. This interface specifies thegetStubExtensions (String itf) (resp. getSkeletonExtensions) method, whoserole is to return the extensions to be used to build a new stub (resp. skeleton) of type itf for thereferenced connector. In order not to reintroduce the combinatorial explosion problem of ODP bindingfactories (see Section 2.1.2), we use a generic implementation (see Figure 9) of the Referenceinterface, i.e. one that can be used for any connector category.

3.3. The JavaPod extensions

The JavaPod kernel, with only 1500 lines of code, provides a minimal framework for its extensions.We implemented several extension ‘layers’ on top of this kernel, both to provide a usable middlewareplatform and to experiment with our architecture [8]. These extensions, including those implementedfor baghera (presented in Section 4), take approximatively 11000 lines of ejava code, and are organizedas follows:

• management extensions—to configure and deploy components;• protocol extensions—to send messages between components and gates;• connector extensions—to implement client–server and stream connectors;• system services extensions—to provide mobility, persistence, protection, replication etc.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 16: An architecture for extensible middleware platforms

1252 E. BRUNETON AND M. RIVEILL

This section focuses especially on the extensions that are used to implement client–serverconnectors, because they are needed to understand how the extensions used for baghera work.

3.3.1. The client–server connector extensions ‘layers’

As with Java RMI, where client–server connectors are implemented by three independent layers calledTransport, Reference and Stub/Skeleton [9], our client–server connectors are also implemented byseveral ‘layers’ of extensions. We use this approach for its well-known advantages: modularity (a layercan be replaced by another one, provided they have the same interface), and reusability (a layer can bereused in another context).

The layers used for our client–server connectors are organized as follows: the stp and gtp layersare transport layers used to transport messages between servers and gates. They play the role of theRMI Transport layer. The csp layer constructs and analyzes invocation requests and replies, anduses the gtp layer to send them. It also uses an ie layer to import and export connector references.The csp and ie layers roughly play the role of the RMI Stub/Skeleton layer.

3.3.2. The server transport protocol (stp) layer

The stp layer is used to send messages between JavaPod servers. It is specified by an abstract interfacewhich can be implemented in many different ways. A default implementation is provided, as a Serverextension, based on TCP/IP sockets and the Java Serialization mechanism.

3.3.3. The gate transport protocol (gtp) layer

The gtp layer is similar to the stp layer, but sends messages between gates (i.e. stubs and skeletons).It is also specified by an abstract interface which can be implemented in many different ways.The default implementation is based on the stp layer, and uses three extension classes, for servers,containers and gates. The server extension provides, among others, a gtpGetContainer method,which returns a container from its identifier (see Figure 11). The gate extension provides, among others,a gtpSend method, used to send messages to other gates, and a gtpRecv method, used to handleincoming messages.

3.3.4. The client–server protocol (csp) layer

The csp layer uses the previous layers to provide client–server connectors. This layer uses twocomplementary gate extensions, for the client and server sides. On the client side the csp extensionoverrides the Stub’s invoke method in the following manner: it constructs an object describingthe original method call, exports it with the ie layer, and sends it to the server with the gtp layer.The result is then imported, with the ie layer, and returned to the caller. The server side csp extensionis similar, except that it overrides the gtpRecv method instead of the invoke method.

4. EXPERIMENTS WITH THE BAGHERA APPLICATION

This section presents the experiments we made with the baghera application in order to evaluateour architecture with respect to our goals. It first gives some details about the implementation

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 17: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1253

interface ExerciseRepository extends JavaPodInterface {

Figure getExerciseProposition (String name) throws JavaPodException;Figure getExerciseProof (String name) throws JavaPodException;void addExercise (String name, Exercise exercise) throws JavaPodException;void removeExcercise (String name) throws JavaPodException;

}

class ExerciseRepositoryImpl extends Component implements ExerciseRepository {

private Hashtable exos = new Hashtable();

// A ’<T> get<X>InputPort’ method indicates that the component provides// an input interface ’X’ of type ’T’, which is returned by this method.

public ExerciseRepository getRepositoryInputPort () { return this; }

// functional code = implementation of the ExerciseRepository interface

public Figure getExerciseProposition (String name) { return get(name).prop; }public Figure getExerciseProof (String name) { return get(name).proof; }public void addExercise (String name, Exercise exo) { exos.put(name,exo); }public void removeExcercise (String name) { exos.remove(name); }

private Exercise get (String name) { return (Exercise)exos.get(name); }}

Figure 10. Source code of the ExerciceRepository component (slightly simplified). Component,JavaPodInterface and JavaPodException are defined in the JavaPod kernel.

of this application with JavaPod, and then presents the qualitative and quantitative results weobtained.

4.1. Implementation of baghera with JavaPod

The functional code of the baghera application presents no difficulty and is not detailed here. We justgive, in Figure 10, the code of one of the baghera components, in order to show that this code isin Java (ejava is only used to program the middleware platform), and that it does not include anynon-functional code. It is much more interesting to present how the three non-functional properties(persistence, protection and disconnected mode) were implemented and associated with the functionalcode.

4.1.1. Persistence

Since we were not primarily concerned with performance, we systematically chose the easiest wayto implement non-functional properties. For persistence, we therefore chose the following approach:a persistent component is serialized into a file, as well as its container and all its stubs and skeletons.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 18: An architecture for extensible middleware platforms

1254 E. BRUNETON AND M. RIVEILL

// server extension used to implement the gtp layerpublic extension class BasicGTPServerx dextends Server implements GTPServerx {private Hashtable containers = new Hashtable();public extensible Container gtpGetContainer (GTPAddress addr) {

return (Container)containers.get(addr);}public extensible void gtpAddContainer (Container container) {

containers.put(container.GTPContainerx::getGTPAddress(),container);}public extensible void gtpRemoveContainer (Container container) {

containers.remove(container.GTPContainerx::getGTPAddress());}// other methods ...

}

Figure 11. One of the extensions used to implement the gtp layer (slightly simplified).

// server extension to automatically load persistent components from diskpublic extension class BasicPersistentServerx dextends Server, GTPServerx {public extensible Container gtpGetContainer (GTPAddress addr) {

Container c = dsuper.gtpGetContainer(addr);if (c == null) { // component not found => load it from disk and register it

c = loadContainer(addr);dsuper.gtpAddContainer(c);

}return c;

}// other methods ...

}

Figure 12. One of the extensions used to implement persistence (slightly simplified).

This is done after each remote execution, by this component, of a method that may have changed itsstate.

To this end, the programmer must indicate, separately from the functional code, the methods thatmay change the component’s state. This information is used at deployment time, and stored in anextension of the component’s container. Another extension is used to override the skeleton’s invokemethod, in order to serialize, if necessary (i.e. as indicated by the previous container extension), thecomponent and its container after the execution of each incoming remote method call. Finally, a serverextension is used to automatically load the persistent components that have not yet been loaded intomemory: the gtpGetContainermethod, that returns a component from its identifier (see Figure 11)is overridden by this extension (see Figure 12) so that, in case of failure of the original method, therequested component is loaded from disk.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 19: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1255

// stub extension to add the caller’s identity to each outgoing message

public extension class ACLGTPStubx dextends GTPStubx {

public extensible PDU gtpSend (GTPAddress dst, PDU data, boolean sync) {// gets the caller’s identity (stored in a container’s extension)Identity id = Stub::getContainer().ACLContainerx::getCallerIdentity();// encapsulates ’data’ and ’id’ in a new message and sends it by calling dsuperreturn dsuper.gtpSend(dst,new ACLGTPMessage(data,id),sync);

}}

Figure 13. One of the extensions used to implement protection (slightly simplified).

4.1.2. Protection

We chose to implement protection by using access control lists (ACLs): a list of authorized users isassociated with each method that needs to be protected. Each component has an associated identity,transmitted at each remote method invocation, and used at the server side to check if the callingcomponent has the permission to call this method. An authenticator component is used to store theidentity and password of each user of the application. It is used to ensure that the identity transmittedwith each remote method call is not usurped.

To protect a component, the programmer must define, separately from the functional code, theauthorized users for each method of the component. This information is used at deployment time,and stored in an extension of the component’s container. Another extension is used to override theskeleton’s invoke method, in order to check that incoming remote method calls are authorizedbefore effectively executing them. To transmit the caller’s identity with each remote methodinvocation message, a stub’s extension (see Figure 13) is used to override the gtpSend method (seeSection 3.3.3), and a symmetric skeleton’s extension is used to override the gtpRecv method. Thesetwo methods respectively add and extract the caller’s identity to or from each message. Finally, twoother extensions, overriding the same methods and placed before the previous extensions, are used tocipher and uncipher each message, so that the identity (and password) added by the previous extensionsto each message can not be intercepted on the network.

4.1.3. Disconnected mode

In order to be able to use a component while in disconnected mode, a complete or partial copy ofthis component must be made upon disconnection. It is then possible to work with this copy whiledisconnected. Upon reconnection, this copy must be merged with the original component, knowingthat they may both have evolved since the copy was made.

Two problems must be solved to implement this solution: what should be copied upondisconnection? how should the copy and the original component be merged? Unfortunately, thereseems to be no generic response. In other words, the semantics of these operations strongly depends on

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 20: An architecture for extensible middleware platforms

1256 E. BRUNETON AND M. RIVEILL

the application semantics. For example, in the baghera application, when a student wants to disconnect,the VirtualSchool component and the student’s ElectronicCase component are copied completely, butthe other components are not copied or only partially: only the exercises (and not their solutions) thatappear in the student’s electronic case are copied from the ExerciseRepository, and the electronic casesand mailboxes of other users are not copied. When a student reconnects, the messages he or she haswritten during disconnection are really sent, and the exercises he or she has solved are added to theoriginal student’s ElectronicCase component. The VirtualSchool and ExerciseRepository componentare not merged, since students, connected or not, cannot modify these components.

Because of this lack of genericity we were only able to separate in extensions the mechanisms tosend, upon disconnection and reconnection, disconnect and reconnect messages to each appropriatecomponent, and to transmit, install and uninstall these copies. The clone and merge operations werenot separated from the functional code: they must be programmed in upcalls in the functional code ofcomponents. It was not possible to define or to configure these operations separately, as was the casewith persistence and protection.

4.2. Qualitative results

This section presents to what extent our goals were achieved with the baghera application. We recallthat these goals are the following: separation of functional and non-functional code, composition ofnon-functional properties, and a modular and extensible platform. They are evaluated each in turn.

4.2.1. Separation of functional and non-functional code

This goal is achieved for persistence and protection, but only partially for disconnected mode. It isprobably possible to improve this separation by requiring the application to give more information tothe middleware about the representation and semantics of its data. However, unless this informationcan be given separately from the functional code, this does not allow for a complete separation.

The separation of functional and non-functional code is therefore difficult to achieve for propertiesthat are not very ‘generic’, as could have been expected. However, we also found that this separation isnever really complete, even for very generic properties: even when the functional and non-functionalcode seem completely separated, implicit links may remain between them.

• The ‘granularity’ of application components depends on their non-functional properties.For example, it would have been possible to group the VirtualSchool, ExerciseRepository,ElectronicCase and Mailbox components into a single big component: functionally, this makesno difference. However, such a strategy would be very inefficient because of persistency: thewhole component would need to be serialized, even for very small modifications.

• The ‘granularity’ of component interfaces depends on the protection policy. For example, toprevent students from getting the solution of an exercise from the ExerciseRepository, whileallowing them to get the text of these exercises, we use two methods in the interface of thiscomponent (see Figure 10): one to get the text of an exercise, the other to get its solution.This way, two different ACLs can be associated with these methods. But the protection policy isthe only reason to use two methods instead of one.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 21: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1257

4.2.2. Composition of non-functional properties

This section defines and illustrates the concept of independent non-functional properties, and presentsour solution for the composition of the non-functional properties of the Baghera application.

The algorithm used to protect a component is the same for persistent and transient components.Similarly, the algorithm used for persistence is the same for protected and unprotected components.Protection and persistence are therefore said to be independent. On the contrary, protection and dis-connected mode are not independent, because the algorithm used to protect a component cannot be thesame in connected and in disconnected mode. For example, the access check used in connected modeto prevent students from getting the solution of an exercise would be ineffective in disconnected mode(because, to protect a component’s local copy, this access check would have to be performed by a local,untrusted client’s host). The only solution here is to send to clients, in disconnected mode, a partial andunprotected copy of the ExerciseRepository component, containing only the text of the exercises.

Composing independent non-functional properties, such as persistence and protection, or persistenceand disconnected mode, is easy with our platform. It is indeed sufficient to compose the extensionsrelated to the two non-functional properties, in the right order (specified manually), and to associatethem with stubs, skeletons, etc. But it is more difficult to compose non-functional properties that arenot independent. For example, to compose protection and disconnected mode, we had to modify thedisconnection algorithm, so as to send to clients, during the disconnection process, unprotected copiesof protected components (by default, a component’s copy has the same non-functional properties as theoriginal component, because the disconnection algorithm makes a complete copy of the component’scontainer). Fortunately, we were able to modify the disconnection algorithm by using additionalextensions: it was not necessary to change the existing extensions related to disconnected mode.

In order to facilitate the composition of non-functional properties, the system services providingthese properties should be implemented by using components and connectors. Thus, non-functionalproperties designed for applications can be applied to system services as well. For example, weimplemented the authenticator service in a component (see Section 4.1.2), so that it can easily bemade persistent. Likewise, the disconnection and reconnection protocols were implemented on top ofstandard client–server connectors, so that these protocols can easily be protected against illegal use.

4.2.3. Modularity and extensibility

Modularity was easily achieved: it was not difficult to program separately the extensions related topersistence, protection, and disconnected mode. Moreover, these ‘modules’ can be removed when theyare unused. They can also be replaced by other versions. For example, we implemented a protectionmechanism based on hidden software capabilities [10] instead of access control lists.

Extensibility is sometimes possible, but not always. For example, we wanted to prevent users fromsending messages with false emitter names. This required the protection model to be extended, so thatit can use method arguments, and not just the method name, to decide if a call can be accepted or not.This was easily done by implementing an application specific‡‡ extension overriding the skeleton’s

‡‡Because this extension uses application specific data structures.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 22: An architecture for extensible middleware platforms

1258 E. BRUNETON AND M. RIVEILL

Table I. Performances of extensible method calls. (Pentium III 730 MHz, ejavac 1.2).

Java ejava(invokeinterface) (extensible method call)

Linux, JDK 1.2.2, Borland JIT 0.22 µs 1.00 µsWindows NT 4, JDK 1.2.2, Hotspot 0.022 µs 0.30 µs

invoke method. Likewise, in order to improve performance, we were able to add application specificextensions to cache, on the client side, the results of frequently called remote methods (although theseextensions were absolutely not foreseen).

But in some cases it was necessary to modify existing code in order to add new functionalities to theplatform. For example, it was necessary to change the component identifiers used to implement basicclient–server connectors (see Section 3.3.3) when we introduced persistency. Indeed, these identifiersneeded to remain valid across several executions of the server, but they were initially valid only duringthe lifetime of a server. In some other cases, it was necessary to reorganize some code to isolate aportion of it in an extensible method, so that it could be easily overridden.

4.2.4. Usefulness of the object composition model

Although we motivated in Section 2.3.1 our object composition with an example based on a stub, wefound that it was also useful for skeletons, containers and servers. Its ability to override methods wasused, for example:

• in servers to automatically load persistent components (see Section 4.1.1);• in containers to automatically configure newly created stubs and skeletons, according to a

configuration/deployment descriptor (this was done by overriding, for example, the method tocreate skeletons—see Section 3.2.2);

• in stubs and skeletons to override the invoke method, but also the methods to send messagesbetween gates, to import and export connector references etc.

4.3. Quantitative results

Although we are not primarily interested in performance, this section gives some performance resultsto give an idea of the overhead introduced by our architecture.

The ejava language introduces an overhead for method calls to extensible methods (calls toother methods are unaffected). Indeed, as shown in Table I, an extensible method call to an emptymethod is five to fifteen times slower than the slowest type of Java method call (i.e. using theinvokeinterface opcode), depending on the Java Virtual Machine. This is important, but methodsare rarely empty. In practice, the overhead introduced by ejava is therefore much smaller. This can beseen by comparing the duration of a remote call to an empty method, by using Java RMI and the

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 23: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1259

Table II. Performances of remote method calls between two JVMson the same host. Client = request construction + reply analysis.Network = serialization + transmission + deserialization. Server= request analysis + method execution + reply construction.(Pentium III 730 MHz, Linux, JDK 1.2.2, Borland JIT, ejavac1.2, optimized object input and output stream classes—to avoid

sending full class descriptors in each message).

Time spent in . . . Java RMI JavaPod

Client – 0.06 msNetwork – 1.12 msServer – 0.18 ms

Total 0.90 ms 1.36 ms

JavaPod platform. In this case, as shown in Table II, the overhead drops to a factor of 1.5, which couldbe reduced by using a more efficient remote-method-call algorithm∗. In other words, the overhead dueto ejava alone is negligible when compared to the duration of remote method calls.

The performances of remote method calls drop dramatically when using persistence and/orprotection. This is mainly due to the ‘naive’ algorithms we used to implement these non-functionalproperties. For example, for persistence, since we serialize the container and all its stubs and skeletonsas well as the component itself, we obtain a serialized size ranging from 3 to 10 kilobytes for an emptycomponent (depending on the number of stubs and skeletons, and of the total number of extensions).It is certainly possible to do much better than that, but, in general, it is not sufficient to serialize thecomponent itself only. Likewise, for protection, performances drop because we use an RSA algorithmto cipher each message, instead of using symmetric-keys algorithms, which are much more efficient.

5. RELATED WORK

Our work belongs to several domains, such as middleware systems, extensible systems, reflexivesystems and languages, aspect-oriented programming or distributed algorithms. We only present herethe research work that has more or less the same goals as ours.

5.1. Proposals based on reflexive techniques

Meta-object based reflexive languages are object-oriented languages that include meta-objects,i.e. objects that can observe and modify the behavior of one or more base-level objects. Iguana, based

∗Our request and reply messages are constructed from nested objects, representing nested protocol data units (PDUs), with Java’sserialization mechanism (see Figure 13). This method, chosen for its simplicity, takes more time and produces bigger messagesthan optimized but more complex methods.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 24: An architecture for extensible middleware platforms

1260 E. BRUNETON AND M. RIVEILL

on C++, Actalk, based on SmallTalk, and also Dalang [11], Guarana [12] and metaXa [13], basedon Java, are examples of such languages. These languages can be used to separate non-functionalproperties from functional code. Indeed, non-functional properties such as synchronization, monitoringor protection are in fact optional behaviors that can be added to the normal behavior of a method call.In traditional programming languages, since the semantics of method calls cannot be changed, thesenon-functional properties must be implemented in the functional code of each method. In contrast,with a meta-object-based reflexive language, it is easy to put the code of non-functional properties in ameta-object, completely separated from the base-level program.

To separate the non-functional properties from each other, a meta-object composition technique mustbe used, so that each non-functional property can be implemented in its own meta-object. For this,one solution is to use an orthogonal composition technique: the meta-level is partitioned into severalmeta-spaces, where each meta-space can accept at most one meta-object. Each meta-space managesa specific aspect of the base-level behavior, independent from the other aspects. For example, theCodA language [14] decomposes the meta-level of an object into seven meta-spaces: send, accept,queue, receive, protocol, execution and state. CodA allows the definition of new meta-spaces, while Iguana and OpenORB [15] use a fixed set of meta-spaces.

Another solution to the composition of meta-objects is to use a non-orthogonal compositiontechnique. In this case, the meta-level can still be partitioned into several meta-spaces, but each meta-space can now receive more than one meta-object. For example, to associate several meta-objectsmodifying the semantics of method calls to a base-level object, a simple solution is to compose themin a list, so that a reified method call is handled by each meta-object in turn, before being handled bythe base-level object. This is the solution proposed in Dalang and metaXa. Other languages, such asGuarana, allow the programmer to define his or her own composition methods, which can be arbitrarilycomplex.

These two methods have been used to separate non-functional properties from the functional codein distributed systems, and in particular in the following platforms.

• The Tj platform [16], based on the CodA language (i.e. on an orthogonal composition approach)has been used to implement mobility, replication, and various marshaling rules at the meta-level.

• Singhai et al. [17] also use an orthogonal approach, with a fixed set of meta-spaces. For example,a stub has two meta-spaces, invoker and marshaler. This reflexive ORB has been usedto associate real-time constraints to remote method invocations, and to support load balancingor fault tolerance by using replicated servers that are invoked in turn (for load balancing), orsimultaneously (for fault tolerance). Since their ORB is not implemented in a reflexive language,‘meta-objects’ are in fact simulated by using a delegation model.

• The Flexinet ORB [18] uses the second approach: it decomposes stubs and skeletons in a list of‘meta-objects’. These ‘meta-objects’ are not, strictly speaking, true meta-objects, since Flexinetis not based on a reflexive language. However, they can be assimilated to meta-objects, since theymanipulate manually reified method calls. They can implement communication protocols as wellas non-functional properties. The Flexinet ORB has been used to implement mobile objects [19].

• The composition filters model [20] allows filters to be associated with objects. These filterscan manipulate the method invocation messages received by an object before the method isactually executed. They can therefore be seen as meta-objects. The filters of an object forma list, and each message is processed by each filter in turn. This model therefore uses a non-

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 25: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1261

orthogonal composition approach. It can be used to separate non-functional properties such assynchronization and real-time.

Meta-class based reflexive languages, such as CLOS [21], can also be used to separate non-functional properties from the functional code. For example, OpenCorba [22] uses such a languageto implement the remote method invocation mechanism and the type checking of remote methodinvocations in meta-classes.

5.2. Proposals based on aspect-oriented programming

The goal of aspect-oriented programming is to separate the code of each aspect of an application.An aspect designates any function that can not be isolated from the rest of the application byusing traditional programming building blocks, such as types, functions, procedures or objects. Errorhandling, optimizations, synchronization and memory management are examples of aspects. The goalof aspect-oriented programming is to find new programming techniques that allow aspects to beseparated from each other and from functional code.

The first possibility is to use a traditional language for the functional code, and a specialized languagefor each aspect. An application is then made of several separate programs, each dealing with an aspectof the application. An aspect weaver must be used to compose these programs into a single executable.Another approach, as in Aspect/J, is to use a single, low-level aspect language to program all theaspects. In both cases, the aspect weaver can either be static (i.e. used at compile time) or dynamic(i.e. used at runtime). A dynamic aspect weaver often has less freedom than a static one to composeaspects, but can potentially change the aspects that are associated with an application at runtime.Dynamic aspect weavers can be implemented using meta-objects to represent aspects [23].

Since many, if not all, non-functional properties are also aspects, aspect-oriented programming canbe used to separate non-functional properties from the functional code, as shown by the followingexamples.

• The D framework [24] uses two specialized aspect languages to separate synchronization andmarshaling aspects from the functional code of distributed applications.

• Lippert and Lopes [25] use Aspect/J to separate exception handling code from the functionalcode. As in the previous example, the aspect weaver used is static.

• The composition filters model, previously presented as a reflexive model, can also be used foraspect-oriented programming [26]. It can be used to separate synchronization and real-timeaspects and, with this model, the weaving of aspects can be done at runtime.

5.3. Comparison with our proposal

Would it have been better to build servers, containers, stubs and skeletons with one of the abovecomposition mechanisms? It is difficult to answer this question, because, if we had used anothermechanism, the resulting platform would have been completely different. However, if we suppose thatthe best way to build the previous elements is by using a mechanism that simulates class inheritance,without its disadvantages, then the question becomes easier: would it have been better to use anothermechanism to simulate class inheritance? We think that the answer is ‘no’, for the following reasons.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 26: An architecture for extensible middleware platforms

1262 E. BRUNETON AND M. RIVEILL

• Although it might be relatively easy to program composite objects in Aspect/J or in a languagewith mixin-based class inheritance [27], it would be difficult to modify these composite objectsdynamically because, in these languages, composition is done at compile time.

• Class inheritance could be simulated with meta-objects. However, using a meta-object protocolto override specific methods is less natural and more error-prone than using a language suchas ejava. Moreover, this solution would probably be slower than ours, because method calls tocomposite objects would need to be reified and reflected (the ejava language is implementedwithout using these costly operations).

• A composite object o can be simulated in Self [28] by linking its members through parent*slots; but this requires the extensible object to be placed at the tail of this linked list, andto reference o through a ‘sentinel’ object placed at the head of the list. Moreover, and mostimportantly, static typing of ‘normal’ objects is impossible with this solution.

Our proposal can also be compared, at a higher level, to the middleware platforms cited in theprevious sections. The result is that our middleware platform architecture has the following advantagesand disadvantages.

+ Our architecture was designed to allow any type of interactions between components. In contrast,the Flexinet platform and the platform proposed by Singhai et al. [17] are restricted toclient–server interactions (the Tj platform can probably support other types of interaction, butthe examples given in Reference [16] are all based on client–server interactions).

+ Our architecture has a component concept, which allows non-functional properties to be appliedto groups of objects (when a component moves or is serialized, all the object it containsare moved or serialized simultaneously). In contrast the Tj platform associates meta-objectswith individual objects. Likewise, Singhai et al. [17] and the Flexinet platform concentrate onbindings, and do not propose a component concept (it is however possible to add a ‘cluster’concept on top of Flexinet [19]).

+ Our architecture makes a good tradeoff between extensibility and performance. Tj is extremelyextensible but probably slow (there are no quantitative results, but the use of CodA, based onSmallTalk, probably slows down the platform and its applications). In contrast, the very limitedform of reflection used by Singhai et al. [17] makes their platform efficient but also poorlyextensible.

− Our architecture has not been tested with a real-world middleware platform, but only withthe JavaPod prototype. Therefore, it is not sure that our architecture still ‘works’ with a real-world platform. In contrast, the Flexinet platform is not a ‘toy’ platform. In particular, it is fullyresource controlled, and uses pools for resources such as buffers and threads.

To conclude this section, it should be noted that the platform proposed by Blair and colleagues[29,30,15], which was not designed for the same goals as ours, and was therefore not presented inthe previous sections, has in fact many similarities with our platform. For example, it allows any typeof interaction between components. Likewise, the meta-spaces used to allow applications to adapt theplatform to their own needs can probably be used to associate non-functional properties with them.Unfortunately, this platform is not yet completely implemented, and it is therefore difficult to compareit with our platform in greater detail.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 27: An architecture for extensible middleware platforms

AN ARCHITECTURE FOR EXTENSIBLE MIDDLEWARE PLATFORMS 1263

6. CONCLUSION

The baghera application shows that, depending on the environment in which it is deployed, anapplication must be adapted differently, i.e. it must be associated with different non-functionalproperties. To satisfy these needs, we think that a supporting middleware platform should satisfythree requirements that can be summarized as follows: separation of functional and non-functionalcode in applications, composition of non-functional properties, and modularity and extensibility of theplatform itself. To achieve these goals, we propose to use an architecture inspired by the EnterpriseJava Beans platform, and extended with a new object composition model (to separate and compose thecode implementing non-functional properties). In order to evaluate this architecture, we implementedthe JavaPod platform, and then a prototype of the baghera application.

The results of these experiments are that, globally, our architecture actually achieves our goals.We were indeed able to separate completely the non-functional code related to persistence andprotection, to compose persistence, protection and disconnectedness, and to add unforeseen extensionsto the middleware platform. Moreover, we think that our composition model is more adapted for ourneeds than other composition techniques such as meta-objects. There are however some limitations.Some non-functional properties are not very ‘generic’, and therefore not easy to separate from thefunctional code. Composing non-functional properties can require additional code to cope with theinterdependencies of non ‘orthogonal’ properties. Finally, it is sometimes necessary to modify existingcode when extending the platform. However, these limitations seem more intrinsic than linked to ourarchitecture. They seem to arise from (irreducible?) semantic interdependencies between the functionaland non-functional code, and between the system services.

Besides these limitations, a lot of open issues remain to be solved. Can extensions be sortedautomatically so that they result in a ‘correct’ semantics (for the moment, this must be done manually)?Is our object composition model appropriate for a more ‘realistic’ middleware platform (in ourprototype, all low-level mechanisms such as buffer management thread scheduling, or communicationprotocols are overly simplified)? How can we dynamically reconfigure the platform in a consistentway?

REFERENCES

1. Balacheff N. Teaching, an emergent property of eLearning environments. Proceedings of the Information Society for All(IST), Nice, France, 2000.

2. ODP reference model: Overview. ITU-T—ISO/IEC Recommendation X.901—International Standard 10746-1, 1995.3. CORBA 3.0 CCM FTF draft ptc/99-10-04, 1999.4. Bruneton E, Riveill M. JavaPod: une plate-forme a composants adaptable et extensible. Technical Report RR-3850, INRIA,

2000.5. Bruneton E, Riveill M. JavaPod: an adaptable and extensible component platform. Proceedings of the Workshop on

Reflective Middleware (RM’2000), New York, USA, 2000.6. The KOPI project. Decision Management Systems. http://www.dms.at/kjc/ [1999].7. The ejava compiler. SIRAC Project, INRIA. http://sirac.inrialpes.fr/Logiciel/.8. Bruneton E, Riveill M. Reflective implementation of non-functional properties with the JavaPod component platform.

Proceedings of the Workshop on Reflection and Metalevel Architectures (RMA’2000), Cannes, France, 2000. OnlineProceedings available at http://www.disi.unige.it/RMA2000.

9. Krishnaswamy V, Walter D, Bhola S, Bommaiah E, Riley G, Topol B, Ahamad M. Efficient implementation of Java remotemethod invocation (RMI). Proceedings of the 4th USENIX Conference on Object-Oriented Technologies and Systems(COOTS), Santa Fe, New Mexico, 1998; 19–35.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264

Page 28: An architecture for extensible middleware platforms

1264 E. BRUNETON AND M. RIVEILL

10. Hagimont D, Ismaıl L. A protection scheme for mobile agents on Java. Proceedings of the 3rd ACM/IEEE InternationalConference on Mobile Computing and Networking (MOBICOM), Budapest, Hungary, 1997; 215–222.

11. Welch I, Stroud R. Dalang—a reflective Java extension. Proceedings of the OOPSLA’98 Workshop on ReflectiveProgramming in C++ and Java, Vancouver, Canada, 1998; 11–15.

12. Oliva A, Buzato LE. The design and implementation of Guarana. Proceedings of the 5th USENIX Conference on Object-Oriented Technologies and Systems (COOTS), San Diego, California, USA, 1999.

13. Golm M, Kleinoder J. metaXa and the future of reflection. Proceedings of the OOPSLA’98 Workshop on ReflectiveProgramming in C++ and Java, Vancouver, Canada, 1998.

14. McAffer J. Meta-level programming with CodA. Proceedings of the European Conference on Object-OrientedProgramming (ECOOP), Aarhus, Denmark, 1995 (Lecture Notes in Computer Science, vol. 952). Springer: Berlin, 1995;190–214.

15. Blair GS, Coulson G, Costa F, Duran HA. On the design of reflective middleware platforms. Proceedings of the Workshopon Reflective Middleware (RM’2000), New York, USA, 2000.

16. McAffer J. Meta-level architecture support for distributed objects. Proceedings International Workshop on Object-Orientation in Operating Systems, Lund, Sweden, 1995. IEEE, 1995, 232–241.

17. Singhai A, Sane A, Campbell R. Reflective ORBs: Supporting robust, time-critical distribution. Proceedings of theECOOP’97 Workshop on Reflective Real-Time Object-Oriented Systems, Jyvaskyla, Finland, 1997.

18. Hayton R, Herbert A, Donaldson D. FlexiNet: a flexible, component oriented middleware system. Proceedings of theEuropean Workshop Support for Composing Distributed Applications, Sintra, Portugal, 1998 (Lecture Notes in ComputerScience, vol. 1752). 1998; 497.

19. Hayton R, Bursell MH, Donaldson D, Herbert A. Mobile Java objects. Proceedings of the International Conference onDistributed Systems Platforms and Open Distributed Processing (MIDDLEWARE), The Lake District, UK, 1998.

20. Bergmans LM. The composition filters object model. Department of Computer Science, University of Twente, 1994.http://trese.cs.utwente.nl/publications/paperinfo/cf.pi.ref.htm.

21. DeMichiel LG, Gabriel RP. The Common Lisp object system: An overview. Proceedings of the European Conferenceon Object-Oriented Programming (ECCOP), San Diego, California, USA, 1997 (Lecture Notes in Computer Science,vol. 276). Springer: Berlin, 1995; 15–170.

22. Ledoux T. OpenCorba: a reflective open broker. Proceedings of the 2nd International Conference on MetalevelArchitectures and Reflection (REFLECTION), Saint-Malo, France, 1999 (Lecture Notes in Computer Science, vol. 1616).Springer: Berlin, 1995; 197–214.

23. Lunau CP. Is composition of metaobjects = aspect oriented programming. Proceedings of the ECOOP’98 Aspect-OrientedProgramming Workshop, Brussels, Belgium, 1998.

24. Lopes CV, Kiczales G. D: A language framework for distributed programming. Technical Report SPL97-010, Xerox PaloAlto Research Center, 1997.

25. Lippert M, Lopes CV. A study on exception detection and handling using aspect-oriented programming. Technical ReportP9910229 CSL-99-1, Xerox Palo Alto Research Center, 1999.

26. Aksit M, Tekinerdogan B. Solving the modeling problems of object-oriented languages by composing multiple aspectsusing composition filters. Proceedings of the ECOOP’98 Aspect-oriented Programming Workshop, Brussels, Belgium,1998. Object-oriented Technology ECOOP’98 Workshop Reader, Demeyer S, Bash J (eds.). Springer: Berlin, 1998.

27. Bracha G, Cook W. Mixin-based inheritance. Object Oriented Programming Systems Languages and Applications(OOPSLA), Ottawa, Canada. ACM SIGPLAN Notices 1990; 25(10):303–311.

28. Ungar D, Smith RB. Self: The power of simplicity. Object Oriented Programming Systems Languages and Applications(OOPSLA), Orlando, USA. ACM SIGPLAN Notices 1987; 22(12):227–242.

29. Blair GS, Coulson G, Robin P, Papathomas M. An architecture for next generation middleware. Proceedings of theInternational Conference on Distributed Systems Platforms and Open Distributed Processing (MIDDLEWARE), The LakeDistrict, UK, 1998; 191–206.

30. Costa FM, Blair GS, Coulson G. Experiments with reflective middleware. Proceedings of the ECOOP’98 Workshop onReflective Object-Oriented Programming and Systems, Brussels, Belgium, 1998.

Copyright 2001 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2001; 31:1237–1264