Play 2.5 Framework: Why Akka Streams? Why not iteratees?
New streaming API based on Akka Streams
The main theme of Play 2.5 has been moving from Play’s iteratee-based asynchronous IO API to Akka Streams.
At its heart, any time you communicate over the network, or write/read some data to the filesystem, some streaming is involved. In many cases, this streaming is done at a low level, and the framework exposes the materialized values to your application as in-memory messages. This is the case for many Play actions, a body parser converts the request body stream into an object such as a parsed JSON object, which the application consumes, and the returned result body is a JSON object that Play then turns back into a stream.
Traditionally, on the JVM, streaming is done using the blocking InputStream and OutputStream APIs. These APIs require a dedicated thread to use them - when reading, that thread must block and wait for data, when writing, that thread must block and wait for the data to be flushed. An asynchronous framework, such as Play, offers many advantages because it limits the resources it requires by not using blocking APIs such as these. Instead, for streaming, an asynchronous API needs to be used, where the framework is notified that there’s data to read or that data has been written, rather than having to have a thread block and wait for it.
Prior to Play 2.5, Play used Iteratees as this asynchronous streaming mechanism, but now it uses Akka Streams.
Why not iteratees?
Iteratees are a functional approach to handling asynchronous streaming. They are incredibly powerful, while also offering an incredibly small API surface area - the Iteratee API consists of one method, fold, the rest is just helpers built on top of this method. Iteratees also provide a very high degree of safety, as long as your code compiles, it’s very unlikely that you would have any bugs related to the implementation of an iteratee itself, such as concurrency or error handling, most bugs would be in the “business” logic of the iteratee.
While this safety and simplicity is great, the consequence of it was that it has a very steep learning curve. Programming using iteratees requires a shift in thinking from traditional IO handling, and many developers find that the investment required to make this shift is too high for their IO needs. Another disadvantage of iteratees is that they are practically unimplementable in Java, due to their reliance on many high level functional programming features.
Why Akka Streams
Akka streams provides a good balance between safety, simplicity and familiarity. Akka streams intentionally constrains you in what you can do so that you can only do things correctly, but not as much as iteratees do. Conceptually they are much more familiar to most developers, offering both functional and imperative ways of working with them. Akka streams also has a first class Java API, making it simple to implement any streaming requirements in Java that are needed.
Where are Akka streams used?
The places where you will come across Akka streams in your Play applications include:
Streaming response bodies
Request body parsers
Streaming WS client responses
Reactive Streams is a new specification for asynchronous streaming, which is scheduled for inclusion in JDK9, and available as a standalone library for JDK6 and above. In general, it is not an end-user library, rather it is an SPI that streaming libraries can implement in order to integrate with each other. Both Akka streams and iteratees provide a reactive streams SPI implementation. This means, existing iteratees code can easily be used with Play’s new Akka streams support. It also means any other reactive streams implementations can be used in Play.
The future of iteratees
Iteratees still have some use cases where they shine. At current, there is no plan to deprecate or remove them from Play, though they may be moved to a standalone library. Since iteratees provide a reactive streams implementation, they will always be usable in Play.
Please drop me a comment if you like my posts or have any suggestions or comments