Applying AspectOriented Software Development to Middleware Frameworks Tal

  • Slides: 48
Download presentation
Applying Aspect-Oriented Software Development to Middleware Frameworks Tal Cohen Joint work with Yossi Gil

Applying Aspect-Oriented Software Development to Middleware Frameworks Tal Cohen Joint work with Yossi Gil

Research Overview More Results – Applicable to almost any software development domain. Solution •

Research Overview More Results – Applicable to almost any software development domain. Solution • The research outcome: a set of programming language constructs. Problem – Huge software programs for banks, government agencies, etc. Overview • The problem: simplifying the design, development and modularity of enterprise applications.

Contributions • Shakeins – aspect-like mechanism combining AOP with OOP. Problem Solution More Results

Contributions • Shakeins – aspect-like mechanism combining AOP with OOP. Problem Solution More Results • Factories – a language-level mechanism for managing object instantiation. • JTL –a language for Query-by-Example searches in a program source. • Object Evolution – objects can change type at runtime in type-safe systems. Overview – Aspect. J 2 EE – a proof-of-concept design for shakeins in Enterprise Java.

Outline • The Problem: Enterprise Application Development. • Additional Contributions More Results – From

Outline • The Problem: Enterprise Application Development. • Additional Contributions More Results – From better static pointcuts to dynamic shakeins Solution – How to integrate AOP with middleware frameworks Problem • The Solution: Shakeins Overview – "The unbelievable complexity of simple chores" – Overview of existing solutions: middleware frameworks, aspects… – … and why they aren't good enough

Shakeins Overview class Secure<Car class Car > Now with anti-theft mechanism! Problem Solution More

Shakeins Overview class Secure<Car class Car > Now with anti-theft mechanism! Problem Solution More Results Interface Implementation: Interface: Engineremains and other visible externally unchanged internals features

Shakeins Now with recording blackbox! class We also Logging<Secure<Car>> do buses! Overview Problem Solution

Shakeins Now with recording blackbox! class We also Logging<Secure<Car>> do buses! Overview Problem Solution More Results Interface is still unchanged

Shakeins in Brief • Intelligently modify the original class: C++ More Results • Similar

Shakeins in Brief • Intelligently modify the original class: C++ More Results • Similar to but less chaotic than aspects. Solution Account accnt = new Secure<Account>() Problem • Can be used to create objects, but not to declare variables (not a new type): Overview shakein Secure { // Secure<T> re-implements T before execution of any public method (in T) { … perform security test … Mixins, Java generics, and } } templates cannot do this!

The Problem

The Problem

Why Programming a Banking Application is Easy Overview Problem class Account { void transfer.

Why Programming a Banking Application is Easy Overview Problem class Account { void transfer. To(Account other, int amount) { if (balance < amount) throw new Overdraft. Exception(); this. balance -= amount; other. balance += amount; } … Solution More Results

Why Programming a Banking Application is Not Easy Problem Solution More Results Non-functional concerns

Why Programming a Banking Application is Not Easy Problem Solution More Results Non-functional concerns yield tangled and scattered code. Overview class Account { void transfer. To(Account other, int amount) { Log. log("Attempting transfer"); LOGGING User user = Security. get. Context(). get. Current. User(); if (!user. can. Transfer. From(this)) SECURITY Log. security. Error(); throw new Security. Exception(); Transaction tx = Db. get. Connection(). begin. Transaction(); this. refresh. Fields(); other. refresh. Fields(); if (balance < amount) tx. rollback(); throw new Overdraft. Exception(); this. balance -= amount; BUSINESS LOGIC other. balance += amount; this. update. Db(); other. update. Db(); PERSISTENCE tx. commit(); TRANSACTION MANAGEMENT Log. log("Transfer completed"); } …

Making Enterprise Development Easier • Past: Work hard • Present: Middleware Frameworks Solution •

Making Enterprise Development Easier • Past: Work hard • Present: Middleware Frameworks Solution • Future: Future Aspect-Oriented Middleware Frameworks Problem – CORBA, DCOM, Enterprise Java Overview – Bonus: You get to use COBOL More Results

Middleware Frameworks and Services More Results – e. g. , by XML files. Solution

Middleware Frameworks and Services More Results – e. g. , by XML files. Solution • Services are configurable. Problem – You write the business logic, – The framework handles everything else. Overview • Enable large-scale, multi-tier application development. • Provide services attachable to business logic. • The (unreached) ideal:

Programming a Banking Application Set of services is pre-defined and not in J 2

Programming a Banking Application Set of services is pre-defined and not in J 2 EE extensible. Overview Problem Solution More Results class Account. Bean { • So (e. g. ) logging remains tangled and scattered. void transfer. To(Account other, int amount) { Log. log("Attempting transfer"); LOGGING if (get. Balance() < amount) BUSINESS throw new Overdraft. Exception(); LOGIC set. Balance(get. Balance() – amount); Not trivial to use. other. set. Balance(other. get. Balance() + amount); • e. g. , can't simply access the field balance. Log. log("Transfer • Several supportcompleted"); class required (not shown) – } home, interface, etc. <ejb-jar> … • Somewhat easier with. Persistence, v 5. transactions, security: <enterprise-beans> services, configured using XML files. <entity> Services are<ejb-name>Account</ejb-name> not programmable. <home>come. acme. Account. Home</home> • Need a different security model? No can do. <remote>com. acme. Account</remote> • Can't control how persistence logs operations. <ejb-class>com. acme. Account. Bean</ejb-class> <persistence-type>Container</persistence-type> …

Aspect-Oriented Programming To The Rescue! Problem P O A Solution More Results – Decompose

Aspect-Oriented Programming To The Rescue! Problem P O A Solution More Results – Decompose the system into distinct aspects (code modules). – Develop each aspect independently. – The aspects are then woven into a complete system. – Chief example: Aspect. J Overview • The new kid in town: a buzzword and a panacea solution to tangled and scattered code:

Decomposition and Weaving Problem Program requirements Executable Overview Clearly distinct concerns (conceptual process) Aspect

Decomposition and Weaving Problem Program requirements Executable Overview Clearly distinct concerns (conceptual process) Aspect Weaving (mechanical process) Solution Aspectual Decomposition More Results

Programming a Banking Application with AOP Very extensible. Problem Solution More Results User user

Programming a Banking Application with AOP Very extensible. Problem Solution More Results User user = Security. get. Context(). get. Current. User(); defined as Aspects aspect Logging { ifbefore (!user. can. Access. Account(this)) execution of public methods in Account { throw new Security. Exception(); Log. log("Began " + method. Name); } } } after successful execution of same { Log. log(method. Name + " ended successfully"); } Reusable configurable. after failed and execution of same { • Log. log(method. Name e. g. , the same logging aspect can be used for many "classes. + " caused exception: + e); … Overview • Define new aspects as you deem fitting. class Account { void transfer. To(Account other, int amount) { if (balance < amount) BUSINESS new Overdraft. Exception(); Highlythrow programmable. LOGIC this. balance amount; • Not just a pre-defined –= set of code transformations. other. balance += amount; } aspect Security { … before execution of any public method in Account { Everything else:

The Problem with Aspects More Results – Can't handle large enterprise applications. Solution •

The Problem with Aspects More Results – Can't handle large enterprise applications. Solution • Worse, aspects do not scale. Problem – A "paradigm mismatch" between AOP and OOP. Overview • Aspects are very similar to inheritance in that they create variations on existing code. • However, there is a schism between aspects and inheritance.

Aspects as Class Modifiers • Unclear: How may an aspect modify the type? –

Aspects as Class Modifiers • Unclear: How may an aspect modify the type? – Can it remove members? – Can it change method signatures? • Unclear: Does an aspect modify subclasses, too? Solution More Results – Does a subclass inherit from the modified version of the class, or from the original one? – Does an advice applied to "before execution of method m()" apply to execution of overridden versions of m, too? Problem – Can it require additional constructor parameters? – Insert code before super()? Overview • Unclear: How may an aspect modify the instance creation mechanisms?

Scalability? • Versatility • Configurability Solution More Results – AOP: Precedence problems with multiple

Scalability? • Versatility • Configurability Solution More Results – AOP: Precedence problems with multiple aspects. – Enterprise apps: Order matters – and should not be set globally. Problem • Plus, different modifications of same base class required by different parts of the program. Overview – AOP: Aspect application is destructive. – Enterprise apps: Legacy code must not be broken.

Manageability? • Granularity Solution More Results – AOP: Class is oblivious to aspects that

Manageability? • Granularity Solution More Results – AOP: Class is oblivious to aspects that modify it – Enterprise apps: Need to know what aspects apply to a given class Problem • Seeing the Big Picture Overview – AOP: An aspect may apply to any class! – Enterprise apps: Selective application required.

Aspects Do Not Scale • The Aspect. J philosophy: Overview – Throw in all

Aspects Do Not Scale • The Aspect. J philosophy: Overview – Throw in all program modules (classes, aspects). – Let the compiler do the mixing. Problem Solution More Results

The Solution

The Solution

Shakeins Problem Solution – No paradigm mismatch… Overview • The basic principle: Use OOP

Shakeins Problem Solution – No paradigm mismatch… Overview • The basic principle: Use OOP to implement AOP. • Use the existing inheritance mechanism to implement class modifications. • Suddenly, all the problems disappear. More Results

What is a Shakein? Solution • A parameterized, generic-like structure. Problem – We get

What is a Shakein? Solution • A parameterized, generic-like structure. Problem – We get a new implementation of an existing type. – The old implementation continues to exist! Overview • A Shakein makes a re-implementation of a class. • It does not change the type. More Results

Shakeins as “Reimplements” Operators A class in OOP is: Simple subclassing: 1. A type

Shakeins as “Reimplements” Operators A class in OOP is: Simple subclassing: 1. A type declaration C p; 2. Template for object creation (constructor, field layout etc. ) p = new C(); 3. An implementation p. m(); 1. Creates a subtype by adding more functions to the protocol. 2. Extends the structure definition by adding more fields. – Cannot declare variables of type C’ More Results 2. May have additional fields. 3. May have a modified behavior. Solution 1. C’ has the same type as C. Problem Given a class C, shakein S, the application C’=S[p 1, …, pn]<C> is a new class such that Overview 3. Modifies the behavior by replacement and refinement

Aren't These Just Mixins? • A mixin takes a class parameter and generates a

Aren't These Just Mixins? • A mixin takes a class parameter and generates a subclass. – Unparameterized (except for the superclass). More Results • Can't include instructions to "add security tests to every public method". Solution – Create a new type. – Must be highly aware of the superclass. Problem • However, unlike shakeins, mixins: Overview – M<C> extends C. – Encapsulates the "delta" between layers of inheritance.

Shakein Example Note: not "public methods in Account" Implicit type parameter ("<T>") Solution More

Shakein Example Note: not "public methods in Account" Implicit type parameter ("<T>") Solution More Results after failed execution of same { Log. log(method. Name + " caused exception: " + e); … Problem after successful execution of same { Log. log(method. Name + " ended successfully"); } Overview shakein Logging { before execution of public methods { Log. log("Began " + method. Name); }

Using a Shakein • Account accnt = new Logging<Account>(); Problem Solution – Shakeins do

Using a Shakein • Account accnt = new Logging<Account>(); Problem Solution – Shakeins do not define new types, only new implementations! Overview • The shakein application is explicit. • The variable type is the (original) type. More Results

Applying a Shakein to a Class Hierarchy Type C 1 C 1’ Type C

Applying a Shakein to a Class Hierarchy Type C 1 C 1’ Type C 3 C 2’ C 4’ No inheritance relationship between the re-implementations Since no new types are defined, this does not disturb polymorphism! More Results C 4 C 3’ Solution Type C 4 C 3 Problem C 2 Overview Type C 2

Shakeins Do Scale Solution More Results • Explicit and flexible ordering – you can

Shakeins Do Scale Solution More Results • Explicit and flexible ordering – you can have Logging<Secure<Account>>, or Secure<Logging<Account>>, or both. Problem – If the changes are desired in existing code, only instance creation points have to be changed. – See our work on factories… Overview • Explicit application – no undesired classes are matched, ever. • Original class still exists – existing code is not broken.

Parameterization Solution More Results … Account a = new Logging["a. log"]<Account>(); Account b =

Parameterization Solution More Results … Account a = new Logging["a. log"]<Account>(); Account b = new Logging["b. log"]<Account>(); Problem shakein Logging[String filename] { before execution of public methods { Log. log(filename, "Began " + method. Name); } after successful execution of same { Log. log(filename, method. Name + " ended"); } Overview • What if we want different instances of Account to log into different log files? • With aspects – though luck. • With shakeins – just add a parameter to the shakein:

Repeated Applications • We can even apply the same shakein more than once to

Repeated Applications • We can even apply the same shakein more than once to the same class. • Example: More Results Log of operations before security tests. Solution Log["pre"]<Secure<Log["post"]<Account>>>() Problem Log of operations after security tests. Overview – Possibly with different parameters.

Pointcut Parameters • Shakeins support pointcut parameters. Solution More Results shakein Secure[pointcut p, String

Pointcut Parameters • Shakeins support pointcut parameters. Solution More Results shakein Secure[pointcut p, String role] { before p { Security. Context(). require. Role(role); } } Problem – Examples: "execution of public methods", "read access of field f", etc. Overview • A "pointcut" is the expression that specifies where the aspect/shakein code ("advice") should be injected.

Pointcut Parameters + Repeated Application Secure[Pt, "teller"]< Secure[Pc, "client"]<Account>> More Results – (client operations)

Pointcut Parameters + Repeated Application Secure[Pt, "teller"]< Secure[Pc, "client"]<Account>> More Results – (client operations) Solution • Pc = execution of transfer. To || withdraw Problem – (teller-only operations) Overview • Pt = execution of create. New || change. Owner

Shakein Composition shakein Std. Persistence = Transactional ○ Persistent; Overview Problem Solution shakein My.

Shakein Composition shakein Std. Persistence = Transactional ○ Persistent; Overview Problem Solution shakein My. Secure = Secure[Pt, "teller"] ○ Secure[Pc, "client"]; More Results

Other Middleware AOP Solutions • JBoss AOP: Extension to the JBoss opensource J 2

Other Middleware AOP Solutions • JBoss AOP: Extension to the JBoss opensource J 2 EE server. Solution More Results – Works using interceptors. – Pointcuts evaluated at runtime. Problem • Spring AOP: Open-source "lightweight" middleware framework. Overview – Works by bytecode manipulation. – Supports runtime application/removal of aspects. – Susceptible to runtime failure if not configured properly.

Feature Comparison Pointcut parameters Untouched Patched Untouched Class/type separation Join points supported Most of

Feature Comparison Pointcut parameters Untouched Patched Untouched Class/type separation Join points supported Most of Aspect. J's All of Aspect. J's Method execution only Weaving mechanism Ahead-of-time Subclassing Patching classes at load-time Runtime proxy generation Repeated application Original class More Results Explicit, local ordering Parameterization Solution Spring Problem JBoss AOP Overview Shakeins

Performance Comparison Problem Solution More Results – Classic example of repeated, parameterized application. –

Performance Comparison Problem Solution More Results – Classic example of repeated, parameterized application. – Code in all 3 versions optimized for repeated application (no code duplication) rather than performance. Overview • Given a class Point, apply aspects (shakeins) to confine the valid range of values for x and y.

How Do You Take Your Aspects? Shaken, not stirred. Overview Problem Solution More Results

How Do You Take Your Aspects? Shaken, not stirred. Overview Problem Solution More Results

Additional Results

Additional Results

Aspect. J 2 EE Secure[Pt, "teller"]<Secure[Pc, "client"]<Account>> Problem – No expressions like Overview •

Aspect. J 2 EE Secure[Pt, "teller"]<Secure[Pc, "client"]<Account>> Problem – No expressions like Overview • An integration of the shakein concept into existing J 2 EE frameworks and applications. • Each service defined as a shakein. • Shakein application managed by XML configuration files. appear in the code. Solution More Results • J 2 EE Home objects ensure that all instances are created with shakeins applied. • Deploy-time weaving.

JTL: The Java Tools Language • Joint research with Itay Maman and Evelina Zarivach.

JTL: The Java Tools Language • Joint research with Itay Maman and Evelina Zarivach. Overview Problem Solution More Results • The Aspect. J pointcut-specification sublanguage is generally viewed as insufficient. • JTL is a Datalog-like language for code queries that can (among other things) replace Aspect. J's pointcut sublanguage. • Based on Query-by-Example. • No need for looping constructs. • Rich predefined predicate library.

JTL Examples • Search for float-typed static method: – Regular exp. : static. *float.

JTL Examples • Search for float-typed static method: – Regular exp. : static. *float. *(. *) – Aspect. J: static float *. *(. . ) Overview • Inaccurate. • OK, for this specific use. • Insane. More Results – JTL: static float method Solution . //returns/@type="float" and @modifiers="static" ] Problem – XQuery: /class/method[

JTL Examples • Another query: "any public field in a class that contains no

JTL Examples • Another query: "any public field in a class that contains no setter or getter methods". void 'set[A-Z]? *'(_); -- Given: = the standard getter public library: !void 'get[A-Z]? *'(); Solution More Results field_in_plain_class : = public field, declared_in[C], C { C. members: { no getter; no setter; }; Problem Regular exp. : impossible. Aspect. J: impossible. XQuery: Possible, but… JTL: setter : = public Overview – –

Factories • Remove the need for the Abstract Factory and Factory Method design patterns.

Factories • Remove the need for the Abstract Factory and Factory Method design patterns. Solution More Results – Including: which actual class to instantiate, or if we should use an existing instance. Problem • Ensure all instances are created with shakeins applied – without touching client code. • Constructors only deal with initialization; factories deal with object creation. Overview – Used extensively in middleware frameworks (e. g. , home objects in J 2 EE, Bean Factory in Spring, etc. )

Factories Solution More Results • With existing patterns: if B extends A, and A

Factories Solution More Results • With existing patterns: if B extends A, and A has controlled instantiation via a get. Instance method, what will B. get. Instance() return? • With factories: such static methods are not needed. Problem – The factory S() will manage a single instance. Overview • With existing patterns: if class S is changed to become a singleton, all existing code that calls new S() must be changed to call S. get. Instance(). • With factories, the change is local to S.

Object Evolution • Dynamic reclassification: allowing an object to change its type at runtime.

Object Evolution • Dynamic reclassification: allowing an object to change its type at runtime. • e. g. , State design pattern. Overview – e. g. , prince → frog. – Supported by Smalltalk, several others. – Many real-world uses • Type safety problems… Prince p = new Prince(); if (…) p → Frog(); p. draw. Sword(); // potential runtime type error Problem • Our solution: limit to monotonic changes only. Solution More Results – "Object evolution" -- moving down the inheritance tree. – Prince → king is okay!

Object Evolution Flavors • I-Evolution: Movement down the inheritance tree. – Might fail if

Object Evolution Flavors • I-Evolution: Movement down the inheritance tree. – Might fail if runtime type differs from static type. • S-Evolution: Move by applying a shakein to the runtime type of the object. Solution More Results – Type not changed at all (only the class), so… – Changes can be undone – still monotonic! – Result: shakeins as "dynamic aspects". Problem – No "type mismatch" possible. – Failure even less likely with idempotent mixins. Overview • M-Evolution: Move by applying a mixin to the runtime type of the object.