Remote Pointcut - A Language Construct for Distributed AOP To appear at AOSD’04 Muga Nishizawa (Tokyo Tech, Japan) Shigeru Chiba (Tokyo Tech, Japan) Michiaki Tatsubori (TRL, Japan IBM) PPL 2004, Gamagori, AICHI 1 This Presentation Our goal To modularize crosscutting concerns in distributed software This presentation Background AOP, crosscutting concern, AspectJ, … Motivating problem and example A test code for distributed software Our solution Remote pointcut SPA’04 PPL 2004, Gamagori, AICHI 2 AOP (Aspect-Oriented Programming) Separation of crosscutting concerns What is a crosscutting concern? The implementation of the concern cuts across multiple modules Crosscutting concerns Within confines of existing technology class Car { E.g. OOP void start() { System.out.println(“start”); …… aspect Log { }} before(): class Bike { execution(void Car.start()) exec void start() { || execution(void Bike.start()) { System.out.println(“start”); exec System.out.println(“start”); …… PPL 2004, Gamagori, AICHI 3 }} }} AspectJ - General-purpose AOP Language for Java Like event-driven model Pointcut To identify join points Join poin (event) aspect Log { before(): execution(void Car.start()) Execution point in a program || execution(void Bike.start()) { E.g. method call, field access System.out.println(“start”); }} Advice (action) Code that should be execute at each identified join point in pointcuts Before, after, and around PPL 2004, Gamagori, AICHI 4 Motivating Problem Crosscutting concerns in distributed software AspectJ can separate them But, the implementation is NOT simple PPL 2004, Gamagori, AICHI 5 Test Code for Distributed Authentication Service Confirm addUser() is executed on Database Client calls registerUser(), registerUser() calls addUser() Authenticator Register a new user on a DB registerUser() Client Database addUser() PPL 2004, Gamagori, AICHI 6 Ideal Design for Test Code On Client, 1. flag = false. 2. call registerUser() on Authenticator. 3. if addUser() is executed on Database, then flag = true. 4. assert flag == true. Authenticator registerUser() Client Database PPL 2004, Gamagori, AICHI addUser() 7 Test Code in Java Crosscutting concern Database code must be edited for test Authenticator Client 1. Flag = false 2. Call registerUser() Database Crosscutting 3. assert flag == true RMI Callback (Remote Method Invocation) Flag = true PPL 2004, Gamagori, AICHI class Database { void addUser() { concern invoke Callback …… add the user to the database } …… } 8 Test Code in Java and AspectJ The concern is separated Database code is not edited Database class Database { void addUser() { …… add the user to the database Client 1. Flag = false 2. Call registerUser() } } 3. Assert flag == true DatabaseTest Callback aspect DatabaseTest { before(): execution(void addUser()){ invoke Callback } 9 } Flag = true RMI PPL 2004, Gamagori, AICHI This Design is Not Satisfactory When writing the test code, we must consider two concerns: Test Don’t consider this! Distribution It requires to divide the code into three sub-modules Network processing (RMI) and deployment 1. flag = false. 2. call registerUser() on Authenticator. Three distributed sub-modules 3. if addUser() is invoked on Database, flag = true. 4. Assert flag == ture PPL 2004, Gamagori, AICHI 10 Our Solution - Remote Pointcut To identify join points in a program on a remote host To run advice on a different host from the host where join points are pointcut Like RMI for distributed OOP Identified join point Remote aspect Log { class Database { pointcut before() : void addUser() { execution(void addUser()) { System.out.println(“addUser”); …… } } } PPL 2004, Gamagori, }AICHI 11 Test Code using a Remote Pointcut Test program is a single non-distributed module AuthenticatorTest (Aspect) Authenticator call registerUser() 1. flag = false 2. call registerUser() 3. assert flag == true call addUser() Database class Database { void addUser() { before(): Remote cflow(call(void registerUser())) Pointcut } &&execution(void addUser()){ …… flag = true } } PPL 2004, Gamagori, AICHI 12 Test Code Implementation aspect AuthenticatorTest extends TestCase { boolean flag; Declares and initializes the flag Calls registerUser() Confirms the flag is true When addUser() is executed, the flag is set to true void testRegisterUser() { flag = false; String userId = "muga", password = "xxx"; Authenticator auth = (Authenticator) Naming.lookup("auth"); auth.registerUser(userId, password); assertTrue(flag); } before(): // remote pointcut cflow(call(void Authenticator.registerUser())) && execution(void Database.addUser()) { flag = true; }} PPL 2004, Gamagori, AICHI 13 DJcutter - Distributed AOP Language It’s an extension of AspectJ language Remote pointcut Remote inter-type declaration Load-time weaving Aspect weaving in DJcutter is performed at load-time PPL 2004, Gamagori, AICHI 14 DJcutter Language Specification Pointcut DJcutter provides pointcut designators in AspectJ Call, execution, within, target, … Hosts(Host, …) The join points in execution on the hosts Cflow(Pointcut) All join points that occur between the entry and exit of each join point specified by Pointcut Advice Before, after, and around PPL 2004, Gamagori, AICHI 15 Remote Inter-type Declaration To declare methods and fields in classes on a remote host AuthenticatorTest Append at load-time Database boolean containsUser(); aspect AuthenticatorTest { boolean Database.containsUser(String userId) { // If the user entry specified by userId is found // in the database. } } PPL 2004, Gamagori, AICHI 16 Use of Remote Inter-type Declaration aspect AuthenticatorTest extends TestCase { Confirms that the user entry void testRegisterUser() { String userId = "muga", password = "xxx"; Authenticator auth = (Authenticator) Naming.lookup("auth"); Database db = (Database) Naming.lookup(“db”); assertFalse(!db.containsUser(userId); auth.registerUser(userId, password); assertTrue(db.containsUser(userId)); } boolean Database.containsUser(String userId) { // If the user entry specified by userId is // found in the database. }} PPL 2004, Gamagori, AICHI 17 DJcutter Implementation Compiler To generate Java-bytecodes representing aspects Runtime infrastructure To implement load-time weaving PPL 2004, Gamagori, AICHI 18 Load-time Weaving Distributed software Aspect source file weave Class Loader Runtime Infrastructure Compiler Java bytecode deploy Distributed software weave entry Class Loader Aspect Server deploy Runtime Infrastructure Runtime Infrastructure PPL 2004, Gamagori, AICHI 19 Related Work 1 Middleware for automatic distribution E.g. J-Orchestra and Addistant They completely hide distribution concern Conbination of AspectJ and them We are not sure they are good for Tomcat, Oracle, … PPL 2004, Gamagori, AICHI 20 Related Work 2 Other distributed AOP languages E.g. D language framework JAC (Java Aspect Componenets) To modularize functional crosscutting concerns DJcutter Remote pointcut To modularize non-functional crosscutting concerns PPL 2004, Gamagori, AICHI 21 Conclusion Remote pointcut To transparently identify join points on remote hosts Like RMI for distributed OOP To run advice on a different host from the host where join points are pointcut Without consideration of distribution concern DJcutter – Distributed AOP Language Remote pointcut Extension of AspectJ language PPL 2004, Gamagori, AICHI 22 The End Thanks PPL 2004, Gamagori, AICHI 23 PPL 2004, Gamagori, AICHI 24 PPL 2004, Gamagori, AICHI 25 Even if writing RMI is very easy, We still have a question: Why the test code consists of three submodules? Because of not test but distribution concern 1. flag = false. 2. call registerUser() on Authenticator. 4. Assert flag == ture Design Problem 3. if addUser() is invoked on Database, flag = true. PPL 2004, Gamagori, AICHI 26 DJcutter Implementation Compiler To generate a Java-bytecode representing an aspect Runtime infrastructure To implement load-time weaving Aspect server Extended class loader PPL 2004, Gamagori, AICHI 27 PPL 2004, Gamagori, AICHI 28 Our Solution To run advice on a different host from the host where join points are pointcut Implementing a single module without consideration of distribution That is, it can separate distribution concern from the test code Non-distributed sub-modules, Automatic deployment, And separation of crosscutting concerns PPL 2004, Gamagori, AICHI 29 Remote Pointcut To identify join points in a program flow on remote host transparently Corresponding to RMI for distributed OOP Extends to pointcut designators in AspectJ A single non-distributed module on a single host Log Database aspect Log { before() : execution(void addUser()) { System.out.println(“addUser”); } } Remote pointcut class Database { void addUser() { System.out.println(“addUser”); …… } } PPL 2004, Gamagori, AICHI 30 Three Distributed Sub-modules Ideally, a concern should be described a nondistributed single module We want to write without consideration of distribution The test code is written with consideration of distribution As a result, sub-modules, complicated network processing, deployment 1. flag = false. 2. call registerUser() on Authenticator. 3. if addUser() is invoked on Database, flag = true. 4. Assert flag == ture PPL 2004, Gamagori, AICHI 31 Three Distributed Sub-modules Idealy, a concern should be described as a non-distributed single module on a single host この test code は、分散した sub-modules になっ ている Separated, but far from the ideal test code Remote method invocation among sub-modules Deployment Client Client Callback DatabaseTest Callback DatabaseTest DatabaseTest RMI PPL 2004, Gamagori, AICHI 32 Related Work PPL 2004, Gamagori, AICHI 33 Ideal Test Code In the test code, we declare a flag for comfirming that addUser() was executed call registerUser() Test Program Main part for testing call addUser() 1. Sets flag to false 2. Remotely calls registerUser() Database Flag is set to true, when addUser() is executed 3. Confirms that flag is ture Authenticator PPL 2004, Gamagori, AICHI class DbServer { void addUser() { …… } } 34 実際に実装する AuthServerTest 1.registerUser() 呼出 AuthServer class AuthServerTest extends TestCase { boolean wasAddUserCalled; void testRegisterUser() { Naming.rebind("test", new RecieverImpl()); 2.addUser() 呼出 wasAddUserCalled = false; String userId = "muga", password = "xxx"; DbServer AuthServer auth = (AuthServer) Naming.lookup("auth"); auth.registerUser(userId, password); interface NotificationReceiver { void confirmCall(); } aspect Notification { assertTrue(wasAddUserCalled); before(): } class ReceiverImpl execution(void DbServer.addUser()){ extends UnicastRemoteObject NotificationReceiver test implements NotificationReceiver { = (NotificationReceiver) void confirmCall() { Naming.lookup("test"); wasAddUserCalled = true; RMI test.confirmCall(); }} PPL 2004, Gamagori, AICHI 35 }} interface NotificationReceiver { void confirmCall(); } Experimental Results PPL 2004, Gamagori, AICHI 36
© Copyright 2024 ExpyDoc