software design & development

why use akka on the jvm?

Asynchronous, reactive, cloud native systems on the JVM
timestamp: 2020-03-19T11:45Z

Technologically, my company is conservative, within reason. There’s a good reason for that, being an airline, lots of our hardware (airplanes) and processes (at airports and in the sky) are highly regulated, and require the utmost attention to safety, risk management, and other critical factors. In that, we cannot afford to be cavalier, like move fast and break things Silicon Valley an-app-and-a-backend startups.

For this reason, and many others beside, we still operate our critical systems and integrations targeted to execute on the Java Virtual Machine (OpenJDK for the most part).

Recently, my programming group has been developing micro-services using the akka framework. We also use some Apache Camel to glue endpoints together, especially our many legacy data endpoints running in IBM MQ, JMS, and SOA services (more on this later).

Some might ask, why are we even still using Java at all? The bleeding edge of software development hasn’t been in Java specifically, or even on the JVM in general, for a good decade or more. It is seen as being stodgy, and corporate. It’s the very uncool kid in the programming school. We did trial the use of NodeJS, with at least half-an-eye on the possibility of an all-Javascript implementation. The problem (other than some of the programmers’ reluctance over Javascript) that we encountered was mainly around integrations with much of our legacy environment. In the main our vendors tend to provide SOAP-based XML endpoints. The richness of libraries for Node in this area was nowhere near enough to make up for the loss of the very rich Java-based ecosystem in these types of technologies. That said, we are still (in our group, at least, as I said) going to use NodeJS for REST and GraphQL API endpoints over our MongoDB (Atlas) data storage layer. But for most of core implementation, we’re sticking with the JVM for now.

My other arguments for continuing to use it, I think, centre around two main points.

The first is that this is a familiar technology to corporate management. We’re not a startup. Things like rearchitecting your existing in-house applications, services, and integrations, into a cloud-native, micro-services based, modern architecture makes senior managers wary that they may be just about to waste many millions of dollars on a plaything for software engineers. Even though another goal of this project is also to reduce our Oracle product footprint (and hence, our licensing costs), “Java” (for us, an Open JDK implementation) is by now a familiar and soothing component in the technical landscape; something that managers nowadays rarely understand.

The second argument for using a technology that runs on the JVM, comes from Akka itself. First, Akka is written in Scala, and this gives us an out from Java to a functional language if we desire it, and meanwhile it comes with a fully scoped Java DSL/API. Second, Akka allows us to use a programming paradigm which, while very old, is coupled to another which is very new. By this I mean Akka’s Actor Model, and there’s also Akka’s implementation of Reactive Streams.

However, even more importantly for me, is the way that Akka leverages that base to be able to provide persistent, distributed, stateful services with scale and performance, and with a CQRS architecture. The systems we need to build must integrate a range of message-driven message inputs. These inputs are often ‘partial’ inputs. By converting them into ‘commands,’ which are then processed by stateful singletons in our service cluster into ordered ‘events’, we achieve performant and concurrent processing of message streams without having to resort to delegating state management to the database layer. Events, the result of the command processing, are always ‘write only’. ‘State’ is regenerated simply by replaying the events in their definitive order. This is generally the lie of “stateless” services: actually they are very typically not stateless, it’s just that you’ve delegated the management of state to your database technology. Your service then must implement the management of thing things like consistency and transaction deadlocks (or delegate this to an implementation layer like a transaction manager and deal with the exceptions). That’s why nonces and version numbers in the storage model exist.

There’s a great overview of the way this interacts with cloud-native services architecture from the Akka developers here. As well there is this interview with Jonas BonĂ©r at InfoQ. There’s also an interesting article here, although, note the implementation discussed is on Akka.Net.