29
Aspect-oriented Transactions via Explicit Join Points Kevin Hoffman / Patrick Eugster

Aspect-oriented Transactions via Explicit Join Points

Embed Size (px)

DESCRIPTION

We demonstrate how to safely and effectively implement transactions following an aspect-oriented paradigm using our proposed extension of AspectJ, Explicit Join Points.

Citation preview

Page 1: Aspect-oriented Transactions via Explicit Join Points

Aspect-oriented Transactions

via Explicit Join Points

Kevin Hoffman / Patrick Eugster

Page 2: Aspect-oriented Transactions via Explicit Join Points

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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

-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