aspect-oriented transactions via explicit join points
DESCRIPTION
We demonstrate how to safely and effectively implement transactions following an aspect-oriented paradigm using our proposed extension of AspectJ, Explicit Join Points.TRANSCRIPT
![Page 1: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/1.jpg)
Aspect-oriented Transactions
via Explicit Join Points
Kevin Hoffman / Patrick Eugster
![Page 2: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/2.jpg)
-2-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Outline
Review of Transactions
Review of Aspects
AOP Methods for Transactions
Discussion of problems
New Approach
The good, the bad, and the unknown
The next step
![Page 3: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/3.jpg)
-3-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Review of Transactions
Transactions provide:
(A)tomicity – all or nothing
(C)onsistency – deterministic data changes
(I)solation – appears concurrency not present
(D)urability – finished results never lost
![Page 4: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/4.jpg)
-4-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Review of Transactions [2]
Implementation approaches: Language approach
+ Safety
+ Elegance
- Flexibility
- Interoperability
Library approach- Safety
- Elegance
+ Flexibility
+ Interoperability
Can we do better?
![Page 5: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/5.jpg)
-5-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Introducing AOP
Aspect Oriented Programming can do it! (or can it?)
AOP Motivation: Programs naturally decompose in multiple ways
(functional, information flow, …)
Programs cannot be captured by one way of decomposition
Cross-cutting concerns result from superimposing logic tied to one method of decomposition on top of another
(…Examples from the audience…)
![Page 6: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/6.jpg)
-6-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Review of Aspects
AOP Solution:
Expose structural points of the program’s
primary decomposition as first class language
features (join points)
Provide first class language mechanisms
(aspects) to superimpose logic (advice)
systematically on top of the primary program
decomposition (via pointcuts)
![Page 7: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/7.jpg)
-7-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
AspectJ: AOP’s “mother tongue”
Extension of Java
Primary program decomposition is functional
Join point model (100% implicit): Method calls, object construction, thrown exceptions
Member variable access
Pointcuts expressed via pattern matching
Philosophy of obliviousness Write your program ignoring cross cutting concerns
Add logic for these concerns ad hoc
Pray that you haven’t broken anything!
![Page 8: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/8.jpg)
-8-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Simple AspectJ Example
class Bank {public void deposit(Account A, Account B, double amount){
...}
}
aspect Auditer {OutputStream m_logger = System.out;pointcut auditPoints(): call(public * Bank.*(..));around(): auditPoints() {
m_logger.println("BEFORE: "+thisJoinPoint.);proceed();m_logger.println("AFTER: "+thisJoinPoint.);
}}
![Page 9: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/9.jpg)
-9-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Aspects and Transactions
AOP approach to transactions:+ Elegance
Separates base code and transactionalizing mechanisms
+ Flexibility
Easy to change implementation details anytime
+ Interoperability
Compiles to Java 2 bytecode
- Safety
Relies on “skill” of aspect programmer to maintain
![Page 10: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/10.jpg)
-10-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Safety Issues with AOP
Why there is no safety for transactions: Advice introduces new error paths that the base code is not
constrained to handle
Implies there is a semantic coupling
But aspects provide only implicit, one-way communication from classes to aspects
Aspects can change anything at any time
Aspects superimposes stricter semantics upon classes, introducing problems (unsolvable deadlock)
Advice has a narrow focus (they affect one joinpoint at a time)
Changes in classes break aspects (mitigated by tools)
![Page 11: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/11.jpg)
-11-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Transactions w/ AspectJ [1]
//First we naively write this class
class Bank {
public void transfer(Account A, Account B, double amount){
if (A.getBal() < amount){ … }
A.withdraw(amount);
B.deposit(amount);
}
public void waitAndTransfer(Account A, Account B, double amount)
{
A.deposit(amount);
while (B.getBalance() <= amount){}
B.withdraw(amount);
}
}
![Page 12: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/12.jpg)
-12-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Transactions w/ AspectJ [2]
//And we blissfully write this simple class
class BankSystem {
public void mutualExch(Bank bank, Account A, Account B,
double a1, double a2){
Threads T = new Threads();
T.add(new Thread(bank.waitAndTransfer(A,B,a1)));
T.add(new Thread(bank.waitAndTransfer(B,A,a2)));
T.joinAll();
}
}
![Page 13: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/13.jpg)
-13-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Transactions w/ AspectJ [3]
//The bank also serves as a travel agency…
class Agent {
…
void createTrip(Person p, Flight f, Hotel h) {
f.ReserveSeat(p);
f.ReserveRoom(p);
m_CC.Debit(p.getCC(), ...);
}
}
![Page 14: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/14.jpg)
-14-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Transactions w/ AspectJ [4]
//Now we create a transactionalizing mechanisms using aspects
public abstract aspect TransactionalMethods {
abstract public pointcut MethodsToWrap();
void around() : MethodsToWrap() {
Object TARGET = thisJoinPoint.getTarget();
TransMan.beginTrans(TARGET);
boolean aborted = false;
try{ proceed(); } catch (Exception e){
TransMan.abortTrans(TARGET);
aborted=true; throw e;
} finally {
if (!aborted){ TransMan.commitTrans(TARGET); }
}
}
}
![Page 15: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/15.jpg)
-15-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Transactions w/ AspectJ [5]
//Now we transactionalize these three classes post-mortem using aspects
aspect MakeBankTran extends TransactionalMethods {
public pointcut MethodsToWrap() :
call (public * Bank.deposit*(..));
}
aspect MakeBankSystemTran extends TransactionalMethods {
public pointcut MethodsToWrap() :
call (public * BankSystem.mutualExch(..));
}
aspect MakeAgentTran extends TransactionalMethods {
public pointcut MethodsToWrap() :
call (public * Agent.createTrip(..));
}
![Page 16: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/16.jpg)
-16-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
New Error Paths
Can throw AbortException or CommitException, but there is no way
to constrain the base code to catch these exceptions…
![Page 17: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/17.jpg)
-17-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
New Error Paths [2]
Oblivious code has no idea that the end of the method call could
result in an exception. Even wrapping m_CC.Debit with finally does
not help [exception is thrown after method exits].
![Page 18: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/18.jpg)
-18-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Stricter Semantics --> Problems
The TransactionalMethods aspect wraps a transaction around
mutualExch, causing all data access to become serialized… Also, advice
is narrow and is not aware that scope of transaction contains 2 threads.
![Page 19: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/19.jpg)
-19-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Stricter Semantics --> Problems [2]
<thread 1>
public void waitAndTransfer(Account Alice,
Account Bob, double amount)
{
Alice.deposit(amount);
while (Bob.getBalance() <= amount){}
Bob.withdraw(amount);
}
<thread 2>
public void waitAndTransfer(Account Bob,
Account Alice, double amount)
{
Bob.deposit(amount);
while (Alice.getBalance() <= amount){}
Alice.withdraw(amount);
}
Thread 1 acquires lock on Alice and Bob, preventing thread 2 from
depositing the amount needed to unblock thread 1 (because the aspect
does not know the 2 threads are part of the same transaction and forces
each to acquire separate locks). Unsolvable deadlock!
![Page 20: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/20.jpg)
-20-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Our Proposed Solution
Make aspects an explicit part of mainline code
Mainline code tells aspect how to apply itself
Impose constraints on the interaction (bi-directional)
Explicitness allows for new types of interaction and structure
Define notion of explicit join points (EJPs): Explicitly declared (think of it as a new type)
Declaration defines properties, parameters, and constraints
Declared globally or within an [abstract] aspect
![Page 21: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/21.jpg)
-21-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Introduction to EJPs
aspect AspectName {
[scoped] joinpoint AJPName (parameters) [throws ClassList];
}
class ClassName {
public void methodName(type1 parm1, type2 parm2, ...){
joinpoint AspectName.AJPName(parm2,parm2*parm1);
joinpoint AspectName.AJPNameNested(parm2,parm2*parm1){
…
}
}
}
![Page 22: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/22.jpg)
-22-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Transactions w/ EJPs
//Actually write the aspect first (could be an abstract aspect…)
aspect Transactionalizer {
scoped joinpoint jpTrans(Serializable[] objects) throws CommitException;
pointcut pcTrans(Serializable[] objects) : joinpoint(jpTrans) && args(objects);
before(Serializable[] objs): pcTrans(objs) {
TransMan.begin(objs, ...);
}
after() returning: pcTrans() {
TransMan.commit(...);
}
after() throwing: pcTrans() {
TransMan.abort(...);
}
}
![Page 23: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/23.jpg)
-23-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Transactions w/ EJPs [2]
//Now write the code that is semantically tied to the (possibly) abstract aspectclass Agent implements Serializable {
void createTrip(Person p, Flight f, Hotel h) {boolean bCharged = false;try {
Serializable[] objects = {this, p, f, h};Transactionalizer.jpTrans(objects) {
f.ReserveSeat(p);f.ReserveRoom(p);m_CC.Debit(p.getCC(), ...);bCharged = true;
}} catch (CommitException e) {
if (bCharged){ m_CC.Credit(p.getCC(), ...); }}
}}
![Page 24: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/24.jpg)
-24-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
EJP Error Path Constraints
CommitException
must be caught or a
compiler error is
generated
![Page 25: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/25.jpg)
-25-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
EJP Scope Constraints
Aspect understands
scope of transaction
![Page 26: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/26.jpg)
-26-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Explicit Join Pointspublic aspect TranMethods pertarget {
scoped jpTrans (pointcut)
throws CommitException;
public pointcut JPTransNewThread() :
within(jpTrans) &&
call (public * Thread.Thread(..));
public pointcut JPTransEnterScope() :
enterScope(jpTrans);
public pointcut JPTransExitScope() :
exitScope(jpTrans);
Threads m_T = new Threads();
void after() : JPTransNewThread() {
m_T.add(thisJoinPoint.getTarget());
}
void before() : JPTransEnterScope() {
TransMan.beginTrans(…);
}
void after() : JPTransExitScope() {
m_T.joinAll();
TransMan.commitTrans(…);
}
}
class Bank {
public void depositWait(Account A, Account B,
double amount)
{
A.deposit(amount);
while (B.getBalance() <= amount){}
B.withdraw(amount);
}
}
class BankSystem {
public void mutualExch(Bank bank
Account A, Account B,
double a1, double a2)
throws CommitException
{
TranMethods.jpTrans(
public * Bank.deposit*(..))
{
Threads T = new Threads();
T.add(new Thread(
bank.waitDeposit(A,B,a1)));
T.add(new Thread(
bank.waitDeposit(B,A,a2)));
T.joinAll();
}
}
}
![Page 27: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/27.jpg)
-27-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Explicit Join Points
Why is it different than a function call?
Aspect(s) may apply advice at the explicit join point
Aspect instance can be specific to instance of target
method
Other joinpoints may be passed as parameters
Scoped explicit join points provide additional structure
Makes pointcuts more deterministic
![Page 28: Aspect-oriented Transactions via Explicit Join Points](https://reader033.vdocuments.site/reader033/viewer/2022051411/547cf2dcb479597f508b47c3/html5/thumbnails/28.jpg)
-28-Kevin Hoffman and Patrick Eugster, DSN’06 (Handout)
Transactions via EJPs
+ Elegance Separates base code and transactionalizing mechanisms
+ Flexibility Easy to change implementation details anytime
+ Interoperability Compiles to Java 2 bytecode
+ Safety EJP enforces constraints on base code at compile time