Thursday, April 16, 2015

Scala Future Callback for Apache HTTP Async Client

In a recent project, I needed an asynchronous HTTP client and due to some other requirements, I decided to use the Apache Async HTTP Client. The problem is, that the Async HTTP Client uses Java's Future implementation:
"The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready." [Java Futures]
An example code snippet demonstrates how to send an asynchronous HTTP request. To make a long story short: accessing the result of the Future means we block the current thread. An alternative solution is to use the Apache FutureCallback interface, which also lacks the ability to access the result of the future in a non-blocking way (see example). Hence: the provided functionality does not scale well in highly concurrent environments.

After I discussed the problem with a collegue, he came up with a pretty cool solution that prepares the ground for Scala Futures. The trick is to implement the FutureCallback interface by using a Scala Promise:

class ScalaFutureCallbackImpl[T] extends FutureCallback[T] {
  private val promise: Promise[T] = Promise()


  def cancelled(): Unit = 

     promise.failure(new RuntimeException("cancelled!"))

  def completed(result: T): Unit = promise.success(result)


  def failed(ex: Exception): Unit = promise.failure(ex)


  def getScalaFuture: Future[T] = promise.future
}


Its interesting to see, how perfect the methods from the interface can be mapped to the corresponding Promise methods. The additional method getScalaFuture is necessary to give the caller access to the underlying Scala Future. With the new implementation, we are now able to use the Apache Async HTTP Client in a more convenient way:

val httpclient = HttpAsyncClients.createDefault()
val callback = new ScalaFutureCallbackImpl[HttpResponse]
httpClient.execute(host, request, context, callback)

for {
   httpResponse <- callback.getScalaFuture

}
yield httpResponse

No comments:

Post a Comment