Introduction To Middle Ware
Introduction To Middle Ware
c
2003-2009,
Sacha Krakowiak (version of February 27, 2009 - 12:58)
Creative Commons license (http://creativecommons.org/licenses/by-nc-nd/3.0/)
Chapter 1
An Introduction to Middleware
This chapter is an introduction to middleware. It starts with a motivation for middleware
and an analysis of its main functions. It goes on with a description of the main classes
of middleware. Then follows a presentation of a simple example, Remote Procedure Call,
which introduces the main notions related to middleware and leads to a discussion of the
main design issues. The chapter concludes with a historical note outlining the evolution
of middleware.
1.1
1-2
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
exchange protocols for communication between applications. These protocols are implemented by a software layer that acts as an exchange bus, also called a broker, between the
applications. The method for integrating a legacy application is to develop a wrapper, i.e.
a piece of software that serves as a bridge between the applications primitive interface
and a new interface that conforms to the selected standard.
legacy
application
legacy
application
wrapper
wrapper
proprietary
interface
new
component
standard
interface
standard
interface
inter-applications exchange bus
new
component
wrapper
legacy
application
A wrapped legacy application may now be integrated with other such applications
and with newly developed components, using the standard inter-applications protocols
and the inter-applications broker. Examples of such brokers are CORBA, message queues,
publish-subscribe systems; they are developed further in this book.
Example 2: mediation systems. An increasing number of systems are composed of
a collection of various devices interconnected by a network, where each individual device performs a function that involves both local interaction with the real world and remote interaction with other devices of the system. Examples include computer networks,
telecommunication systems, uninterruptible power supply units, decentralized manufacturing units.
Managing such systems involves a number of tasks such as monitoring performance,
capturing usage patterns, logging alarms, collecting billing information, executing remote
maintenance functions, downloading and installing new services. Performing these tasks
involves remote access to the devices, data collection and aggregation, and reaction to
critical events. The systems that are in charge of these tasks are called mediation systems.
The internal communication infrastructure of a mediation system needs to cater for
data collection (data flowing from the devices towards the management components, as
well as for requests and commands directed towards the devices. Communication is often
triggered by an asynchronous event (e.g. the occurrence of an alarm or the crossing of a
threshold by a monitored value).
An appropriate communication system for such situations is a message bus, i.e. a
common channel to which the different communicating entities are connected (Figure
1.2). Communication is asynchronous and may involve a varying number of participants.
1-3
administrator
administrator
router
networked equipment
message bus
1-4
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
application components
domain-specific
service interface
domain-specific
services
clients
client
call interface
database
common
service interface
database
1-5
Clients
Proxy
Servers
the Internet
2. Hiding the heterogeneity of the various hardware components, operating systems and
communication protocols that are used by the different parts of an application.
3. Providing uniform, standard, high-level interfaces to the application developers and
integrators, so that applications can easily interoperate and be reused, ported, and
composed.
4. Supplying a set of common services to perform various general purpose functions, in
order to avoid duplicating efforts and to facilitate collaboration between applications.
These intermediate software layers have come to be known under the generic name
of middleware (Figure 1.5). A middleware system may be general purpose, or may be
dedicated to a specific class of applications.
Application
Standard API
Application
Standard API
Application
Standard API
Middleware
Specific API
Specific API
Operating
system
Specific API
Operating
system
Operating
system
Communication system
Using middleware has many benefits, most of which derive from abstraction: hiding
low-level details, providing language and platform independence, reusing expertise and
1-6
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
possibly code, easing application evolution. As a consequence, one may expect a reduction
in application development cost and time, better quality (since most efforts may be devoted
to application specific problems), and better portability and interoperability.
A potential drawback is the possible performance penalty linked to the use of multiple
software layers. Using middleware technologies may also entail a significant retraining
effort for application developers.
1.2
Categories of Middleware
Middleware systems may be classified according to different criteria, including the properties of the communication infrastructure, the global architecture of the applications, the
provided interfaces.
Communication properties. The communication infrastructure that underlies a middleware system is characterized by several properties that allow a first categorization.
1. Fixed vs variable topology. In a fixed communication system, the communicating
entities reside at fixed locations, and the configuration of the network does not change
(or such changes are programmed, infrequent operations). In a mobile (or nomadic)
communication system, some or all communicating entities may change location,
and entities may connect to or disconnect from the system, while applications are in
progress.
2. Predictable vs unpredictable characteristics. In some communication systems, bounds
can be established for performance factors such as latency or jitter. In many practical
cases, however, such bounds are not known e.g. because the performance factors
depend on the load on shared devices such as a router or a communication channel.
A synchronous communication system is one in which an upper bound is known for
the transmission time of a message; if such a bound cannot be predicted, the system
is said to be asynchronous 1 .
Usual combinations of these characteristics are defined as follows.
Fixed, unpredictable. This is the most frequent case, both for local and wide area
networks (e.g. the Internet). Although an average message transmission time may be
estimated in many current situations, it is impossible to guarantee an upper bound.
Fixed, predictable. This applies to environments developed for specially demanding
applications such as hard real time control systems, which use a communication protocol that guarantees bounded message transfer time through resource reservation.
Variable, unpredictable. This is the case of communication systems that include mobile (or nomadic) devices such as mobile phones or PDAs. Communication with such
devices use wireless technologies, which are subject to unpredictable performance
1
In a distributed system, the term asynchronous usually indicates, in addition, that an upper bound is
not known for the ratio of processing speeds at different sites (a consequence of the unpredictable load on
shared processors).
1.3
We now present a simple middleware system, Remote Procedure Call (RPC). We do not
intend to cover all the details of this mechanism, which may be found in all distributed
1-8
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
systems textbooks, but to introduce a few patterns that will be found repeatedly in other
middleware architectures, as well as some design issues.
1.3.1
P(x,y)
site A
process p
site B
site A
P(x,y)
P(x,y)
network
interface
interface
interface
By preserving the semantics between local and remote call, procedural abstraction is
preserved; portability is improved because the application is independent of the underlying communication protocols. In addition, an application may easily be ported, without
changes, between a local and a distributed environment.
However, preserving semantics is no easy task, for two main reasons.
the failure modes are different in the local and distributed cases; in the latter, the
client site, the server site and the network may fail independently;
even in the absence of failures, the semantics of parameter passing is different (e.g.
passing a pointer as a parameter does not work in the distributed case because the
calling process and the procedure execute in distinct address spaces).
Concerning parameter passing, the usual solution is to use call by value for parameters
of simple types. Fixed-size structures such as arrays or records can also be dealt with.
In the general case, passing by reference is not supported, although solutions exist such
as specific packing and unpacking routines for pointer-based structures. The technical
aspects of parameter passing are examined in Section 1.3.2.
Concerning the behavior of RPC in the presence of failures, there are two main difficulties, at least if the underlying communication system is asynchronous (in the sense of
unpredictable). First, it is usually impossible to know upper bounds on message transmission time; therefore a network failure detection method based on timeouts runs the risk of
false detections. Second, it is difficult to distinguish between the loss of a message and the
failure of a remote processor. As a consequence, a recovery action may lead to a wrong
decision such as re-executing an already executed procedure. Fault tolerance aspects are
examined in Section 1.3.2.
1.3.2
Implementation Principles
The standard implementation of RPC [Birrell and Nelson 1984] relies on two pieces of
software, the client stub and the server stub (Figure 1.7). The client stub acts as a local
representative of the server on the client site; the server stub has a symmetrical role. Thus
both the calling process (on the client side) and the procedure body (on the server side)
keep the same interface as in the centralized case. The client and server stubs rely on a
communication subsystem to exchange messages. In addition, they use a naming service
in order to help the client locate the server (this point is developed in section 1.3.3).
client
server
procedure
call interface
procedure
call interface
client stub
name service
server stub
communication
interface
communication
interface
communication
subsystem
network
communication
subsystem
1-10
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
fixed-size pool of worker threads (Figure 1.8 (c)). Worker threads communicate with the
daemon through a shared buffer using the producer-consumer scheme. Worker threads
are waiting for new work to arrive; after executing the procedure, a worker thread returns
to the pool, i.e. tries to get new work to do. If all worker threads are busy when a call
arrives, the execution of the call is delayed until a thread becomes free.
daemon
thread
daemon
thread
wait
wait
call
worker
thread
execute P
create
thread
call
daemon
thread
worker
thread
buffer
wait
wait
call
get
work to do
execute P
P(x, y)
put
work to do
P(x, y)
execute P
return
return
P(x, y)
exit
return
(c) thread pool
Figure 1.8. Remote procedure call: thread management on the server side
correctly, or it stops), and message loss for communication (i.e. either a message arrives
uncorrupted, or it does not arrive at all, assuming that message corruption is dealt with
at the lower levels of the communication system). Failure detection mechanisms are based
on timeouts. When a message is sent, a timeout is set at an estimated upper bound of the
expected time for receipt of a reply. If the timeout is triggered, a recovery action is taken.
Such timeouts are set both on the client site (after sending the call message) and on
the server site (after sending the reply message). In both cases, the message is resent after
timeout. The problem is that an upper bound cannot be safely estimated; a call message
may be resent in a situation where the call has already been executed; the call might then
be executed several times.
The net result is that it is usually impossible to guarantee the so-called exactly once
semantics, meaning that, after all failures have been repaired, the call has been executed
exactly one time. Most systems guarantee an at most once semantics (the call is either
executed, or not at all, but partial or multiple executions are precluded). The at least
once semantics, in which the call is executed one or more times, is acceptable when the
call is idempotent, i.e. the effect of two calls in succession is identical to that of a single
call.
The overall organization of RPC, not showing the aspects related to fault tolerance, is
described on Figure 1.9
Client
stub
Client
Communication
subsystem
Server
stub
Communication
subsystem
Server
call P(x, y)
m=marshall(P, x, y)
network transmission
wait
send(m)
creates
or selects
thread
[P, x, y]=
unmarshall(m)
m=receive()
call P(x, y)
unblock
return r
send(q)
network transmission
q=receive()
return r
q=marshall(r)
thread exits or
returns to pool
r=unmarshall(q)
1.3.3
In order to actually develop an application using RPC, a number of practical issues need
to be settled: how are the client and the server linked together? how are the client and
1-12
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
server stubs constructed? how are the programs installed and started? These issues are
considered in turn below.
Client-Server Binding. The client needs to know the server address and port number
to which the call should be directed. This information may be statically known, and
hardwired in the code. However, in order to preserve abstraction, to ensure a flexible
management of resources, and to increase availability, it is preferable to allow for a late
binding of the remote execution site. Therefore, the client must locate the server site prior
to the call.
This is the function of a naming service, which is essentially a registry that associates
procedure names (and possibly version numbers) with server addresses and port numbers.
A server registers a procedure name together with its IP address and the port number at
which the daemon process is waiting for calls on that procedure. A client consults the
naming service to get the IP address and port number for a given procedure. The naming
service is usually implemented as a server of its own, whose address and port number are
known to all participant nodes.
Figure 1.10 shows the overall pattern of interaction involving the naming service.
Client
Client
stub
Naming
service
call P(x, y)
Server
stub
Server
P(x, y)
The problem of binding the server to the client is easily solved by including the address
and port number of the client in the call message.
Stub generation. As seen in Section 1.3.2, the stubs fulfill a set of well-defined functions, part of which is generic (e.g. process management) and part of which depends on
the specific call (e.g. parameter marshalling and unmarshalling). Considering this fixed
pattern in their structure, stubs are obvious candidates for automatic generation.
The call-specific parameters needed for stub generation are specified in a special notation known as an Interface Definition Language (IDL). An interface description written in
IDL contains all the information that defines the interface of the procedure call: it acts as
a contract between the caller and the callee. For each parameter, the description specifies
its type and mode of passing (e.g. by value, by copy-restore, etc.). Additional information
such as version number and mode of activation may also be specified.
Several IDLs have been defined (e.g. Sun XDR, OSF DCE). The stub generator is
associated with a specific common data representation format associated with the IDL;
Client application
gcc
client_proc.c
client
client stub
proc_clnt.c
source
code
conversions
proc_xdr.c
libraries
rpcgen
proc.x
definitions
proc.h
Interface
definition
executable
code
server stub
proc_svc.c
gcc
server_proc.c
server
provided by programmer
Server application
tools and services
generated
it inserts the conversion routines provided by the corresponding marshallers and unmarshallers. The overall development cycle of an application using RPC is shown on Figure
1.11 (the notation is that of Sun RPC).
Application Deployment. Deployment is the process of installing the program pieces
that make up a distributed application on their respective sites and of starting their
execution when needed. In the case of RPC, the installation is usually done by executing
prepared scripts that call the tools described in Figure 1.11, possibly using a distributed
file system to retrieve the source files. As regards activation, the constraints are that the
server needs to be activated before the first call of a client, and that the naming service
must be activated before the server. These activations may again be performed by a script;
the server may also be directly activated by a client (in that case, the client needs to be
allowed to run a remote script on the servers site).
1.3.4
1-14
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
1.4
In this section, we first discuss the main issues of middleware organization, which define the
structure of the rest of the book. We then identify a few general requirements that favor
a principled design approach. We conclude by listing a few challenges for the designers of
future middleware systems.
1.4.1
Design Issues
1-15
Naming and binding are central in middleware design, since middleware may be defined
as software that binds pieces of application software together. Naming and binding are
the subject of Chapter 3.
Any middleware system relies on a communication layer that allows its different pieces
to interoperate. In addition, communication is a function provided by middleware itself
to applications, in which the communicating entities may take on different roles such as
client-server or peer to peer. Communication is the subject of Chapter 4.
Middleware allows different interaction modes (synchronous invocations, asynchronous
message passing, coordination through shared objects) embodied in different patterns. The
main paradigms of middleware organization using distributed objects, mainly in clientserver mode, are examined in Chapter 5. The paradigms based on asynchronous events
and coordination are the subject of Chapter 6.
Software architecture deals with the structural description of a system in terms of
elementary parts. The notions related to composition and components are now becoming
a key issue for middleware, both for its own organization and for that of the applications
it supports. Software composition is the subject of Chapter 7.
Data management brings up the issues of persistence (long term data conservation and
access procedures) and transactions (accessing data while preserving consistency in the
face of concurrent access and possible failures). Persistence is the subject of Chapter 8,
and transactions are examined in Chapter 9.
Administration is a part of the applications life cycle that is taking an increasing
importance. It involves such functions as configuration and deployment, monitoring, and
reconfiguration. Administration middleware is the subject of Chapter 10.
Quality of Service includes various properties of an application that are not explicitly
formulated in its functional interfaces, but that are essential for its users. Three specific aspects of QoS are reliability and availability, performance (specially for time-critical
applications), and security. They are respectively covered in Chapters 11, 12, and 13.
1.4.2
Architectural Guidelines
In this section, we briefly discuss a few considerations derived from experience. They are
generally applicable to software systems, but are specially relevant to middleware, due to
its dual function of mediator and common services provider.
Models and Specifications
A model is a simplified representation of (part of) the real world. A given real object may
be represented by different models, according to the domain of interest and to the accuracy
and degree of detail of the representation. Models are used to better understand the object
being represented, by explicitly formulating relevant hypotheses, and by deriving useful
properties. Since no model is a perfect representation of the reality, care must be taken
when transposing the results derived from a model to the real world. A discussion of the
use (and usefulness) of models for distributed systems may be found in [Schneider 1993].
Models (with various degrees of formality) are used for various aspects of middleware,
including naming, composition, fault tolerance, and security.
1-16
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
Models help in the formulation of rigorous specifications. When applied to the behavior
of a system, specifications fall into two categories:
Safety (informally: no undesirable event or condition will ever occur).
Liveness (informally: a desirable event or condition will eventually occur).
For example, in a communication system, a safety property is that a delivered message
is not corrupted (i.e., it is identical to the message sent), while an example of liveness is
that a message sent will eventually be delivered to its destination. Liveness is often more
difficult to ensure than safety. Specifications of concurrent and distributed systems are
discussed in [Weihl 1993].
Separation of Concerns
In software engineering, separation of concerns refers to the ability to isolate independent,
or loosely related, aspects of a design and to deal with each of them separately. The
expected benefits are to allow the designer and developer to concentrate on one problem
at a time, to eliminate artificial interactions between orthogonal concerns, and to allow
independent variation of the requirements and constraints associated with each separate
aspect. Separation of concerns has deep implications both on the architecture of middleware and on the definition of roles for the division of the design and implementation
tasks.
Separation of concerns may be viewed as a meta-principle that can take a number
of specific forms, of which four examples follow.
The principle of encapsulation (2.1.3) separates the concerns of the user of a software
component from those of its implementor, through a common interface definition.
The principle of abstraction allows a complex system to be decomposed into levels
(2.2.1), each level providing a view that hides irrelevant details which are dealt with
at lower levels.
Separation between policy and mechanism [Levin et al. 1975] is a widely used principle, specially in the area of resource management and protection. This separation
brings flexibility for the policy designer, while avoiding overspecification of the mechanisms. It should be possible to change a policy without having to reimplement the
mechanisms.
The principle of orthogonal persistence (8.2) separates the issue of defining the lifetime of data from other aspects such as the type of the data or the properties of
their access programs.
These points are further developed in Chapter 2.
In a more restricted sense, separation of concerns attempts to deal with aspects whose
implementation, in the current state of the art, is scattered among various parts of a
software system, and tightly interwoven with other aspects. The goal is to allow a separate expression of aspects that are considered independent and, ultimately, to be able
1-17
to automate the task of producing the code dealing with each aspect. Examples of such
aspects are those related to extra-functional properties (see 2.1.2) such as availability,
security, persistence, and those dealing with common functions such as logging, debugging,
observation, transaction management, which are typically implemented by pieces of code
scattered in many parts of an application.
Separation of concerns also helps identifying specialized roles in the design and development process, both for applications and for the middleware itself. By focusing on a
particular aspect, the person or team that embodies a role can better apply his expertise
and improve the efficiency of his work. Examples of roles associated with various aspects
of component software may be found in Chapter 7.
Evolution and Adaptation
Software systems operate in a changing environment. Sources of change include evolving
requirements resulting from the perception of new needs, and varying execution conditions
due to the diversity of communication devices and systems, which induce unpredictable
variations of quality of service. Therefore both applications and middleware need to be
designed for change. Responding to evolving requirements is done by program evolution.
Responding to changing execution conditions is done by dynamic adaptation.
In order to allow evolution, the internal structure of the system must be made accessible. There is an apparent contradiction between this requirement and the principle of
encapsulation, which tends to hide implementation details.
There are several ways to deal with this problem. Pragmatic techniques, often based
on interception (2.3.4), are widely used for commercial middleware. A more systematic
approach is to use reflection. A reflective system [Smith 1982, Maes 1987] is one that provides a representation of itself, in order to enable inspection (answering questions about
the system) and adaptation (modifying the behavior of the system). To ensure consistency,
the representation must be causally connected to the system, i.e. any change of the system
must be reflected in its representation, and vice versa. Meta-object protocols provide such
an explicit representation of the basic mechanisms of a system and a protocol to examine
and to modify this representation. Aspect-oriented programming, a technology designed
to ensure separation of concerns, is also useful for implementing dynamic evolution capabilities. These techniques and their use in middleware systems are reviewed in Chapter
2.
1.4.3
Challenges
1-18
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
Large scale. As applications become more and more interconnected and interdependent, the number of objects, users and devices tends to increase. This poses the
problem of the scalability of the communication and object management algorithms,
and increases the complexity of administration (for example, does it even make sense
to try to define and capture the state of a very large system?). Large scale also
complexifies the task of preserving the various forms of Quality of Service.
Ubiquity. Ubiquitous (or pervasive) computing is a vision of the near future, in
which an increasing number of devices embedded in various physical objects will be
participating in a global information network. Mobility and dynamic reconfiguration
will be dominant features, requiring permanent adaptation of the applications. Most
of the architectural concepts applicable to systems for ubiquitous computing are still
to be elaborated.
Management. Managing large applications that are heterogeneous, widely distributed
and in permanent evolution raises many questions, such as consistent observation,
security, tradeoffs between autonomy and interdependence for the different subsystems, definition and implementation of resource management policies.
1.5
Historical Note
The term middleware seems to have appeared around 1990, but middleware systems existed long before that date. Messaging systems were available as products in
the late 1970s. The classical reference on Remote Procedure Call implementation is
[Birrell and Nelson 1984], but RPC-like, language-specific constructs were already in use
by then (the original idea of RPC appeared in [White 1976]2 and an early implementation
was proposed in [Brinch Hansen 1978]).
Starting in the mid-1980s, a number of research projects developed middleware
support for distributed objects, and elaborated the main concepts that influenced
later standards and products.
Early efforts are Cronus [Schantz et al. 1986] and
Eden [Almes et al. 1985]. Later projects include Amoeba [Mullender et al. 1990], ANSAware [ANSA ], Arjuna [Parrington et al. 1995], Argus [Liskov 1988], Chorus/COOL
[Lea et al. 1993], Clouds [Dasgupta et al. 1989], Comandos [Cahill et al. 1994], Emerald
[Jul et al. 1988], Gothic [Ban
atre and Banatre 1991], Guide [Balter et al. 1991], Network
Objects [Birrell et al. 1995], SOS [Shapiro et al. 1989], and Spring [Mitchell et al. 1994].
The Open Software Foundation (OSF), later to become the Open Group
[Open Group ], was created in 1988 in an attempt to unify the various versions of the Unix
operating system. While this goal was never reached, the OSF specified a software suite,
the Distributed Computing Environment (DCE) [Lendenmann 1996], which included such
middleware components as an RPC service, a distributed file system, a distributed time
service, and a security service.
The Object Management Group (OMG) [OMG ] was created in 1989 in order to define standards for distributed object middleware. Its first effort led to the CORBA 1.0
2
REFERENCES
1-19
specification in 1991 (the latest version, as of 2003, is CORBA 3). Later developments include standards for modeling (UML, MOF) and components (CCM). The Object Database
Management Group (ODMG) [ODMG ] defines standards applicable to object databases,
bridging the gap between object-oriented programming languages and persistent data management.
The Reference Model for Open Distributed Processing (RM-ODP) [ODP 1995a],
[ODP 1995b] was jointly defined by two standards bodies, ISO and ITU-T. Its contribution is a set of concepts that define a generic framework for open distributed computing,
rather than a specific standard.
The definition of the Java programming language by Sun Microsystems in 1995 led the
way to several middleware developments such as Java Remote Method Invocation (RMI)
[Wollrath et al. 1996] and the Enterprise JavaBeans (EJB) [Monson-Haefel 2002]. These
and others are integrated in a common platform, J2EE [J2EE ].
Microsoft developed the Distributed Component Object Model (DCOM)
[Grimes 1997], a middleware based on composable distributed objects, and an improved version, COM+ [Platt 1999]. Its next offering is .NET [.NET ], a software
platform for distributed applications development and Web services provision.
The first scientific conference entirely dedicated to middleware took place in 1998
[Middleware 1998]. Current research issues include adaptive and reflective middleware,
and middleware for mobile and ubiquitous systems.
References
[Almes et al. 1985] Almes, G. T., Black, A. P., Lazowska, E. D., and Noe, J. D. (1985). The Eden
system: A technical review. IEEE Transactions on Software Engineering, SE-11(1):4359.
[ANSA ] ANSA. Advanced networked systems architecture. http://www.ansa.co.uk/.
[Balter et al. 1991] Balter, R., Bernadat, J., Decouchant, D., Duda, A., Freyssinet, A., Krakowiak,
S., Meysembourg, M., Le Dot, P., Nguyen Van, H., Paire, E., Riveill, M., Roisin, C., Rousset de
Pina, X., Scioville, R., and Vandome, G. (1991). Architecture and implementation of Guide, an
object-oriented distributed system. Computing Systems, 4(1):3167.
[Banatre and Ban
atre 1991] Ban
atre, J.-P. and Ban
atre, M., editors (1991). Les syst`emes dis
tribues : experience du projet Gothic. InterEditions.
[Birrell and Nelson 1984] Birrell, A. D. and Nelson, B. J. (1984). Implementing remote procedure
calls. ACM Transactions on Computer Systems, 2(1):3959.
[Birrell et al. 1995] Birrell, A. D., Nelson, G., Owicki, S., and Wobber, E. (1995). Network objects.
SoftwarePractice and Experience, 25(S4):87130.
[Brinch Hansen 1978] Brinch Hansen, P. (1978). Distributed Processes: a concurrent programming
concept. Communications of the ACM, 21(11):934941.
[Cahill et al. 1994] Cahill, V., Balter, R., Harris, N., and Rousset de Pina, X., editors (1994). The
COMANDOS Distributed Application Platform. ESPRIT Research Reports. Springer-Verlag.
312 pp.
[Dasgupta et al. 1989] Dasgupta, P., Chen, R. C., Menon, S., Pearson, M. P., Ananthanarayanan,
R., Ramachandran, U., Ahamad, M., LeBlanc, R. J., Appelbe, W. F., Bernabeu-Auban, J. M.,
Hutto, P. W., Khalidi, M. Y. A., and Wilkenloh, C. J. (1989). The design and implementation
of the Clouds distributed operating system. Computing Systems, 3(1):1146.
1-20
CHAPTER 1.
AN INTRODUCTION TO MIDDLEWARE
[Fox et al. 1998] Fox, A., Gribble, S. D., Chawathe, Y., and Brewer, E. A. (1998). Adapting
to network and client variation using infrastructural proxies: Lessons and perspectives. IEEE
Personal Communications, pages 1019.
[Grimes 1997] Grimes, R. (1997). Professional DCOM Programming. Wrox Press. 592 pp.
[J2EE ] J2EE. The Java2 Platform, Enterprise Edition. Sun Microsystems.
http://java.sun.com/j2ee.
[Jul et al. 1988] Jul, E., Levy, H., Hutchinson, N., and Black, A. (1988). Fine-grained mobility in
the Emerald system. ACM Transactions on Computer Systems, 6(1):109133.
[Lea 1999] Lea, D. (1999). Concurrent Programming in Java. The Java Series. Addison-Wesley,
2nd edition. 412 pp.
[Lea et al. 1993] Lea, R., Jacquemot, C., and Pillevesse, E. (1993). COOL: System Support for
Distributed Object-oriented Programming. Communications of the ACM (special issue, Concurrent Object-Oriented Programming, B. Meyer, editor), 36(9):3747.
[Lendenmann 1996] Lendenmann, R. (1996). Understanding OSF DCE 1.1 for AIX and OS/2.
Prentice Hall. 312 pp.
[Levin et al. 1975] Levin, R., Cohen, E. S., Corwin, W. M., Pollack, F. J., and Wulf, W. A.
(1975). Policy/mechanism separation in hydra. In Proceedings of the Fifth ACM Symposium on
Operating Systems Principles, pages 132140.
[Liskov 1988] Liskov, B. (1988). Distributed programming in Argus. Communications of the ACM,
31(3):300312.
[Maes 1987] Maes, P. (1987). Concepts and Experiments in Computational Reflection. In Proceedings of the Conference on Object-Oriented Programming Systems, Languages, and Applications
(OOPSLA87), pages 147155, Orlando, Florida, USA.
[Middleware 1998] Middleware (1998). IFIP International Conference on Distributed Systems Platforms and Open Distributed Processing. September 15-18 1998, The Lake District, England.
[Mitchell et al. 1994] Mitchell, J. G., Gibbons, J., Hamilton, G., Kessler, P. B., Khalidi, Y. Y. A.,
Kougiouris, P., Madany, P., Nelson, M. N., Powell, M. L., and Radia, S. R. (1994). An overview
of the Spring system. In Proceedings of COMPCON, pages 122131.
[Monson-Haefel 2002] Monson-Haefel, R. (2002). Enterprise JavaBeans. OReilly & Associates,
Inc., 3rd edition. 550 pp.
[Mullender et al. 1990] Mullender, S. J., van Rossum, G., Tanenbaum, A. S., van Renesse, R.,
and van Staveren, H. (1990). Amoeba: A distributed operating system for the 1990s. IEEE
Computer, 23(5):4453.
[.NET ] .NET. Microsoft Corp. http://www.microsoft.com/net.
[ODMG ] ODMG. The Object Data Management Group. http://www.odmg.org.
[ODP 1995a] ODP (1995a). ITU-T & ISO/IEC, Recommendation X.902 & International Standard
10746-2: ODP Reference Model: Foundations.
http://archive.dstc.edu.au/AU/research news/odp/ref model/standards.html.
[ODP 1995b] ODP (1995b). ITU-T & ISO/IEC, Recommendation X.903 & International Standard
10746-3: ODP Reference Model: Architecture.
http://archive.dstc.edu.au/AU/research news/odp/ref model/standards.html.
[OMG ] OMG. The Object Management Group. http://www.omg.org.
REFERENCES
1-21