HumbleBlogger

Saturday, March 19, 2005

Use AOP to wrap objects
(and solve thorny dependency injection issues)

At first glance Java was supposed to have this garbage collection feature that would cure the common cold and world hunger.

It was soon realized, though, that there are kinds of resources other than memory that require deterministic cleanup. An example is a database which has a license that restricts maximum number of connections. Any Java code that uses db connections needs to deterministically release a db connection as soon as possible in order to maximize the utilization efficiency of this limited resource.

Because this is a reoccurring problem, Java classes that encapsulate such resources tend to provide a close() method, etc., which can be explicitly invoked to deterministically release the underlying resource. (The C# language introduced the IDispose interface and 'using' keyword as features in that language to effect this particular pattern - and works fine for the occasional case where the resource is only used for the lifetime of some local scope of activation.)

Well, relatively new concepts, such as dependency injection (where a framework is in charge of setting references to dependent collaborating objects on behalf of client code that it manages), introduce yet an additional strain on Java programming practice.

If a framework is in charge of providing and setting references to dependent resources, then it will need to be in charge of managing the continuity of these dependent objects. The client code that is managed by the framework should never have to worry with the lifetime availability of the collaborating objects it makes use of or else the whole notion of dependency injection breaks down. (The goal is for client code managed by the framework to solely concentrate on business logic and not unrelated concerns.)

Opinion: Injection in EJB going too far?

So the framework provider could provide a wrapper class for every such dependent object that it has responsibility for injecting. This wrapper code would intercept all method calls such that when invoked there will be an opportunity to reestablish the availability or viability of the wrapped resource (in the event it has gone away or gone bad), and then complete the call transparently to the caller. Effectively there is a proxy object that is intercepting all access to the underlying wrapped object. It is a reference to the proxy that the framework injects into the client code that it manages. The proxy is then responsible for managing its underlying wrapped object.

Implementing such wrappers for complex classes would get tedious very quickly, though. What is needed is a language feature that simplifies wrapping other classes with such pervasive interceptor mechanisms. Perhaps what is needed is something analogous to the C++ ability to create smart pointers via overloading the pointer access operator. Well, one could indeed add a new Java language feature - but in contemporary Java the thing to do would be to use AOP to byte code enhance the public methods and properties of the target class. One would have to specify the pointcut in xml AOP language instead of rely on an AOP annotation because most typically the target classes one wants to wrap are being provided from third parties in the form of .jar libraries (i.e., a database JDBC driver) where there is no access to source code.

The upshot is that this problem is quite solvable and with the advent of AOP it should be straightforward for framework providers to implement. Most frameworks which are providing the feature of dependency injection are now also general purpose AOP frameworks. Hence the tools are already present. Contrary to the linked discussion above, the is no inherent fatal shortcoming to the feature of framework provided dependency injection. The problem issues that were raised are entirely solvable with application of yet more AOP.

2 Comments:

  • While you can use AOP or smart proxies to do this, you have the issue of programmatically knowing when to release the reference to the actual object. The naive implementation would be to aquire-use-release on every method call. Once you decide to hold on to the object, you need to know when to do the release. This is a very difficult thing to solve for most situations.

    By Anonymous Brian Repko, at 4:21 PM  

  • I have a client JMS application that I have devised a wrapper layer for all of the application's JMS access (which is rather extensive in terms of different threads doing different messaging interactions). In this case the wrapper layer is in charge of maintaining connection continuity (when things run long enough on a network flakey stuff will eventually happen).

    Being a .NET client app, the wrapper object supports the IDispose interface. When the application exits, the using statement enveloping the GUI event loop insures that the underlying JMS stuff is closed explicitly.

    But while the app is running the wrapper tries to repair broken connections. It relieves the application code itself from having to deal with that issue and thus provides a great deal of simplification.

    As to when to release pooled resources, LRU strategies and such can be employed.

    I just don't see the rocket science involved in any of this.

    By Blogger rogerv, at 8:27 PM  

Post a Comment

<< Home