Thursday, January 25, 2007

Our first Tuna (eduna) blog!

Thanks to the first blogger (outside netlabs:)) that mentions e-duna! .... Of course, maybe he's not the first, but he is the first we found ;).

AspectJ

For some time now, we've been using AspectJ at work for several projects after playing with Spring 1.2 AOP support which was lacking a lot because it used proxies to implement AOP (or CGLIB which carried some other limitations).

It was pretty hard to convince the development team of trying aspects and I had to do it step by step. The main concern was having some code executing without being able to realize what was being executed from looking at the code. So I decided to mix aspects with annotations, and advice only parts of the code explicitly marked with a particular annotation. So if you wanted to use the advice, you just added an annotation, and by looking at the annotation you knew that an aspect was being weaved. Annotations mixed with aspects worked as a neat kind of code reuse which we could use as an alternative to inheritance and composition/delegation.

We used that mechanism to add statistics support to our messaging gateway (a gateway for MMS/SMS from and to different protocols including SMPP, HTTP, web services, MM1, MM7, RMI...) and it was quite successful. You only needed to annotate a method by specifying the type of the stat and it's namespace (the place of the stat in a browseable hierarchy of stats, which could include parameters values, return types, or properties of the annotated method class). We did something similar to check for authorization before executing some method, which also worked OK (even if, nonetheless, we needed additional layers of authorization before and after method authorization).

My next step was to try to implement synchronization using aspects. Our messaging gateway is based on the concept of independent services that share the same lifecycle (started, stopped, reloading, etc.). Most of the lifecycle methods needed to be executed with an exclusive lock (since we want to avoid start and stop from being executed concurrently, and reloading from being executed while handling a request), and the service methods (things like submitting a message) must not be executed when a lifecycle method was executing but could be executed concurrently with other service methods. To achieve this, I considered three alternatives:
  • Write code before and after each lifecycle and service method to synchronize the access. Since the gateway is basically a framework for implementing new services, programmers also needed to ensure to write this code or things could go wrong. This approach required A LOT of duplicate code, and required the framework user to write code at each service method to make sure its services where well behaved.
  • By using inheritance, through a template pattern, so the programmer sub-classed the template class which handled synchronization. This required a new class for each type of possible service (and there are more than a few!), and required an additional method for each template method (the template method wrapper that handled synchronization, and the template method itself).
  • Use aspects.
By using aspects, I could ensure than any class that implemented a given service interface had each of the required methods correctly synchronized, and when a framework user needed to add a new service, he just implemented the interface and didn't have to worry about handling the synchronization issues, reducing the code he had to write (which was the main objective for the framework.... we always want to have a simple as it gets "hello world" example ;)).

The team reception to this approach was not exactly warm. It's currently working OK, but there are some issues with lock escalation that must be taken in account by programmers in some border cases (like calling a lifecycle method from a service method).

Main concerns are that Aspects should not be used when the adviced code NEEDS the aspect to work correctly. While I share this view somewhat, I decided to leave the synchronization aspect because it greatly reduced the code base. I still have my doubts however....

Our first Tuna (eduna) blog!

Thanks to the first blogger (outside netlabs:)) that mentions e-duna! .... Of course, maybe he's not the first, but he is the first we ...