{nano,blay,pinna,riveill}@essi.fr. Abstract: Components have brought with them the notion of services which let the programmer concentrate on the business ...
An abstract model for integrating and composing services in component platforms Olivier Nano, Mireille Blay-Fornarino Anne-Marie Dery, Michel Riveill {nano,blay,pinna,riveill}@essi.fr
Abstract: Components have brought with them the notion of services which let the programmer concentrate on the business behavior of his component while the non functional part (i.e. the services) is the responsibility of the platform provider. Thus services are not reusable through out the different platforms; the mechanism used to integrate them in the component is totally platform dependant. In this paper we propose a model to define the integration of services independently of the platforms and moreover to automate the composition of services.
I Introduction Adding and composing non-functional requirements[1] is the usual approach to services integration. Transactions, security, persistency, database support are regular services proposed by platform provider. Configuring distributed application consists in spreading services (or call to services) in the component classes and managing the behavior of components. To partially achieve services integration, component models such as CORBA Component Model (CCM) [2] and Enterprise Java Beans (EJB) [3] have emerged. One of the most important contribution in component models is to separate applications programming from deployment. Indeed, deployment descriptors allow component programmers to give information on which services to use. Then the deployer has to customize the deployment descriptor in order to adapt the component to the specificity of the runtime environment (transaction, persistency, security, database support, etc). According to deployment descriptors, generators (provided by platforms) generate interposition code. So, the integration of services by the deployer is basically done through parameter files. As the definition of services is integrated into the platform, their evolution and composition depend of platform providers. So, according to the platform, the deployer may be confronted to semantic differences of the service integration and implementation. The specification of standard tries to eliminate such issues. However, code generators deal only with services supported by the platform. So to use new services, for example replicated EJB, the deployer must either modify the generated code or specialize the generator which is making maintenance, evolution and services composition difficult. In such way, the work of a service provider is no more exactly the same as it was with the CORBA services. Now to offer a new service, he will have to plug its service on the different platform. He is then confronted at his turn to the composition of services. The resolution of this combination depends on the service implementation and integration provided by the plateform. We argue that service integration can be captured at meta-level in an independent way of the platform. Doing the same job for each service allows automatic composition of services and detection of inconsistency. In this paper we first show the process that we use to integrate services in components. Then are some examples of services integration (event, security,
1
asynchronous call). Next we describe the generation process and the projection mechanism. Finally comes a discussion on the meta-model and some of the underlying ideas. II Platform independent process Our model for services integration is based on the following actors (cf. figure 1): • The service developer provides a description of the parameters and operations needed to integrate the service in an application. This description is done in a declarative way. We call this specification of service integration: an integrator. For example, the service provider of a trace service will declare an integrator specifying that the trace file, the classes and the methods to trace are parameters of the service. The integration of this service consists to say that when parameter methods are called then the “write” message is sent to the parameter file. • The programmer that wants to use services in his application writes a deployment file where he specifies the services that he needs and parameters for each services. The parameters are: upon which classes to apply, which methods are concerned, flag specification… They depend on what requires the services description. • Then the generator composes all the services required by the application with a process that we call the merging. And finally after the merging, the appropriate code is generated according to the targeted platform. write programmer
write
Services Generate the application code through the process of decoration, merging and projection.
Integrators
use deployer
write
Deployement file
generator application
user
write
application
Figure 1: Process for services integration and composition. An integrator is thus a description of operations to perform to integrate a service. This description lays on a meta-model. The meta-model is based on the MOF[6] and is general enough to accept integration of services in different platforms. To manipulate this meta-model we use a meta-object protocol that let us do the transformations induced by the integrator. Integrators are written in a language whose operators go with the meta-model and the MOP. An integrator is thus written independently of the targeted platform. The platform dependant part is done during the projection mechanism which is the last step of the process. So the declaration of service integration and the merging of services are platform independent.
2
III Some integrators The figure 2 describes an integrator for the integration of an event active publisher service. It takes two parameters, a class and a list of methods that will trigger an event when executed. 1.
ChannelService(Entity e, Collection methods){ e.required += com.sun.Channel, com.sun.Event
2.
e.variables += Private Channel l
3.
c in e.getAllConstructors() do e.getConstructor(c) :- _call ;l = new Channel().
4.
m in methods do e.getMethod(m) :- _call ; l.push(new Event(_call.getName()))
5. e.methods += Public Channel getChannel(){ return l} Figure 2: Integrator for an event service. The integrator expresses that (1) both classes Channel and Event have to be known by the component. Then (2) a variable l of type Channel is added to the component, (3) the constructors of the component are extended to integrate the initialization of the channel. (4) Each method that where passed through the parameter file will terminate by pushing a new event in the associated channel. Finally (5) a method to acquire the channel from outside is added to the set of the component’s methods. The user could use this service simply declaring which class and methods of this class are concerned by this service. The syntax for the deployment file is not discussed in this paper. As the standard for EJB and CCM, we use a XML approach. Integrators (and thus the MOP) are based on two kinds of operators. The first kind is operators based on set (line 2 and 5). They add and remove elements in sets. The second kind is operations on behavior. Operations on behavior are based on the rewriting operator “:-“ which means that when we receive or emit a call, described by the left part of the operator (using “.” for reception and “>” for emission), we execute the right part of the operator. The right part is also constituted of different operators: • “;” is the sequential operator, left is executed and then right. • “//” is the parallel operator, there is no order between left and right execution. • “if cond then stat1 [else stat2]” and “try stat1 catch except” which have same semantics as usual. • “_call” expresses a call to the original method. In an integrator, new properties can be defined. Using the keywords Private or Public we specify if a property is private to the implementation or has to be published in the contract. In our example, the variable channel is private although the method to retrieve the channel is public.
3
When we introduce a new method we need to handle code. For this purpose we use a code specification. The code specification is parsed to generate the adequate code. At present time, the declaration language is simple. It integrates operators such as new, assignments, message sending and so one. And only projection in Java and Smalltalk has been studied. At Term, we think to use ASL. The second integrator in figure 3 shows how to integrate a security service. In this example, we have chosen to leave one entity, the security manager, decides if a call is authorized or not. So when initialising the class to control (according to the infrastructure, it can occur at deployment time or at load time) the security manager is set up with the file describing the security policies to apply to the instances of this class. SecurityService(Entity e, Collection methods, Filename file){ e.required : org.jonas.SecurityManager m in methods do e.getMethod(m) :if SecurityManager.check(_call.getName()) then _call else throw RemoteException(“Check Security”) e.init() :- SecurityManager.manageSecurity(file) // _call } Figure 3: Integrator for a security service. The user uses this service giving information about the class to control, the method list and a file describing the way to apply security. The following example shows that service integration can specify that a control has to occur at message emission and not at message reception. It shows how we can make a call asynchronous handling a future[7]. AsynchronousService(Entity e, Collection methods){ e.required += fr.essi.rainbow.Futur m in methods do res : e>getMethod(m) :- t = Futur.CreateType(res.type); res = T.new() ; return res; x = _call ; res.set(x) } IV Integration steps The implementation is based on the construction and transformation of abstract syntax trees built upon the component. Let’s describe the different steps to accomplish the services integration and composition.
4
1. Abstraction of the different platforms: a common meta-model Using adequate parser according to the application language and the targeted platform an abstract syntax tree platform independent is built for each entity to control. This tree is built according to a meta-model corresponding to an instantiation of the MOF. Let’s look at Java RMI and EJB approaches as examples because they both correspond to a general way of services integration. In the both cases, we propose to manage service integration respecting their architectures. Let’s describe their data models to see theirs differences. The set of data that has to be given by the programmer to integrate a service is: • For RMI: a Remote interface, an implementation Class, a part of code which can be qualified as server and eventually a remote interface corresponding to the Factory. • For EJB: a Remote interface, an implementation Bean, and a Home interface.
2. Decoration process Then according to the deployment descriptors and the involved integrators the trees are decorated[5]. At this step errors can occur if some information in the deployment descriptors such as method name doesn’t correspond to data. The decoration occurring on a set of properties such as “all the methods” or “all the constructors” are attached at the level of the set property (methods, constructors) and are not deployed. The other one, such as the one modifying the behaviour of methods are directly attached to these methods as “behaviour control”.
3. Merging process The merging process presents different steps in order to manage operators on set and operators on entities. The decorations are merged from top to bottom. The set of decorations on a same node are managed simultaneously. • Decorations based on set operators such as adding variables or methods, modifying signatures are first operated respecting the following rules. We can’t add and retract simultaneously the same properties. This step of process can then detect some inconsistencies such as a method added by a service and retracted in another one • Decorations expressing that an operation has to be realized on a set of properties are then unfold to be translated as decoration on each corresponding property. So each constructor in the example of the channel service integrator will now be decorated with a behaviour control asking to create a channel. • Finally behaviour controls are merged and translated in a sub-tree. For example the merging of the security and event on a method “addRdv” would result in: addRDV() :if SecurityManager.check(_call.getName()) then l.push(Event.new(_call.getName()) else throw RemoteException(“Check Security”) The merging is based on the semantic of operators. The operation of merging is defined in a formal way allowing the proof commutative and associative properties. So, the order in which integrations are merged doesn’t modify semantically the result
5
At this step of the merging process, errors due to incompatibility between services can be detected. For example, two services integration triggering different exceptions in a same context can’t be merged.
4. Projection Finally comes the platform dependant mechanism namely the projection. According to the decorated tree and the targeted platform the corresponding code is generated. As for the entry data set we have to look at what is produced by the process of services integration. This output is the modified entry data code and the generated code. According to the platform the output code is different. For EJB approach we have chosen to conform to the code generated by Jonas. So an interposition class is generated according to the containers and to the descript file and an implementation of the home is generated too. For RMI, we propose to modify directly the implementation class like a programmer who wants to integrate services would do. So the output set is as follow: • a Contract for Client (It can be modified for the integration of the services adding or retracting methods, modifying the method signature, …) • The implementation of the contract (This entity manages the services). • The implementation of the business component (It manages the intrinsic knowledge of the component. This entity has so to be modified for integration of some services which need access to the internal state of a component such as persistency service). • A home Contract for Clients (it is optional. It depends on the entry set). • The implementation of the home contract. • A Server code • The implementation of the “proxy” on the client side (according to the implementation, this entity can be merged with the stub). In the case of EJB the projection mechanism does a graph traversal to determine if the transformations are relative to the implementation code or to the interposition object. For example each new method accessing variables from the implementation code have to be inserted in the implementation code while other methods are added in the interposition object. Another example is in the asynchronous call when we use the “>” operator. In the RMI projection the code to catch the call will be placed in the proxy. VI Conclusion To allow a service provider to integrate his service in different platform we have introduce a meta-model and a MOP that is platform independent. The service provider has to describe the integration of his service. Then we propose a process resulting in the merging of the different services that a user wants to integrate in his components, and a projection mechanism that is platform dependant and generates the adequate code for the targeted platform. We argue that the integration of service has to be expressed at level of interacting classes, having a partial point of views of all the potential service integration. Tools have to check the consistency of all the services integration, signaling inconsistency and warning deployer about drawbacks. Analyzing the interaction graph of all the entities involved in an application is not discussed in this paper. It’s a perspective of this work ; indeed the abstraction carried by 6
integrators, and the algebra should allow to analyze interaction graph detecting cycle, indetermination propagation, partial order in triggering exceptions, multiple call of the same message and so on. Our model and the operations are still in a growing state. We try to give a description of different kind of services to see where the merging can be difficult. We are also studying Corba Component Model to offer a projection to it. Until now, we have chosen as targeted platforms CCM, EJB and RMI, we don’t know if other future platform will fit in our model. We are studying the Fractal model at this time and it seems that we will be able to write a projection to it. Bibliography [1] G. Kiczales, J. Lamping, A. Menhdhekar, C. Maeda, C. Lopes, JM.Loingtier, and J. Irwin. Aspectoriented programming. In ECOOP ’97,volume 1241, pages 220–242. 1997. [2] OMG CORBA Component Model (CCM) Technical White Paper http://www.omg.org/ [3] Sun Microsystem Entreprise Java Bean Specification http://java.sun.com/products/ejb/ [4] Laurent Berger Phd Thesis Rainbow 2001, University of Nice Sophia Antipolis [5] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns : Elements of Reusable Object-Oriented Software. Addison Wesley, Massachusetts, 1994. [6] OMG Meta-Object Facility Specification 1.3 http://www.omg.org/ [7] D. Caromel Towards a Method of Object-Oriented Concurrent Programming, pp. 90-102, in CACM, Communications of the ACM, Volume 36, Number 9, September 1993.
7