Transcription

1 Modularizing Communication Middleware Concerns Using Aspects Cristiano Amaral Maffort and Marco Tulio de PUC Minas, Institute of Informatics Anel Rodoviï rio Km 23,5 - Rua Walter Ianni, Belo Horizonte - MG - Brazil Phone: +55 (31) Abstract Software engineers often rely on communication middleware platforms to design and implement distributed systems. However, middleware functionality is usually invasive, pervasive and tangled with business-specific concerns. In this paper, we describe an aspect-oriented distributed programming system that encapsulates middleware services provided by Java RMI and Java IDL. The proposed system, called DAJ, handles the basic service provided by such object-oriented middleware platforms, i.e., synchronous remote calls using call by-serialization and call by-remote-reference semantics. The paper documents our experience in using DAJ to modularize middleware concerns from three legacy distributed systems. Keywords: aspects; separation of concerns; distribution; middleware. 1. INTRODUCTION During the last two decades software engineers have often relied on communication middleware platforms to design and implement distributed systems. Middleware platforms, such as CORBA [34], Java RMI [36], and Web Services [1], encapsulate several details inherent to distributed programming, including communication protocols, data marshalling and unmarshalling, heterogeneity, service lookup, synchronization, and failure handling. Although they shield developers from networking details, middleware systems also require developers to follow their specific code conventions and protocols. For example, programmers must deal with middleware specific classes, interfaces, and remote exceptions. Moreover, usually middleware code impacts several classes of distributed systems and forces such classes to handle more than one concern simultaneously. In other words, middleware code does not sit only between the network and the distributed application, but it is also spreaded and tangled in the latter [12, 29, 32]. The consequence is that distributed object-based systems do not present expected levels of separation of concerns, making such systems more difficult to implement, maintain and evolve. This paper is a revised and extended version of a previous conference paper describing DAJ (Distribution Aspects in Java), a system designed to insulate middleware from business related code [23]. In order to accomplish its goal, DAJ relies on the synergistic combination of three technologies: aspects [16, 15], domain-specific languages [33, 3], and generative programming [8]. In the proposed system, aspects are used to encapsulate crosscutting middleware code, domain-specific languages are used to elevate the abstraction level when defining distributed software architectures, and generative programming is used to synthesize aspects and other components. Particularly, DAJ includes an aspect-oriented framework that encapsulates crosscutting code required by communication middleware. Moreover, DAJ includes a generative tool that specializes abstract aspects from this framework in order to add distribution to a given application. The current version of the system generates aspects for two native JDK middleware platforms: Java RMI [36] and Java IDL [14]. Java RMI is a middleware often used in the implementation of Java-to-Java distributed applications. Java IDL adds CORBA support to the Java plat-

2 Figure 1. Developing distributed applications using DAJ form, providing interoperability with distributed systems written in other programming languages. In DAJ-based applications, business classes do not need to follow particular programming conventions. More specifically, they do not need to extend middleware pre-defined classes, implement remote interfaces or accessor and mutator methods; they also do not need to handle remote exceptions. Instead, a domain-specific language is used to declare the role that plain Java classes and objects play in a particular distributed system configuration. From specifications in such language, called distribution descriptors, DAJ generates classes and aspects that modularize the otherwise crosscutting middleware functionality. The aspects are generated in AspectJ [15, 19]. Figure 1 summarizes the steps proposed by the system to support the implementation of distributed object-based applications. DAJ introduces at least two contributions to the conventional use of middleware platforms. First, and more important, developers can focus on the functional concerns of the system they are building since DAJ automatically generates aspects that modularize crosscutting code required by middleware platforms. Second, DAJ users do not need to master details and idiosyncrasies inherent to middleware APIs. The remaining of this paper is organized as follows. Section 2 presents a motivating example, used in the rest of the paper to describe the DAJ system. Section 3 describes the programming interface that must be followed by DAJ users. Section 4 presents the software architecture and the implementation of the DAJ system, focusing on the abstract aspects defined by the system and the concrete aspects generated from the information defined in distribution descriptors. Section 5 describes our experience in using DAJ to modularize middleware concerns from three medium-sized distributed systems. This experimental study constitutes the main contribution of this work regarding our first paper about DAJ [23]. Section 6 presents a discussion about the lessons learned in DAJ development. Section 7 describes related work and Section 8 concludes the paper. 2. STOCKWATCHER SYSTEM In order to describe the DAJ system, we will use in the remaining of this paper a distributed application that provides information about stock prices. The StockWatcher system consists of a remote object that stores the current price of a set of stocks. Clients access this object to update the price of a given stock and to subscribe for updates in the price of stocks. In the latter case, the server object uses a callback to notify the client. Although simple, StockWatcher uses the core abstractions provided by object-oriented middleware systems. It relies on remote calls using call by-serialization and call by-remote-reference semantics when objects are used as parameters. A copy of an object is passed when call byserialization semantics is specified (also known as objectby-value semantics in CORBA). In this case, there is no relation between the client-side object and the copy that the server uses during the execution of the remote method. On the other hand, when using call by-remote-reference semantics, the remote reference associated with the object is passed as argument of the remote call. During the execution of the remote method, this reference can be used to callback the object in the client address space. StockWatcher admits several deployment configurations. For example, a deployment scenario may include a single RMI server and a number of Java clients. In another scenario, CORBA may be used in order to support interoperation with clients implemented in other programming languages. In a third scenario, we can have two servers, one implemented in CORBA and another implemented in Java RMI. In this case, each server handles a subset of the traded stocks. 82

3 1: <server id="stockmarketa"> 2: <interface>stockwatcher.stockmarket</interface> 3: <class>stockwatcher.stockmarketimpl</class> 4: <protocol>javaidl</protocol> 5: <nameserver>skank.pucminas.br</nameserver> 6: </server> 7: <server id="stockmarketb"> 8: <interface>stockwatcher.stockmarket</interface> 9: <class>stockwatcher.stockmarketimpl</class> 10: <protocol>javarmi</protocol> 11: <nameserver>patofu.pucminas.br:1530</nameserver> 12: </server> 13: <remote> 14: <interface>stockwatcher.stocklistener</interface> 15: <class>stockwatcher.stocklistenerimpl</class> 16: </remote> 17: <serializable> 18: <class>stockwatcher.stockinfo</class> 19: </serializable> Figure 2. A possible distribution descriptor for the motivating example We describe next the main interfaces and classes of the system. Interfaces: The server that stores stock prices implements the following interface: interface StockMarket { void update(stockinfo info); void subscribe(string stock,stocklistener obj); void unsubscribe(string stock,stocklistener obj); StockInfo getstock(string stock) throws StockNotFoundException; Clients publish changes in the price of stocks by calling the update method. The class StockInfo is used to store stock prices in a given date and time: class StockInfo { private String stock; private double value; private String date_time; Clients register their interest in notifications of price changes by calling the method subscribe, passing the name of the stock they are interested in and a reference to a remote object used by the server to call back the client. The unsubscribe method is used to cancel the registration performed by subscribe. In both methods, the client object that the server calls back must implement the interface StockListener: interface StockListener { void update(string stock, double value); The StockMarket interface also provides the getstock method used to retrieve the current price of the stock passed as parameter. If the server does handle the requested stock, a remote exception of type StockNotFoundException is raised. Implementation: In the implementation of the Stock- Watcher system, the class StockMarketImpl implements the interface StockMarket and the class StockListenerImpl implements the interface StockListener. Different from standard objectoriented implementations using Java RMI and Java IDL, the described interfaces and classes do not have any tangled code related to distribution. 3. PROGRAMMING INTERFACE This section describes the DAJ programming interface. More specifically, we describe the conventions that developers must follow in order to define distribution descriptors and to program client and server modules DISTRIBUTION DESCRIPTORS DAJ hides from business classes programming conventions demanded by the underlying middleware platform. The ultimate goal is to allow developers to focus on the functional requirements of the applications they are building, delegating to the framework the implementation of the aspects related to distribution concerns. However, developers must define the distributed configuration of their systems using an XML file called distribution descriptor. Basically, distribution descriptors contain information about remote objects of a given distributed application. A remote object is one whose methods can be accessed from another address space, possibly from a different host. In DAJ, remote objects that are registered in a naming server are called server objects (or just servers). For such objects, DAJ users must define their names, classes and 83

4 interfaces, the middleware used to access them, and the host and port number of the naming server where they must be registered 1. Such information is specified using a server tag in the distribution descriptor. DAJ users must also define the types that are passed in remote calls using call by-serialization and call by-remote-reference. In the case of types passed by-remote-reference (node remote), developers must inform their interfaces and classes. In the case of types passed by-serialization (node serializable), developers must inform their classes. Example: Figure 2 presents a possible distribution descriptor for the StockWatcher system. This descriptor assumes an architecture including two servers: the first uses Java IDL for communication and is registered under the name StockMarketA (lines 1 to 6); the second server uses Java RMI and is registered under the name StockMarketB (lines 7 to 12). Moreover, the descriptor prescribes that in remote calls objects of type StockListener are passed by-remote-reference (lines 13 to 16) and objects of type StockInfo are passed byserialization (lines 17 to 19) CLIENTS In distributed object-based systems, clients locate remote objects and then perform remote calls using the same syntax of local calls. Clients must use the getref method from the DAJ API to obtain references to server objects configured in a given distribution descriptor. Using such references, clients perform remote calls in a transparent way, i.e., without having any knowledge about the underlying middleware platform. Example: We show next a fragment of a client module of the StockWatcher system: 1: StockMarket s1,s2; 2: s1= (StockMarket) 3: ServiceLocator.getRef("StockMarketA"); 4: s2= (StockMarket) 5: ServiceLocator.getRef("StockMarketB"); 6:... 7: StockInfo s; 8: s=new StockInfo("sunw",124.6,"10/04/2007"); 9: s1.update(s); 10:... 11: StockListener listener= new StockListenerImpl(); 12: s1.subscribe("goog", listener); 13: s2.subscribe("yhoo", listener); In lines 1 to 5, the client uses the getref method to obtain references to the servers identified by the names StockMarketA and StockMarketB in the distribution descriptor presented in Figure 2. Next, the client 1 A naming service allows clients to locate objects based on their names. The current implementation of DAJ is compatible with the standard naming servers provided by Java RMI and Java IDL, respectively called rmiregistry and tnameserv. calls the update method of the first server passing byserialization an object of type StockInfo (lines 7 to 9). Finally, the client subscribes to changes in the price of two stocks (lines 11 to 13). It is worth to mention that in both calls the client informs the same object of type StockListener to receive callbacks from the servers. As prescribed by the associated distribution descriptor, the first server will use Java IDL to call back this object and the second server will use Java RMI SERVERS DAJ generates for each server defined in a distribution descriptor an activation class, i.e., a class with a main method used to create, activate and register the remote object. This class has the same name of the server with the suffix _Server. 4. ARCHITECTURE This section presents the software architecture and the implementation of the DAJ system, focusing on the abstract aspects defined by the system and the concrete aspects generated from the information defined in distribution descriptors. We begin the section describing the creation of remote interfaces. Next, we describe aspects used to inject middleware related concerns in business classes, retrieve remote references and activate remote objects. Thus, this section assumes that the reader is familiar with AspectJ syntax and semantics, which includes basic knowledge of abstractions such as join points, pointcuts, advices, and inter-type declarations. Such abstractions are described in details in AspectJ introductory papers [15] or textbooks [19] REMOTE INTERFACES Interfaces that have middleware related concerns tangled in their code are called remote interfaces. From distribution descriptor data, DAJ automatically generates remote interfaces as required by Java RMI and Java IDL. Such interfaces have the same name of their associated business interfaces, but they are created in a different package to avoid name collision. Java RMI Remote Interfaces: Remote interfaces required by Java RMI are similar to their associated business interfaces, except that they must extend java.rmi.remote and their methods must throw java.rmi.remoteexception. DAJ generates code for remote interfaces since the static crosscutting features of AspectJ do not support adding a throws clause in the signature of methods. This problem was already been reported in other works [29, 32]. 84

5 interface StockMarket extends Remote { void update(stockinfo info) throws RemoteException; void subscribe(string stock, stockwatcher.rmi.stocklistener obj) throws RemoteException; void unsubscribe(string stock, stockwatcher.rmi.stocklistener obj) throws RemoteException; StockInfo getstock(string stock) throws StockNotFoundException, RemoteException; Figure 3. Java RMI interface for the motivating example Another difference between business and remote interfaces is related to call by-remote-reference. Suppose that a business interface method has a parameter of a type T declared as remote in the distribution descriptor. In the remote interface, we must change T to the type of its associated remote interface. The reason is that Java RMI transmits the stub of the argument when the formal parameter implements a Remote interface. Thus, the stub is not compatible for assignment with business types. Figure 3 presents the remote interface associated to the business interface StockMarket. The presented interface extends Remote. Moreover, its methods declare that they can throw RemoteException. Finally, the type of the parameter obj in the subscribe and unsubscribe methods was replaced by the associated remote interface type. Java IDL Remote Interfaces: As usual in CORBAbased distributed applications, remote interfaces must be specified in IDL a neutral language proposed by CORBA to define remote interfaces. Thus, DAJ generates an IDL specification for business types defined in the deployment descriptor of a given system. Moreover, DAJ relies on the idlj compiler that is part of the Java IDL platform to generate classes and interfaces required by CORBA implementations. In object-oriented Java IDL systems, the code of such classes is scattered and tangled in the business classes of the distributed system under design. Figure 4 shows the interface StockMarketOperations, generated by the idlj compiler and that must be implemented by a business class. In this interface, business types have also been replaced by their counterpart remote types, as proposed by DAJ for RMI interfaces REMOTE CLASSES Remote classes are those that result from the instrumentation of business classes with distribution concerns. DAJ makes a distinction between remote classes whose instances are registered in a naming service and those whose instances are not registered in such service. The former are always specified in a server tag of distribution descriptors. An example is the Stock- MarketImpl class. The latter are declared in remote tags and are used to create objects that are passed using call by-remote-reference in remote calls. An example is the class StockListenerImpl. The remaining of this subsection describes how these two type of remote classes are instrumented with distribution code required by Java IDL. The instrumentation required by Java RMI follows the same pattern, and thus is not be presented in this paper. Classes that can be located using a naming service: As any remote class, such classes must implement the remote interface generated by DAJ. Moreover, for each method in the remote interface with a parameter of type T, where T is a remote interface type, the system inserts a counterpart method in the class. The body of this method just calls the method that expects the business type associated with T. In order to illustrate, we show the aspect that transforms StockMarketImpl in a remote class. 1: aspect RemoteStockMarketImpl { 2: declare parents: StockMarketImpl implements 3: StockMarketOperations; 4: 5: public void StockMarketImpl.subscribe( 6: String stock, 7: stockwatcher.idl.stocklistener obj) { 8: StockListenerAdapter adapter; 9: adapter= new StockListenerAdapter(obj); 10: subscribe(stock, adapter); 11: 12:... 13: Lines 2-3 define that the class StockMarket- Impl must implement the remote interface Stock- MarketOperations (described in Section 4.1). Since the subscribe method of this interface expects a remote interface type as parameter, a method with the expected signature is also introduced in the class StockMarketImpl (lines 5 to 11). This introduction is needed since the subscribe method originally available in StockMarketImpl expects a parameter of the type StockListener (instead of the remote type stockwatcher.idl.stocklistener prescribed by the interface StockMarketOperations). The method introduced in StockMarketImpl redirects the call to the original subscribe method of the class (line 10). In order to make the redirection possible the following adapter is employed: 85

6 interface StockMarketOperations { void update(stockwatcher.idl.stockinfo info); void subscribe(string stock, stockwatcher.idl.stocklistener obj); void unsubscribe(string stock, stockwatcher.idl.stocklistener obj); stockwatcher.idl.stockinfo getstock(string stock) throws stockwatcher.idl.stocknotfoundexception; Figure 4. Java IDL interface for the motivating example class StockListenerAdapter implements StockListener { stockwatcher.idl.stocklistener adaptee; StockListenerAdapter ( stockwatcher.idl.stocklistener adaptee) { this.adaptee= adaptee; public void update(string stock, double value) { adaptee.update(stock,value); Essentially, this adapter conforms the Stock- Listener remote interface to its counterpart business interface. Classes that are not bound to a naming service: In such classes, the same inter-type declarations described previously are applied. Moreover, two new components are introduced by the associated aspect: a method export2idl responsible for the activation of the remote object, and a reference refidl to the stub created by the activation method provided by Java IDL. The export2idl method uses the value of refidl to decide whether the object needs to be activated or not. If the value is null, the method activates the object and stores its remote reference in refidl. The following aspect is created by DAJ to transform the business class StockListenerImpl into a remote class. 1: aspect RemoteStockListenerImpl { 2: declare parents: StockListenerImpl implements 3: StockListenerOperations; 4: 5: StockListener StockListenerImpl.refIDL= null; 6: 7: StockListener StockListenerImpl.export2IDL() { 8: // activates remote object using Java IDL API 9: 10: Line 3 defines that the class must implement the StockListenerOperations interface. The remainder of the aspect introduces in StockListenerImpl the refidl field (line 5) and the export2idl method (lines 7 to 9) OBTAINING REMOTE REFERENCES As defined in Section 3.2, clients obtain references to server objects by calling the getref method. The implementation of this method basically retrieves the information about the requested object from the distribution descriptor and uses this information to perform a lookup operation in the naming server of Java RMI or Java IDL. However, the getref method does not return a reference to the stub of the remote object, but to a proxy for this object. This proxy is generated by DAJ and acts as representant for the remote object. The proxy implementation assumes the task of activating remote objects when they are passed as arguments of remote calls. In order to support this feature, the proxy relies on the export2idl and export2rmi methods. The following example presents the proxy returned when the client requests a reference to a server object of the type StockMarketImpl: 1: class StockMarketProxy implements StockMarket { 2: stockwatcher.idl.stockmarket server; 3:... 4: void subscribe(string stock, StockListener obj) { 5: stockwatcher.idl.stocklistener _obj; 6: _obj= ((StockListenerImpl) obj).export2idl(); 7: server.subscribe(stock, _obj) 8:... 9: The proxy subscribe method exports the object associated with its obj parameter (line 6) before redirecting the call to the remote object (line 7) ACTIVATING REMOTE SERVERS DAJ generates aspects that are responsible for creating, enabling and registering remote servers, thus removing this concern from business classes. Particularly for Java RMI, the following abstract aspect defines pointcuts and advices for handling these concerns: 1: abstract aspect RMIServer { 2: abstract pointcut ServerMainExecution(); 3: abstract String getservername(); 4: abstract String getregistry(); 5: abstract Remote getinstance(); 6: 7: void around(): ServerMainExecution() { 8: // code to create, activate, and register 9: // remote objects 10: 11: In this aspect, the abstract pointcut ServerMain- Execution includes the join points where remote 86

7 servers should be created (line 2). The abstract method getservername (line 3) returns a string that contains the name under which the object must be registered. The abstract method getregistry returns the host name of the naming server (line 4). The getinstance method is a factory method responsible for the creation of remote objects (line 5). The aspect also contains an around advice associated with the ServerMainExecution pointcut (lines 7 to 10). This advice contains code to create, activate, and register remote objects, by using methods provided by Java RMI. DAJ also provides an abstract aspect called CORBAServer, that is similar to the aspect RMI- Server. Example: The concrete RMIServerStocketMarketB aspect created by DAJ activates and registers an instance of the StockMarketB server object defined in the distribution descriptor of the StockWatcher system. aspect RMIServerStockMarketB extends RMIServer { pointcut ServerMainExecution: execution( public static void ServerStockMarketB.main(..)); String getservername() { return "StockMarketB"; String getregistry() { return "patofu.pucminas.br:1530"; Remote getinstance() { return new StockMarketImpl(); The information needed to generate this aspect including the name of the remote object, the host name of the RMI Registry and the class of the remote object was retrieved from the distribution descriptor of the Stock- Watcher system EXCEPTION HANDLING This section describes how DAJ handles middleware concerns tangled in remote exception classes. Exception handling in Java IDL: In Java IDL, exceptions must be specified in the IDL signature of remote methods. From IDL interfaces, the idlj tool generates classes that represent such exceptions in Java. However, the generated classes present tangled Java IDL code to handle the serialization of the exception, so that it can be propagated from the server to the client address space. For example, such classes must extend org.omg.corba.userexception. On the other hand, the StockWatcher system also includes its own plain Java StockNotFound- Exception class: class StockNotFoundException extends Exception { public StockNotFoundException(String msg) { super(msg); Since we do not want to create any explicit middleware interference in core classes, DAJ generates an aspect that handles remote exceptions in the client and server sides of distributed applications. This aspect includes an advice that catches business exceptions raised by methods of the StockMarketImpl class and throws an equivalent remote exception. The system then relies on the CORBA layer to propagate remote exceptions to the client side. Another advice catches remote exceptions when they arrive in the client proxy class. This advice then throws an equivalent business exception. Exception handling in Java RMI: In Java RMI, business exceptions raised by remote methods are seamlessly propagated to client objects, using the Java built-in serialization mechanism. Therefore, there is no dichotomy between business and remote exception classes, as in Java IDL. However, Java RMI requires remote method signatures to declare a RemoteException checked exception, that is used to signal communication failures. In order to eliminate the need for handling such exception in the client code, DAJ generates an aspect that transforms it into an unchecked exception. 5. EXPERIMENTAL STUDY This section describes the use of DAJ in the modularization of distribution concerns from three applications: HealthWatcher: a Web-based information system used by citizens to register complaints about the sanitary conditions of restaurants and food shops. A first experience on using AspectJ to modularize Java RMI concerns of HealthWatcher has been conducted by Soares, Borba and Laureano [30, 29]. In this paper, we have repeated this experience, but using DAJ instead of manually extracting aspects from Heath- Watcher. Network Pricing System (NPS): a distributed system used to update and monitor stock prices. NPS has been originally designed as a text book example of a distributed application using many features provided by the Java IDL middleware platform [20]. Library: a Java-RMI library management system with functions for handling customers, titles, copies, making reservations etc. Library has also been used to evaluate an instrumentation infrastructure for reverse engineering of UML sequence diagrams proposed by Briand, Labiche and Leduc [4]. 87

8 In the study, we have initially refactored the original implementation of these systems, in order to remove distribution code from their business classes. Afterwards, we have defined distribution descriptors for the evaluated systems. The tool dajc was then used to generate aspects including both Java RMI and Java IDL code. The central idea of the study was to illustrate the ability of the system to handle distribution concerns from real-world applications. Since distribution is widely considered a crosscutting concern and thus a natural candidate for aspect-oriented approaches [30, 29, 32, 5, 21, 18], we only present information about the number of classes, interfaces and lines of code (LOC) regarding the original and refactored versions of the evaluated systems. Further studies may consider other object-oriented metrics in order to better demonstrate the advantages of using aspects for handling distribution HEALTHWATCHER The object-oriented version of the HealthWatcher system relies on Java RMI for communication. Table 1 presents quantitative information about the system. HealthWatcher core has 78 classes and 13 interfaces. Distribution concerns, such as service lookup, remote exceptions and synchronization, are implemented by 4 classes and 2 interfaces. The main modularization drawback of this version of the system is the fact that code related to distribution is tangled in the classes and interfaces of the core. Classes Interfaces LOC Core Distribution Total Table 1. RMI-based HealthWatcher DAJ-based HealthWatcher: Initially, a distribution descriptor was defined considering a deployment configuration employing two servers: one using Java RMI and the other relying on Java IDL. In this deployment descriptor, 25 classes designate objects passed by-serialization. HealthWatcher does not use call by-remote-reference. Table 2 summarizes the components generated by the DAJ compiler from the HealthWatcher distribution descriptor. The new core of the system after removing RMI classes and statements has 410 lines less than the original core. Moreover, the original HealthWatcher has a very rigid architecture, including only one Java RMI server. On the other hand, the DAJ-based system presents a more flexible architecture that supports easily changing the underlying middleware. It is worth to mention that Java IDL requires the generation of much more code than Java RMI (5671 lines C I A LOC Core DAJ internal components Java RMI generated code Java IDL generated code Total Table 2. DAJ-based HealthWatcher (C= Classes; I= Interfaces; A= Aspects) for Java IDL and only 191 lines for Java RMI). The main reason is that the Java IDL compiler must generate several components that are mandatory in CORBA implementations, including stubs, portable adapters, classes responsible for IDL-to-Java mappings etc. The same difference in the number of lines between the two middleware systems will be observed in the following systems NETWORK PRICING SYSTEM (NPS) NPS functionality is very similar to the motivating example used in this paper. However, we choose to refactor NPS because it was originally implemented using Java IDL and uses many of the features provided by this middleware technology. Table 3 presents information about the original version of the system. Classes Interfaces LOC Core Distribution Total Table 3. Java IDL-based NPS DAJ-based NPS: First, Java IDL code was fully removed from NPS core. In this step, we also needed to incorporate new classes in the core in order to replace classes generated by the Java IDL compiler that have been used in the implementation of functional requirements of the system. This is the case, for example, of classes representing objects that are passed by-serialization in remote calls. Such classes are generated by the idlj tool and thus they have methods and fields required by Java IDL programming conventions. After replacing idlj generated classes by plain Java classes, the core was converted into an application that is independent from any middleware technology. Table 4 summarizes the components generated by the DAJ compiler from the NPS distribution descriptor. As can be observed, the new core considering the components added to replace Java IDL functional components has 1210 lines, which is almost the same size of the original core. However, the new core does not depend anymore on any particular distribution technology. We were also able to change the communication middleware em- 88

9 ployed to access the two NPS server objects. In this way, it was very simple to build versions of NPS based on Java RMI only, on Java IDL only or on both platforms for example, one server can be configured to use Java RMI and the other one to use Java IDL. C I A LOC Core DAJ internal components Java RMI generated code Java IDL generated code Total Table 4. DAJ-based NPS (C= Classes; I= Interfaces; A= Aspects) both from middleware technology and Java API components. Moreover, by just changing the middleware protocol in the distribution descriptor we were able to deploy a Java IDL version of the Library System. C I A LOC Core DAJ internal components Java RMI generated code Java IDL generated code Total Table 6. DAJ-based Libray (C= Classes; I= Interfaces; A= Aspects) 5.3. LIBRARY SYSTEM The original version of the Library system uses Java RMI as the underlying communication infrastructure. Table 5 presents information about this version of the system. As can be observed in this table, the system does not have any class addressing distribution concerns (such as classes denoting remote exceptions). Basically, Library relies only on standard Java RMI classes that however are spreaded and tangled in the core functionality of the system. Classes Interfaces LOC Core Table 5. Java RMI-based Library System DAJ-based Library: First, we removed all RMI related concerns from the core. We had also to refactor remote method signatures when they include built-in classes from the Java API (such as java.util.vector). The reason is that such classes are not supported by Java IDL since Java IDL is a language neutral middleware platform. This restriction required us to implement new collection classes independent from the Java API. The Library system has three remote servers. The first one handles functionality related to library employees. The second server handles tasks related to reservations, loans and payments. Finally, the last one is used by customers to search the library collection. Moreover, the system has 27 classes describing objects that must be passed in remote calls using call by-serialization. It does not make use of call by-remote-reference. Table 6 summarizes the components generated by the dajc compiler from the Library distribution descriptor. It is worth to mention that the new core including the new collection classes has 193 more lines of code than the original one. However, this core is fully independent 6. DISCUSSION This section discusses the solution proposed by DAJ considering the following criteria: separation of concerns, usability and flexibility, portability, obliviousness and alternative implementation technologies. Separation of Concerns: Using DAJ we were able to synthesize aspects and classes that modularize distribution concerns in the three evaluated systems. After refactoring, distribution concerns were completely removed from the core of these applications. However, we had to replace concrete components generated by Java IDL to components independent from any middleware technology. The same was required when remote method signatures rely on components from the Java API. A core independent from middleware concerns is more simple to understand, test and evolve. Particularly, tests can be performed without considering distribution, which is critical for example to the success of test-driven development. Usability and Flexibility: Our experience demonstrates that defining distribution descriptors is fairly straightforward. It is very simple for example to change distribution parameters, such as the underlying middleware platform, naming servers location, remote object names etc. Moreover, it is also possible to reconfigure the distributed architecture of the base system. For example, we have rapidly reconfigured HealthWatcher to use two remote servers, instead of a single one. On the other hand, since it is based on XML, the distribution descriptorï s syntax is not as legible and concise when compared with concrete syntax based on non-markup languages. Another drawback is that middleware parameters are hard-coded in distribution descriptors. Thus, DAJ does not provide support for example to applications that dynamically discover information about remote services. In the future, we have plans to 89

10 tackle this problem. A possible solution is to extend the current API of the system, providing methods that allow clients to set up middleware parameters at run-time. Performance: In order to evaluate the performance of the system, we have measured the time to execute the remote calls included in the StockWatcher system. This system was executed 20 times. In each execution, each remote call of the system was dispatched ten thousand times. We then calculated the average time to perform the dispatched calls considering the sequences of 20 executions. Moreover, we have evaluated four versions of StockWatcher: based on Java RMI (using DAJ and using object-oriented code) and on Java IDL (using DAJ and object-oriented code). The results are presented on Tables 7 and 8. We run client and server processes on a Pentium GHz, 1 GB RAM, Microsoft Windows XP Service Pack 2, JDK 1.6 and ajc version c. The experiment demonstrates that DAJ does not impact significantly middleware performance. The performance overhead is negligible in most of the measured calls, both for Java RMI and Java IDL versions of the system. The only exception is when the getstock method raises a StockNotFoundException in the Java IDL-based version of StockWatcher. The performance overhead in this case is higher than 8%, compared with the original implementation of the system using scattered and tangled OO code. This overhead is due to the need of using aspects to handle such exception both on the server and on the client side of the distributed system, as described in Section 4.5. Portability: Using DAJ, we were able to deliver versions of the evaluated systems for a different middleware platform than the one supported by their original implementation. However, DAJ only provides support for the lowest common denominator between Java IDL and Java RMI. Basically, this translates to synchronous remote calls using call by-serialization and call by-remote-reference semantics. DAJ does not provide support for example to features available only in CORBA systems, such as asynchronous calls, oneway calls, portable interceptors, dynamic invocation interfaces etc. On the other hand, we envision that the system can be extended to support other CORBA ORBs, besides Java IDL. Another challenge is to provide support for Web Services in DAJ. In fact, we have already investigated this issue, considering Apache Axis as the middleware platform for supporting Web Services [2]. Basically, we faced two problems. First, Apache Axis generates its own classes for types used in remote service invocations. Such classes contain methods that serializes and deserializes objects according to Web Services standards. Thus, supporting Web Services in DAJ would require several inter-type declarations to transpose such methods to the classes of the base system. Another challenge is that Web Services do not support call by-remote-reference, since this would require the deployment of an HTTP server in each Web Service client. For this reason, we decided to do not support Web Services in the first DAJ implementation. In summary, we consider that DAJ is a solution that targets only crosscutting concerns inherent to distributed object architectures. Particularly, we do not expect that the proposed system can handle concerns related to other middleware paradigms, such as service-oriented, message-oriented or event-based. In the future, we consider that DAJ can be extended to generate code for other programming languages, such as C++ or C#. The only requirement is that aspect extensions for such OO languages become more mature. Obliviousness: Although DAJ fully insulates middleware code from application components, it is worth to mention that DAJ requires client modules to rely on its own getref method to retrieve remote references. Thus, it can be argued that DAJ replaces middleware tangling code by its own. However, this degree of tangling is minimal and it can be eliminated by creating an extra aspect, as illustrated below for an hypothetical StockWatcher client: 1: class MyClient { 2: StockMarket s1,s2; 3:... 4: 5: aspect MyClientDependencyInjection { 6: after(myclient c): 7: execution(void MyClient.new(..)) && this(s) { 8: c.s1= (StockMarket) 9: ServiceLocator.getRef("StockMarketA"); 10: c.s2= (StockMarket) 11 ServiceLocator.getRef("StockMarketB"); 12: 13: The proposed aspect, as happen in dependency injection frameworks [24, 6], assumes the charge of retrieving and binding remote references to instance variables s1 and s2 (lines 8 to 11). In this way, the class has remained oblivious to DAJ concerns. Alternative Technologies: Instead of aspects, at least two other technologies could have been used to modularize distributions concerns required by middleware platforms: Bytecode manipulation frameworks: Frameworks such as BCEL [9] could have been used to instrument the bytecode of the core classes with middleware related programming conventions. However, aspect-oriented languages, such as AspectJ, provide high-level abstractions to perform the same kind of instrumentation. Such abstractions have contributed to simplify the design and implementation of DAJ. 90

11 Remote Call RMI-DAJ RMI-OO DAJ / OO (%) update subscribe unsubscribe getstock returning StockInfo getstock returning an exception Table 7. Average time (in ms) to perform ten thousand remote calls in the Java RMI-based versions of the StockWatcher system (using DAJ and using tangled and spreaded OO code) Remote Call IDL-DAJ IDL-OO DAJ / OO (%) update subscribe unsubscribe getstock returning StockInfo getstock returning an exception Table 8. Average time (in ms) to perform ten thousand remote calls in the Java IDL-based versions of the StockWatcher systems (using DAJ and using tangled and spreaded OO code) Model-based Development: As promoted by modeldriven approaches [25], CASE tools can be augmented to support the generation of class skeletons incorporating middleware required code. Such classes can be generated from models, such as UML class and sequence diagrams, or from domainspecific languages. However, this approach usually generates code that is hard to understand and evolve. Moreover, since application logic is embedded in the synthesized class skeletons, it is usually hard to achieve round-trip engineering, i.e., moving back and forth between models and generated code [13]. 7. RELATED WORK Soares, Borba and Laureano have reported their experience using AspectJ to provide an aspect-oriented implementation for the HealthWatcher system [30, 29]. Regarding their work, DAJ presents at least three contributions: DAJ supports modularization both for Java RMI and Java IDL communication concerns. Supporting Java IDL is important to provide interoperability with clients and servers written in other programming languages. The challenge in this case was to avoid collisions and interferences among aspects specific to each middleware system. For example, when the aspects proposed by DAJ require inter-type declaration, interface implementation was preferred since Java only supports simple inheritance. DAJ supports parameter passing in remote calls using call by-serialization and call by-remotereference semantics. Instead, the aspects proposed by Soares, Borba and Laureano only handle call byserialization, since this was the only evaluation strategy employed in HealthWatcher. However, call byremote-reference is extensively used in other distributed object-based systems to support the implementation of callbacks [11]. DAJ is compatible with different software architectures employed in the design of distributed systems. On the other hand, the solution proposed by Soares and colleagues is restricted to the original architecture employed by the HealthWatcher system. For example, their solution assumes that there is a single server object of type HWFacade. The proposed pointcuts rely on this particular type to capture remote calls. For this reason, aspects used in Health- Watcher do not apply for example to clients that reference multiple server objects. Kulesza et al. have conducted a quantitative study to assess the positive and negative effects of using AOP in the HealthWatcher system [18]. Their study was driven by a suite of metrics for separation of concerns, coupling, cohesion and size. The conclusion is that the AO version of the system presents better results for almost all the considered metrics. Other works also report the advantages of using aspects to modularize distribution concerns [32, 5, 21]. Ceccato and Tonella have proposed an aspect-oriented framework to support the migration of a non-distributed application to a distributed architecture [5]. Similar to DAJ, the object-oriented code remains oblivious to the injected distributed behavior and the proposed aspects are generated automatically. However, their solution is restricted to Java RMI. Moreover, the configuration file 91

12 that guides the generation of aspects is just a list of class names, which does not contain information about parameter passing strategies, naming servers, etc. In their solution, call by-remote-reference is applied to all invocation parameters. Certainly, this decision is not adequated when the target of the modularization is an existing distributed application whose semantics depends on call byserialization. Additionally, using only call by-remotereference impacts the performance of the system, since the execution of remote methods must call back the client address space to access any argument. Reflective middleware systems rely on the application of reflection to achieve customizable, open, and adaptive middleware platforms [17]. For example, UIC CORBA supports the concept of personality, that allows users to specialize middleware systems according to the requirements of a given distributed application or domain [28]. It is possible for example to configure skeletons that support communication with different middleware systems. Pluggable protocols aim to support custom middleware protocol stacks in TAO, a well-known CORBA middleware framework [27]. The system targets mainly applications with sensitive time constraints, such as real-time and embedded systems. However, as usual in object-oriented middleware systems, both UIC and TAO require developers to follow their specific programming conventions, which usually lead to code scattering and tangling [22]. Ghosh and colleagues have proposed a middleware transparent approach to support the implementation of distributed systems [12]. Similar to DAJ, they rely on aspects to decouple business concerns from middlewarespecific functionality. Moreover, they propose a modeldriven approach to distributed systems development. A middleware transparent design (MTD) is a model of the system that do not address middleware concerns. Aspects are weaved to such model to derive a middleware specific design (MSD) that addresses both business and distribution concerns. Accordingly to Model Driven Architecture (MDA) principles [25], a MTD corresponds to a PIM (Platform Independent Model) and a MSD to a PSM (Platform Specific Model). DAJ is a system that implements and puts into practice many principles and ideas proposed by Ghosh and colleagues in their proposal. Zhang and Jacobsen have quantified the crosscutting nature of several features of CORBA based middleware [37]. They have measured the scattering degree of features such as portable interceptors, dynamic programming invocations, collocation optimizations, and asynchronous calls. They have also showed that such features can be modularized using aspect-oriented programming. From this experience, they have proposed the horizontal decomposition method [38]. Horizontal decomposition advocates the use of traditional modularization techniques, such as vertical decomposition, to implement a minimal but well-modularized core middleware system. Aspects should then be used to superimpose orthogonal features to this core. They have assessed the effectiveness of their method by re-implementing as aspects crosscutting features of the original implementation of OR- Bacus [26]. AspectJRMI is another middleware system whose design has been guided by horizontal decomposition principles [10]. Colyer et al. have conducted an aspect-oriented refactoring of a large scale middleware product-line [7]. They have identified many crosscutting concerns in the product-line, including homogenous concerns (tracing, logging, error analysis and reporting, monitoring, and statistics) and heterogeneous concerns (EJB support). Similar to Zhang and Jacobsen, Colyer work aims to modularize crosscutting concerns that are internal to the middleware layer. In DAJ-based distributed systems, the language employed in the specification of distribution descriptors can be considered as a domain-specific aspect-oriented language. Recently, some works have proposed the use of domain-specific languages to describe crosscutting concerns, since such languages rely on abstractions and vocabulary that is closer to the concern they intend to modularize. Moreover, they are less susceptible to critics commonly related to general purpose aspect-oriented languages. For example, many researchers consider that languages such as AspectJ defeats basic software engineering principles, such as modular reasoning, parallel development and encapsulation [35, 31]. Certainly, such critics are less important when using domain-specific aspect languages. It is also worth to mention that the first generation of aspect languages was defined for domain-specific purposes, including RIDL (for remote interface specification) and COOL (for coordination and synchronization) [21]. 8. CONCLUSIONS In this paper, we have described a system called DAJ that provides middleware independence in distributed, object-oriented systems. For this purpose, DAJ relies on the combination of three technologies: aspects, domainspecific languages and generative programming. DAJ also supports two native, object-oriented JDK middleware platforms: Java RMI and Java IDL. The system modularizes the basic service provided by these middleware platforms, i.e. synchronous remote calls using call byserialization and call by-remote-reference semantics. Particularly, DAJ does not provide support to features available only in CORBA systems, such as asynchronous calls, oneway calls, portable interceptors, dynamic invocation interfaces etc. In order to evaluate the proposed system, we have refactored three medium-sized distributed applications: 92

Report of the case study in Sistemi Distribuiti A simple Java RMI application Academic year 2012/13 Vessio Gennaro Marzulli Giovanni Abstract In the ambit of distributed systems a key-role is played by

Software Engineering, Lecture 4 Decomposition into suitable parts Cross cutting concerns Design patterns I will also give an example scenario that you are supposed to analyse and make synthesis from The

Integration of Application Business Logic and Business Rules with DSL and AOP Bogumiła Hnatkowska and Krzysztof Kasprzyk Wroclaw University of Technology, Wyb. Wyspianskiego 27 50-370 Wroclaw, Poland Bogumila.Hnatkowska@pwr.wroc.pl

MIDDLEWARE 1 David E. Bakken 2 Washington State University Middleware is a class of software technologies designed to help manage the complexity and heterogeneity inherent in distributed systems. It is

Part I EAI: Foundations, Concepts, and Architectures 5 Example: Mail-order Company Mail order Company IS Invoicing Windows, standard software IS Order Processing Linux, C++, Oracle IS Accounts Receivable

Architectures Computing & 2009-11-06 Architectures Computing & SERVICE-ORIENTED COMPUTING (SOC) A new computing paradigm revolving around the concept of software as a service Assumes that entire systems

Appendix A Elements of Advanced Java Programming Objectives At the end of this appendix, you should be able to: Understand two-tier and three-tier architectures for distributed computing Understand the

What is Middleware? Application Application Middleware Middleware Operating System Operating System Software that functions as a conversion or translation layer. It is also a consolidator and integrator.

Toward Next Generation Distributed Business Information Systems: Five Inherent Capabilities of -Oriented Computing Chung, Sam and Davalos, Sergio Abstract The research conducted examines how the emerging

Developing in OMG s New -Driven Architecture Jon Siegel Director, Technology Transfer Object Management Group In this paper, we re going to describe the application development process supported by OMG

CORBAservices CORBAservices are general purpose and application independent services. They resemble and enhance services commonly provided by an operating system: Service Collection Query Concurrency Transaction

Interface Definition Language A. David McKinnon Washington State University An Interface Definition Language (IDL) is a language that is used to define the interface between a client and server process

Research on the Model of Enterprise Integration with Web Services XIN JIN School of Information, Central University of Finance& Economics, Beijing, 100081 China Abstract: - In order to improve business

Getting Started with - Oriented Architecture (SOA) Terminology Grace Lewis September 2010 -Oriented Architecture (SOA) is a way of designing, developing, deploying, and managing systems it is neither a

-Oriented Architecture and Software Engineering T-86.5165 Seminar on Enterprise Information Systems (2008) 1.4.2008 Characteristics of SOA The software resources in a SOA are represented as services based

Writing Grid Service Using GT3 Core Dec, 2003 Long Wang wangling@mail.utexas.edu Department of Electrical & Computer Engineering The University of Texas at Austin James C. Browne browne@cs.utexas.edu Department

System types 1 Personal systems that are designed to run on a personal computer or workstation Distributed systems where the system software runs on a loosely integrated group of cooperating processors

Page 1 de 9 What Is the Java TM 2 Platform, Enterprise Edition? This document provides an introduction to the features and benefits of the Java 2 platform, Enterprise Edition. Overview Enterprises today

Module 17 Client-Server Software Development Lesson 42 CORBA and COM/DCOM Specific Instructional Objectives At the end of this lesson the student would be able to: Explain what Common Object Request Broker

FUSE-ESB4 An open-source OSGi based platform for EAI and SOA Introduction to FUSE-ESB4 It's a powerful OSGi based multi component container based on ServiceMix4 http://servicemix.apache.org/smx4/index.html

Distributed Objects and Components Introduction This essay will identify the differences between objects and components and what it means for a component to be distributed. It will also examine the Java

Distributed systems Distributed Systems Architectures Virtually all large computer-based systems are now distributed systems. Information processing is distributed over several computers rather than confined

Software Engineering Architectural Design 1 Software architecture The design process for identifying the sub-systems making up a system and the framework for sub-system control and communication is architectural

New Generation of Software Development Terry Hon University of British Columbia 201-2366 Main Mall Vancouver B.C. V6T 1Z4 tyehon@cs.ubc.ca ABSTRACT In this paper, I present a picture of what software development

Sun Educational Services Instructor-Led Course Description Fundamentals of Java SL-110 The Fundamentals of the Java course provides students, with little or no programming experience, with the basics of

4D and SQL Server: Powerful Flexibility OVERVIEW MS SQL Server has become a standard in many parts of corporate America. It can manage large volumes of data and integrates well with other products from