1 / 48

Applying Aspect-Oriented Software Development to Middleware Frameworks

Applying Aspect-Oriented Software Development to Middleware Frameworks. Tal Cohen Joint work with Yossi Gil. Research Overview. The problem : simplifying the design, development and modularity of enterprise applications . Huge software programs for banks, government agencies, etc.

desmond
Download Presentation

Applying Aspect-Oriented Software Development to Middleware Frameworks

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

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

  3. Contributions • Shakeins – aspect-like mechanism combining AOP with OOP. • AspectJ2EE – a proof-of-concept design for shakeins in Enterprise Java. • 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 Problem Solution More Results

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

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

  6. shakein "Logging" Shakeins Now with recording black-box! class Logging<Secure<Car>> We also do buses! Overview Problem Interface is still unchanged Solution More Results

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

  8. The Problem

  9. Why Programming a Banking Application is Easy begin::Problem class Account { void transferTo(Account other, int amount) { if (balance < amount) throw new OverdraftException(); this.balance -= amount; other.balance += amount; } … Overview Problem Solution More Results

  10. Why Programming a Banking Application is Not Easy class Account { void transferTo(Account other, int amount) { Log.log("Attempting transfer"); User user = Security.getContext().getCurrentUser(); if (!user.canTransferFrom(this)) Log.securityError(); throw new SecurityException(); Transaction tx = Db.getConnection().beginTransaction(); this.refreshFields(); other.refreshFields(); if (balance < amount) tx.rollback(); throw new OverdraftException(); this.balance -= amount; other.balance += amount; this.updateDb(); other.updateDb(); tx.commit(); Log.log("Transfer completed"); } … LOGGING SECURITY Overview Problem BUSINESS LOGIC Solution PERSISTENCE TRANSACTION MANAGEMENT More Results Non-functional concerns yield tangled and scattered code.

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

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

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

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

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

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

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

  18. Aspects as Class Modifiers • Unclear: How may an aspect modify the type? • Can it remove members? • Can it change method signatures? • Unclear: How may an aspect modify the instance creation mechanisms? • Can it require additional constructor parameters? • Insert code before super()? • Unclear: Does an aspect modify subclasses, too? • 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? Overview Problem Solution More Results

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

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

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

  22. The Solution

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

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

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

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

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

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

  29. Applying a Shakein to a Class Hierarchy Type C1 C1 C1’ Overview Type C2 Type C3 C2 C2’ C3 C3’ Problem Solution Type C4 No inheritance relationship between the re-implementations C4 C4’ More Results Since no new types are defined, this does not disturb polymorphism!

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

  31. Parameterization • 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: Overview Problem shakein Logging[String filename] { before execution of public methods { Log.log(filename, "Began " + methodName); } after successful execution of same { Log.log(filename, methodName + " ended"); } … Solution More Results Account a = new Logging["a.log"]<Account>(); Account b = new Logging["b.log"]<Account>();

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

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

  34. Pointcut Parameters + Repeated Application Secure[Pt, "teller"]< Secure[Pc, "client"]<Account>> • Pt = execution of createNew || changeOwner • (teller-only operations) • Pc = execution of transferTo || withdraw • (client operations) Overview Problem Solution More Results

  35. Shakein Composition shakein StdPersistence = Transactional ○ Persistent; shakein MySecure = Secure[Pt, "teller"] ○ Secure[Pc, "client"]; Overview Problem Solution More Results

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

  37. Feature Comparison Overview Problem Solution More Results

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

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

  40. Additional Results

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

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

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

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

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

  46. Factories • 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.getInstance(). • With factories, the change is local to S. • The factory S() will manage a single instance. • With existing patterns: if B extends A, and A has controlled instantiation via a getInstance method, what will B.getInstance() return? • With factories: such static methods are not needed. Overview Problem Solution More Results

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

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

More Related