API inconsistency with ActionListener

Hey there!

I was hoping someone can shed some light on a possible ES Java client API

In my current project (in Scala using Twitter Finagle), we're wrapping the
ES Java client so we can expose all client actions via twitter Futures

We wrap our calls to ES in a Promise, and provide an overridden
ActionListener like so:

private def magnet[Request <: ActionRequest[Request], Response <:
ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response,
RequestBuilder]](action: Action[Request, Response, RequestBuilder]):
ActionMagnet[Request, Response] =
new ActionMagnet[Request, Response] {
def execute(javaClient: Client, request: Request) = {
val promise = new Promise[Response]
javaClient.execute(action, request, actionListener(promise))

private def actionListener[A](promise: Promise[A]) = new
ActionListener[A] {
def onResponse(response: A) {

def onFailure(e: Throwable) {


Everything works great for successful responses: onResponse is getting
called and the promise value is getting delivered. When exceptions are
thrown, onFailure is never called, so exceptions bubble out of the client
call forcing us to wrap them in try / catch blocks.

I'm confused about the seeming inconsistency in this API. Digging into the
ES source, I found I would have to make the following change to get the
ActionListener onFailure invokation I wanted:

diff --git
index 9cbd9f5..2e44262 100644

@@ -199,7 +199,8 @@ public class TransportClientNodesService extends
AbstractComponent {
public void execute(NodeListenerCallback
callback, ActionListener listener) throws ElasticSearchException {
ImmutableList nodes = this.nodes;
if (nodes.isEmpty()) {

  •        throw new NoNodeAvailableException();
  •        listener.onFailure(new NoNodeAvailableException());
  •        return;
       int index = randomNodeGenerator.incrementAndGet();
       if (index < 0) {

@@ -213,7 +214,7 @@ public class TransportClientNodesService extends
AbstractComponent {
if (e.unwrapCause() instanceof ConnectTransportException) {
} else {

  •            throw e;
  •            listener.onFailure(e);

Can someone help me get my thinking straight about the ActionListener API?
When is onFailure supposed to be invoked?

Thanks, I'm loving ES so far!

Blake Smith

You received this message because you are subscribed to the Google Groups "elasticsearch" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elasticsearch+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.