diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/action/ActionFuture.java b/modules/elasticsearch/src/main/java/org/elasticsearch/action/ActionFuture.java index e71c70b4338..fc38fec353d 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/action/ActionFuture.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/action/ActionFuture.java @@ -20,6 +20,7 @@ package org.elasticsearch.action; import org.elasticsearch.ElasticSearchException; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.unit.TimeValue; import java.util.concurrent.Future; @@ -36,6 +37,10 @@ public interface ActionFuture extends Future { * Similar to {@link #get()}, just wrapping the {@link InterruptedException} with * {@link org.elasticsearch.ElasticSearchInterruptedException}, and throwing the actual * cause of the {@link java.util.concurrent.ExecutionException}. + * + *

Note, the actual cause is unwrapped to the actual failure (for example, unwrapped + * from {@link org.elasticsearch.transport.RemoteTransportException}. The root failure is + * still accessible using {@link #getRootFailure()}. */ T actionGet() throws ElasticSearchException; @@ -43,6 +48,10 @@ public interface ActionFuture extends Future { * Similar to {@link #get(long, java.util.concurrent.TimeUnit)}, just wrapping the {@link InterruptedException} with * {@link org.elasticsearch.ElasticSearchInterruptedException}, and throwing the actual * cause of the {@link java.util.concurrent.ExecutionException}. + * + *

Note, the actual cause is unwrapped to the actual failure (for example, unwrapped + * from {@link org.elasticsearch.transport.RemoteTransportException}. The root failure is + * still accessible using {@link #getRootFailure()}. */ T actionGet(String timeout) throws ElasticSearchException; @@ -51,6 +60,10 @@ public interface ActionFuture extends Future { * {@link org.elasticsearch.ElasticSearchInterruptedException}, and throwing the actual * cause of the {@link java.util.concurrent.ExecutionException}. * + *

Note, the actual cause is unwrapped to the actual failure (for example, unwrapped + * from {@link org.elasticsearch.transport.RemoteTransportException}. The root failure is + * still accessible using {@link #getRootFailure()}. + * * @param timeoutMillis Timeout in millis */ T actionGet(long timeoutMillis) throws ElasticSearchException; @@ -59,6 +72,10 @@ public interface ActionFuture extends Future { * Similar to {@link #get(long, java.util.concurrent.TimeUnit)}, just wrapping the {@link InterruptedException} with * {@link org.elasticsearch.ElasticSearchInterruptedException}, and throwing the actual * cause of the {@link java.util.concurrent.ExecutionException}. + * + *

Note, the actual cause is unwrapped to the actual failure (for example, unwrapped + * from {@link org.elasticsearch.transport.RemoteTransportException}. The root failure is + * still accessible using {@link #getRootFailure()}. */ T actionGet(long timeout, TimeUnit unit) throws ElasticSearchException; @@ -66,6 +83,15 @@ public interface ActionFuture extends Future { * Similar to {@link #get(long, java.util.concurrent.TimeUnit)}, just wrapping the {@link InterruptedException} with * {@link org.elasticsearch.ElasticSearchInterruptedException}, and throwing the actual * cause of the {@link java.util.concurrent.ExecutionException}. + * + *

Note, the actual cause is unwrapped to the actual failure (for example, unwrapped + * from {@link org.elasticsearch.transport.RemoteTransportException}. The root failure is + * still accessible using {@link #getRootFailure()}. */ T actionGet(TimeValue timeout) throws ElasticSearchException; + + /** + * The root (possibly) wrapped failure. + */ + @Nullable Throwable getRootFailure(); } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/action/support/AdapterActionFuture.java b/modules/elasticsearch/src/main/java/org/elasticsearch/action/support/AdapterActionFuture.java index a3bf5973289..c5a7debad9f 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/action/support/AdapterActionFuture.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/action/support/AdapterActionFuture.java @@ -37,17 +37,15 @@ import java.util.concurrent.TimeoutException; */ public abstract class AdapterActionFuture extends AbstractFuture implements ActionFuture, ActionListener { + private Throwable rootFailure; + @Override public T actionGet() throws ElasticSearchException { try { return get(); } catch (InterruptedException e) { throw new ElasticSearchInterruptedException(e.getMessage()); } catch (ExecutionException e) { - if (e.getCause() instanceof ElasticSearchException) { - throw (ElasticSearchException) e.getCause(); - } else { - throw new UncategorizedExecutionException("Failed execution", e); - } + throw rethrowExecutionException(e); } } @@ -71,11 +69,20 @@ public abstract class AdapterActionFuture extends AbstractFuture implem } catch (InterruptedException e) { throw new ElasticSearchInterruptedException(e.getMessage()); } catch (ExecutionException e) { - if (e.getCause() instanceof ElasticSearchException) { - throw (ElasticSearchException) e.getCause(); - } else { - throw new UncategorizedExecutionException("Failed execution", e); + throw rethrowExecutionException(e); + } + } + + static ElasticSearchException rethrowExecutionException(ExecutionException e) { + if (e.getCause() instanceof ElasticSearchException) { + ElasticSearchException esEx = (ElasticSearchException) e.getCause(); + Throwable root = esEx.unwrapCause(); + if (root instanceof ElasticSearchException) { + return (ElasticSearchException) root; } + return new UncategorizedExecutionException("Failed execution", root); + } else { + return new UncategorizedExecutionException("Failed execution", e); } } @@ -88,4 +95,8 @@ public abstract class AdapterActionFuture extends AbstractFuture implem } protected abstract T convert(L listenerResponse); + + @Override public Throwable getRootFailure() { + return rootFailure; + } } diff --git a/plugins/lang/groovy/src/main/groovy/org/elasticsearch/groovy/client/action/GActionFuture.java b/plugins/lang/groovy/src/main/groovy/org/elasticsearch/groovy/client/action/GActionFuture.java index 086ad07fe59..a03df5c6e45 100644 --- a/plugins/lang/groovy/src/main/groovy/org/elasticsearch/groovy/client/action/GActionFuture.java +++ b/plugins/lang/groovy/src/main/groovy/org/elasticsearch/groovy/client/action/GActionFuture.java @@ -160,4 +160,8 @@ public class GActionFuture implements ListenableActionFuture, ActionListen @Override public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return future.get(timeout, unit); } + + @Override public Throwable getRootFailure() { + return future.getRootFailure(); + } }