Thanks to the most recent Scala Coursera offering and a new addition to my family, I’ve been quite too busy to write any blog posts. Now that I’ve completed the course work sans watching a few remaining videos, I’m ready to roll with akka. Although I had played with it some in the past, this was my first time to solve a non-trivial problem with actors. While working through the exercises something funny dawned on me… I tried to build this library before! Now don’t get me wrong. Mine was really crappy in comparison. Despite its inferiority, I want to share it because I always feel encouraged when I’m thinking the same things as people smarter than me. It is also another example of how I began to lean towards functional programming before my exposure to Scala. First, a little background on the problem I was trying to solve.
While at ADTRAN, I worked on a product which began its life as a J2EE 2.0 application developed by another company in the late 90’s. The application server is deployed on a customer’s own hardware, and the client application has to be installed on each user’s machine. At some point, everyone heard about Al Gore’s invention and we figured our customers would rather not install the client and its updates in favor of a browser-based solution. However given the years of development into the client source, it couldn’t quite be pitched into the trash.
That sets the stage for the need of seamless code reuse. Nuggets of functionality (which I thought were correctly termed services. That had still been all the jazz five or so years ago when I did this. The lingo even shows up in the product description page to this day) needed to be available to the installed client, web server, and any back-end processes. Without any infrastructure in place, functionality was getting duplicated in these three different environments at an alarming rate. Business demands were trumping any acknowledgement of the systemic problem we had in front of us. I can’t sit and watch such madness, so I had to fix it. What I created at that time has several of the features I’ve since discovered in akka, albeit they were far less powerful and well-thought out.
Of greatest importance for my library was a separation of the execution context of the service logic from the caller’s context. The code for the service just needs to execute somewhere at some point in time. It should be up to the caller of the service makes sense to register callbacks and run asynchronously or to run synchronously and block the calling thread until the result is ready. Furthermore, it was expected that often times the service would run on a different process on an entirely different machine when called from the old installed client. I utilized J2EE message-driven beans and stateless session beans to implement the asynchronous and synchronous contexts.
In order to abstract plumbing provided by two different bean types from both the service implementer and service caller, I created two Java interfaces for each end to interact with. First, the service would implement the
ServiceImplementer interface which had a method with signature
Serializable perform(Serializable param). This is equivalent to extending
Actor in akka and implementing the
receive method. It was up to the service to define the parameter object it could accept and the response object(s) (both of which we always called the model) . These are analogous to the messages in akka. The difference is that akka has the substantial benefit of case classes and default immutability afforded by Scala. Furthermore an akka actor is NOT required to respond with a message. The second interface was the
ServiceProvider which the service caller would interact with to register for partial updates, responses, call synchronously, etc. This was the counterpart to akka’s
ActorRef. The implementation of
ServiceProvider navigates the catacombs of J2EE land on behalf of the caller to set up the service for the conversation. My library and akka shared this approach of utilizing the same interface for all actor implementations. I chose this design because I saw the method name as just a part of the serializable model/message getting passed to the service. Thanks to these abstractions in both my services library and akka, testing is a cinch. Every service can be easily mocked out for unit testing without the need for a dependency injection framework. While I had one good way of doing that for my services, there are several options for akka which I plan to expound upon in a future post.
Earlier days of our project struggled with issues related to some stateful session beans in the application. Looking back on it, I’m willing to bet that it wasn’t the statefulness of the beans that was the problem, but perhaps the way they were being used. Nonetheless, this influenced me at the time to completely avoid stateful session beans. This was also convenient because I knew the lifetime of every call to the services. They could always be thrown away once the
perform method returned. Unfortunately this is a huge disadvantage compared to a legit actor system like akka where state can be maintained across multiple messages. I’m not a big fan of using variables to maintain this state (more on this also to come in a later post), but the ability to have state greatly increases the use cases that can be satisfied by actors over the “services” I had designed. With my library, state could be indirectly maintained in the database or perhaps in other vile recesses of the application.
Another huge win for akka over my library is an actor isn’t much heavier than any other object in the JVM. On the other hand, my services had to create a bean and so forth to bear the burden of the work. Furthermore, my service execution context was ALWAYS on the server. This resulted in a large amount of overhead for rather trivial services in the name of reuse. This is also grossly less scalable because all of the work must be done on the single server. With akka, you can have actors executing on any JVM participating in the akka cluster.
One thing I was able to create which I don’t believe akka provides is a quick and dirty web API for each service. I had stitched the service API with our struts-based web application along with some reflection-based libraries to automatically produce an XML or JSON formatted response. I have in mind to do a similar thing for Lift. I’ve been working on a Lift + Angular plugin created by Doug Roper, and it performs some simple JSON rendering to the client. I’ve been running a background thread in my mind regarding how a generic bridge between akka and angular could be built using this library. My vision is that one would create an actor on the server and depend on a service in the angular client, and you’d be all hooked up.
Needless to say, I’m really excited to begin working with akka. I’ve already begun using it in my day job. We’re building a web application on top of a 3rd-party SOAP service, which I only call via my actors. I will be able to experiment with pooling my service proxies, retries in the event of failure, and geographic distribution of my actors. It’s gonna be a lot of fun and is sure to produce some more interesting blog posts.