Remote Pointcut - A Language Construct for Distributed AOP
Download
Report
Transcript Remote Pointcut - A Language Construct for Distributed AOP
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