An application server to support online evolution
ABSTRACT Most online evolution of an application depends on its runtime environment. This paper addresses how to support online evolution by an application server, which is considered as a third kind of system software, besides OS and DBMS. From the view of requirements, evolutions of software can be divided into four categories: evolutions that do not alter requirements, evolutions that alter functional requirements, evolutions that alter local constraint requirements, and evolutions that alter global constraint requirements. All changes at the requirement level should be mapped to changes at the implementation level. In our approach implementation level entities, such as components and interceptors are responsible for online evolution. Evolutions in implementation level include adding, removing, updating, and reconfiguring the entities. One of the keys to our approach is to carefully distinguish states of components and interceptors, that is, whether they are in a ready, active, executing or evolving state. A well-designed architecture and feasible mechanisms for runtime instance loading are also keys to the solution. Based on this approach, an application server prototype, named PKUAS, has been implemented and is introduced in our paper.
-
Citations (0)
-
Cited In (0)
Page 1
An Application Server To Support Online Evolution
Qianxiang Wang, Feng Chen, Hong Mei, Fuqing Yang
Department of Computer Science and Technology,
Peking University
100871 P.R.China.
{wqx,cf}@cs.pku.edu.cn meih@pku.edu.cn
Abstract
Most online evolution of application depends on its
runtime environment. This paper addresses how to support
online evolution by application server, which is considered
as third kind of system software, besides OS and DBMD.
From view of requirements, evolutions of software can be
divided into four categories: evolutions that do not alter
requirements, evolutions that alter functional requirements,
evolutions that alter local constraint requirements, and
evolutions that alter global constraint requirements. All
changes at the requirement level should be mapped to
changes at the implementation level. In our approach,
implementation level entities, such as components and
interceptors are responsible for online evolution.
Evolutions in implementation level include adding,
removing, updating, and reconfiguring the entities. One of
the keys to our approach is to carefully distinguish states of
components and interceptors, that is, whether they are in a
ready, active, executing or evolving state. A well-designed
architecture and feasible mechanisms for runtime instance
loading are also keys to the solution. Based on this
approach, an application server prototype, named PKUAS,
has been implemented and is introduced in our paper.
Key words: application server, online evolution,
component, container, interceptor, common service
1. Introduction
Background
Online evolution means changing software’s
implementation at run-time to add its functionality,
improve its performance, or correct its faults. Online
evolution was first focused in safety-critical areas such as
avionics, telecommunication [1]. The main goal of online
evolution in these areas is to keep systems running when
some problem occurs. Today, online evolution gains much
more goals. As software
“product-centred” to “service-centred”, more and more
commercial software are expected to have the feature of
is changing from
online evolution. This requirement may be due to the
following reasons: First, most services need to keep
working 24 hours per day and 7 days per week. Second,
both consumers’ demand and new technologies change
very quickly. As a result, most newly developed software
should have the ability of online evolution, so as to: erase
bugs, add new services, enhance reliability, and enhance
security, etc.
Traditional online software evolution was used to
enhance system’s reliability, which can be implemented
by way of redundancy, degradation, etc [1]. Today,
flexibility, extensibility and ease of replacement are
becoming the most important factors that motivate online
evolution.
Because software is usually divided into system
software and application software, so software evolution
can occur at the system level and application level. In this
paper, we consider only the evolution of application
software, which needs support of system software.
Problem
Some design patterns give excellent solutions to
online reconfiguration [22]. By implementing replaceable
components at developing time, flexible software can be
customized according to user’s preference. But design
patterns focus little on other features, such as extensibility,
online updating. Besides the common problems that all
software evolution must face such as architecture change
[2] and feature interaction [9][21], online evolution
confronts mainly with the following two problems:
First, weak management of evolving blocks prevents
practical online evolution. Although modules and classes
are good construction blocks for applications during
development, they are poorly maintained at runtime.
Processes, generated from those blocks, are the units well
supported by traditional runtime environment such as the
OS, but are still hard to modify. DLLs can load module
dynamically, but it gives little support for online evolution.
The emergence of some component models, such as EJB
[13] and CCM [24], provides the ability to keep the
components isolated at runtime by giving each component
a standalone management entity, which is usually called
Proceedings of the International Conference on Software Maintenance (ICSM’02)
0-7695-1819-2/02 $17.00 © 2002 IEEE
Page 2
component container. With the help of container,
component framework (such as application server) makes it
possible to alter components, while keeps the application
running.
Second, crossing cutting features prevents effective
online evolution. Functional requirement has been well
supported by structured and object-oriented development
methods. But neither supports constraint requirement well.
Implementation of constraint requirement usually involves
multiple modules or classes. This phenomenon is called
crossing cutting problem [8]. When evolving constraint, the
code to be changed is often scattered throughout the whole
application. This situation not only makes the evolution
laborious and time-consuming, but also will result in the
uncertainty of the evolution. So, while some research
focuses on functional requirement evolution [2], other
researchers think the evolution of constraint is much more
popular and important [6][7].
Application Server based solution
Application Server(AS) is one kind of system software
that emerged recently with the developing of computer
network. Application Server gives strong support to
component-based software development (CBSD), which is
well focused recently. With supporting of application server,
components are not only the units of development, but also
the entities in runtime. Thus greatly facilitates the runtime
evolution of component-based applications.
Based on application server, this paper presents a
solution to online evolution of applications. The
architecture of application server that supports the dynamic
component updating, and the states of components are
clearly defined according to the requirement of online
evolution. In order to support the evolution of constraint,
the interceptor pattern is introduced. Interceptor is a
successful design pattern that is widely used today [11][12].
Interceptor is used to filter and process messages that are
transmitted between a client and a server.
This paper is organized as follows. Section 2
introduces some key concepts about an application server,
including application, component, container. Mapping
changes from requirements into implementations is also
introduced. Section 3 describes the challenge and solution
to component evolution, component implementation,
component instance, interceptor, and context. Section 4
describes the solution to interceptor evolution. Section 5
introduces PKUAS, an application server prototype that
supports our approach for online evolution.
2. Structure of Application Server
Nearly all of application servers support component
technology and provide common services to applications.
As a result, developers are able to focus on system’s
business logic, and implementation of constraint is
separated from component’s implementation codes. Thus
we can build well-structured applications.
One typical structure of an application server is
illustrated in figure 1. In this diagram, application server
involves concepts of application, component, common
services, etc.
Operating System, DBMS
Application server
Common
Services
Component
Container
Common
Services
….
Component
Container
System
Software
Application
Software
Application
Common
Services
Figure 1. Structure of application server
Application
One application usually composes of multiple modules,
such as procedures, classes, or components. Modules
interact with each other, by way of method invocation or
message interchanging. Application software runs over
system software such as an Operating System, DBMS.
Component
A component is an independent module that
undertakes some specific functions in software systems.
Although most people focus on component implementation,
component specification is another indispensable part of a
component [14]. Component implementation is the code
that implements the functions of a component. component
specification describes how to assemble, use, and manage
the component. The application that runs on an application
server can contain multiple components. The relationship
between components and applications is similar with the
relationship between employees and enterprise.
Container
Component container is the main mechanism in an
application server that supports component technology.
Container gives component
environment, which makes development and management
of components more feasible and convenient. As one
middle layer located between component and component’s
independent running
Proceedings of the International Conference on Software Maintenance (ICSM’02)
0-7695-1819-2/02 $17.00 © 2002 IEEE
Page 3
client, container is responsible for the connection between
component and client, life cycle management of
components, coordination of transaction for components,
maintenance of component persistency, and identification
authentication of clients, etc., while client is unaware of the
existence of containers. Some of above functions are
implemented with support of common services, and thus
developers can concentrate their attention to the main
functions of applications.
Common service
The concept of service becomes mature with the
development of the client-server computing model.
Belonging to the system level, common services are used to
support common features of different applications.
Common services undertake most of application server’s
functions. For example, naming service is responsible for
locating the server, transaction service is responsible for
assuring system’s consistence, and security service is
responsible for authenticating the client and controlling the
access to server, etc.
At application level, applications also provide services
that are implemented by components. An application
service includes service implementation and service
description. The implementation of components determines
the implementation of service. And description of service
includes not only the description of components, but also
features that emerged when components are combined with
the running environment,
communication protocol, response time, and system’s
throughput, etc.
including security,
3 Solution to online evolution
Online evolution is one process that involves software
development process and software maintenance process.
The continual change of requirement is the motivation, the
adjusting of implementation is the result, and the tracing
between them is the key.
3.1 Evolution at requirement level
Software evolutions contribute mainly to evolutions
of requirement. Requirement is still one challenging
problem in software engineering research. This paper
centers only on those requirements that are related with
software, requirements that rely mainly on hardware are
ignored. Those requirements include: response time,
system distribution, etc.
Oreizy distinguished two types of software changes
[2]: (1) changes of system requirements, and (2) changes
of system implementation that do not alter requirements.
Zave cataloged software requirements into “functions of”
and “constraints on” software systems [3], in other words,
functional requirements and constraint requirements. We
further catalog constraint requirements into local
constraint and global constraint.
For local constraints, we mean those that can be
mapped into one or one group of function requirements,
such as reliability, access control, and auditing. For global
constraints, we mean those features that can only be
incarnated by the whole system, such as architecture of
system, business process. Such requirements can hardly be
mapped to independent functions. Global constraints
involve too many factors, so they are hard to put evolution
in practice on the fly. We do not take them into
consideration also.
In this paper, we proposed four types of software
evolution, which can be illustrated by the example of a
web-based pet store system [4]. When using this web-based
application, users can browse pets, select and put selected
pets into virtual shopping cart, and create orders for
selected pets, etc. For this application, we can divide
requirement changes into four classes:
(1) Changes that do not alter requirements, such as
erasing some bugs in shopping cart, or improving algorithm
of searching pets.
(2) Changes that alter functional requirements such as
when adding electronic payment method to pay by credit
cards online.
(3) Changes that alter local constraints, such as
improving security of order to guarantee that only
authenticated users can create orders and only super user
can browse all orders that have been created. Some special
requirements, such as logging, auditing, exception handling,
are considered as local constraint also. Those requirements
cannot exist alone, and can only be attached to other
functional requirements.
(4) Changes that alter global constraints, such as when
reducing order process time and improving system’s
throughput.
3.2 Evolution at the implementation level
To support online evolution, we proposed a special
architecture of the component container, which has been
implemented by PKUAS. The container in PKUAS consists
of component meta-data, component implementations,
component instances, and interceptors, etc. Figure 2 shows
container’s architecture.
Proceedings of the International Conference on Software Maintenance (ICSM’02)
0-7695-1819-2/02 $17.00 © 2002 IEEE
Page 4
Component Container
Component Implementation
Component Instances Request
Interceptor queue
Instancing
Response
Common
Service
Component
Meta-Data
Figure 2. Structure of component container
Component meta-data
Component meta-data (CMD) records detailed
knowledge of component in formal way. Using component
meta-data, component can be utilized and managed
expediently. The content of component meta-data may
include following information of a component: name, basic
type, type interface, instance interface, implementation,
running state, attribute of transaction, attribute of security,
environment entries, etc. Figure 3 illustrates the component
meta-data used in PKUAS. Component meta-data provides
abundant information for reflection, which makes
components much more manageable [15]. It provides the
basis for online evolution.
public class CMD{
protected String m_ejbName;
protected byte m_beanType;
protected Class m_typeInterface;
protected Class m_instanceInterface;
protected Class m_beanClass;
protected HashMap m_beanMapping;
protected HashMap m_methodMappin;
protected HashMap m_methodPermissions;
protected HashMap m_transactionAttributes;
protected HashMap m_ejbRefMapping;
protected HashMap m_environmentMapping;
protected HashMap m_resourceMapping;
……
}
Figure 3. CMD in PKUAS
Component implementation
Component implementation refers to the code that
implement component’s functions. In object-oriented
systems, a component consists of multiple closely related
classes. Component implementation can be developed
independent of applications, and are usually stored in files,
so as to be easily delivered and assembled. When
components are deployed as parts of applications, they are
loaded into component containers, as figure 2 shows.
Component instance
Component instance is a concept that exists only
during runtime, similar to the concept of object in
object-oriented system. And component implementation is
a concept that exists in both development and runtime,
similar to the concept of the class in object-oriented system.
Container can create multiple component instances from
one implementation. Instances may have their own
attributes, such as identification, data values and running
states.
Interceptor
As a widely adopted design pattern, interceptor is used
to intercept and process messages between a client and a
server. Multiple interceptors can be grouped as one
interceptor queue, so as to process messages one by one,
according to pre-configured application policy. Interceptor
is firstly used by OMG to implement security service such
as authenticating a client [11]. But developers soon find
that it can be used for many other implementations of
constraint requirements.
Interceptor is used in PKUAS to pre-process client
invocation to component, so as to implement constraints of
the applications, with help of common services such as
transaction and security and By reconfiguring the
interceptors, the constraints can be implemented and
evolved effectively.
Interceptors can be regarded as entities at the
implementation level that are mapped from constraint
requirement. In fact, this paper divides constraint
requirements (see section 3.1) from the viewpoint of
interceptor: if one constraint can be implemented by some
interceptor, it can be considered as one local constraint.
Otherwise, it should be considered as a global constraint. It
is feasible to organize requirements based on this rule,
because requirements are usually induced from users by
developers. Moreover, this kind of classification benefits
the application evolution, especially for online evolution.
Figure 4 shows the common basic interface of interceptors
used in PKUAS.
public interface Interceptor{
public void init(Container container);
public void beforeInvoke(Object objectId, cspiMsg mi,Method m);
public void afterInvoke(Object objectId, cspiMsg mi,Method m);
public void handleException(Object objectId, cspiMsg mi,
Method m,Exception ex);
}
Figure 4. Basic interface of interceptor
Proceedings of the International Conference on Software Maintenance (ICSM’02)
0-7695-1819-2/02 $17.00 © 2002 IEEE
Page 5
When deployers deploy one application, different
containers are constructed, according to the component that
buildup that application. Different kinds of interceptors are
also built, according to the application’s assembling
information, especially information that related with
constraint requirements. These interceptors are organized
into interceptor queues shown in figure 2 to process
messages to components according to their own policies.
Context
Context is a concept closely related with the
interceptor, and is very important for dynamic updating
[16]. When a client calls one method, the called method can
be deemed as the extension of the caller method. In order to
perform clients command correctly, the called method
needs get information from the caller method, which is
provided as the some special parameters in the traditional
programming model such as Object Oriented model. But in
a distributed environment, more information is needed. The
information may include caller’s identification, caller’s
requirement for consistency, etc. This information is stored
in the context that is an additional part of the message sent
from the client.
In the interceptor pattern, context also brings the
required information for interceptors. When processing
messages, the interceptor must extracts the interested
information from context, such as caller’s identification,
and then sends this information to corresponding common
service, such as security service, along with other
information got from component meta-data. Common
service executes some operation according to interceptor ‘s
instruction, and return result to interceptors. Interceptor
gets the result, reconstruct the messages and pass it to the
successors. Figure 5 shows an implementation of the
invocation of interceptors to illustrate this process. After
the target entity processes the client request, the response
will be processed through the interceptors queue in a
reverse order, which is also shown in Figure 5.
public abstract class Container implements ContainerMBean{
……
invoked(Object objectId, cspiMsg mi)throws Exception{
Iterator interceptors=m_CMD.getInterceptors();
while (interceptors.hasNext()){
interceptorMetaData=(InterceptorMetaData)interceptors.next();
interceptor=interceptorMetaData.m_interceptor;
interceptor.beforeInvoke(objectId,mi,targetMethod);
invokedInterceptors.add(0,interceptorMetaData);
}
invoke(objectId,mi,targetMethod,isRemote);
interceptors=invokedInterceptors.iterator();
….
while (interceptors.hasNext()){
interceptorMetaData=(InterceptorMetaData)interceptors.next();
Interceptor=interceptorMetaData.m_interceptor;
interceptors.remove();
interceptor.afterInvoke(objectId,mi,targetMethod);
}
……
}
Figure 5. Two phases process of interceptor queue
3.3 From requirement to implementation
From the above discussion, we can see that for
applications that run over application server, functional
requirements can be mapped into components, and local
constraints can be mapped into interceptors (including
corresponding common services). Thus, evolutions at the
requirement level can be mapped into implementation level
as follows:
(1) Evolutions that do not alter requirements. Such
evolutions do not alter the system’s functions and
constraints, so components’ interfaces and interceptors’
policies need not change. We can erase bugs and improve
algorithm by updating component implementations.
(2) Evolutions that alter function requirements. Such
evolutions lead to adding and removing components, or
altering component’s interface to change component’s
functions. Because we can change the component’s
interface by deleting old components and then adding new
components [2], this paper deals with adding and removing
components only.
(3) Evolutions that alter local constraints. Such
evolutions do not change components, but common
services and interceptors. The changes may include adding
and removing interceptor, or altering interceptor’s policy.
Some special evolution of local constraints may need
changes to common services. This belongs to system
software evolution, so this paper does not discuss it.
(4) Evolutions that alter global constraints. Some
evolution of global constraints can be implemented by
altering configuration of applications or common services.
But they are usually beyond the scope of online evolution.
Figure 6 illustrates the mapping rules for changes in
requirement.
Proceedings of the International Conference on Software Maintenance (ICSM’02)
0-7695-1819-2/02 $17.00 © 2002 IEEE