Browse Source

Expose the ability to cancel async requests in REST high-level client (#45688)

This commits makes all the async methods in the high level client return the `Cancellable` object that the low level client now exposes.

Relates to #45379 
Closes #44802
Jilles van Gurp 6 years ago
parent
commit
ab8049f24e
18 changed files with 1044 additions and 750 deletions
  1. 53 53
      client/rest-high-level/src/main/java/org/elasticsearch/client/CcrClient.java
  2. 14 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java
  3. 33 33
      client/rest-high-level/src/main/java/org/elasticsearch/client/DataFrameClient.java
  4. 8 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/GraphClient.java
  5. 56 38
      client/rest-high-level/src/main/java/org/elasticsearch/client/IndexLifecycleClient.java
  6. 200 133
      client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java
  7. 16 10
      client/rest-high-level/src/main/java/org/elasticsearch/client/IngestClient.java
  8. 20 13
      client/rest-high-level/src/main/java/org/elasticsearch/client/LicenseClient.java
  9. 197 137
      client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java
  10. 4 3
      client/rest-high-level/src/main/java/org/elasticsearch/client/MigrationClient.java
  11. 177 131
      client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
  12. 32 26
      client/rest-high-level/src/main/java/org/elasticsearch/client/RollupClient.java
  13. 120 84
      client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java
  14. 51 31
      client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
  15. 17 12
      client/rest-high-level/src/main/java/org/elasticsearch/client/TasksClient.java
  16. 38 25
      client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherClient.java
  17. 7 5
      client/rest-high-level/src/main/java/org/elasticsearch/client/XPackClient.java
  18. 1 1
      client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java

+ 53 - 53
client/rest-high-level/src/main/java/org/elasticsearch/client/CcrClient.java

@@ -85,15 +85,15 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-put-follow.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putFollowAsync(PutFollowRequest request,
-                               RequestOptions options,
-                               ActionListener<PutFollowResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable putFollowAsync(PutFollowRequest request,
+                                      RequestOptions options,
+                                      ActionListener<PutFollowResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::putFollow,
             options,
@@ -129,15 +129,15 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-pause-follow.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void pauseFollowAsync(PauseFollowRequest request,
-                                 RequestOptions options,
-                                 ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable pauseFollowAsync(PauseFollowRequest request,
+                                        RequestOptions options,
+                                        ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::pauseFollow,
             options,
@@ -172,15 +172,15 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-resume-follow.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void resumeFollowAsync(ResumeFollowRequest request,
-                                  RequestOptions options,
-                                  ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable resumeFollowAsync(ResumeFollowRequest request,
+                                         RequestOptions options,
+                                         ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::resumeFollow,
             options,
@@ -217,15 +217,15 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-unfollow.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void unfollowAsync(UnfollowRequest request,
-                              RequestOptions options,
-                              ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable unfollowAsync(UnfollowRequest request,
+                                     RequestOptions options,
+                                     ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::unfollow,
             options,
@@ -260,15 +260,15 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-forget-follower.html">the docs</a> for more details
      * on the intended usage of this API.
-     *
      * @param request the request
      * @param options the request options (e.g., headers), use {@link RequestOptions#DEFAULT} if the defaults are acceptable.
+     * @return cancellable that may be used to cancel the request
      */
-    public void forgetFollowerAsync(
+    public Cancellable forgetFollowerAsync(
             final ForgetFollowerRequest request,
             final RequestOptions options,
             final ActionListener<BroadcastResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
                 request,
                 CcrRequestConverters::forgetFollower,
                 options,
@@ -303,15 +303,15 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-put-auto-follow-pattern.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putAutoFollowPatternAsync(PutAutoFollowPatternRequest request,
-                                          RequestOptions options,
-                                          ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable putAutoFollowPatternAsync(PutAutoFollowPatternRequest request,
+                                                 RequestOptions options,
+                                                 ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::putAutoFollowPattern,
             options,
@@ -347,15 +347,15 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-delete-auto-follow-pattern.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteAutoFollowPatternAsync(DeleteAutoFollowPatternRequest request,
-                                             RequestOptions options,
-                                             ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable deleteAutoFollowPatternAsync(DeleteAutoFollowPatternRequest request,
+                                                    RequestOptions options,
+                                                    ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::deleteAutoFollowPattern,
             options,
@@ -392,15 +392,15 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-auto-follow-pattern.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getAutoFollowPatternAsync(GetAutoFollowPatternRequest request,
-                                          RequestOptions options,
-                                          ActionListener<GetAutoFollowPatternResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable getAutoFollowPatternAsync(GetAutoFollowPatternRequest request,
+                                                 RequestOptions options,
+                                                 ActionListener<GetAutoFollowPatternResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::getAutoFollowPattern,
             options,
@@ -437,14 +437,14 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-stats.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @return cancellable that may be used to cancel the request
      */
-    public void getCcrStatsAsync(CcrStatsRequest request,
-                                 RequestOptions options,
-                                 ActionListener<CcrStatsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable getCcrStatsAsync(CcrStatsRequest request,
+                                        RequestOptions options,
+                                        ActionListener<CcrStatsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::getCcrStats,
             options,
@@ -481,14 +481,14 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-follow-stats.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @return cancellable that may be used to cancel the request
      */
-    public void getFollowStatsAsync(FollowStatsRequest request,
-                                    RequestOptions options,
-                                    ActionListener<FollowStatsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable getFollowStatsAsync(FollowStatsRequest request,
+                                           RequestOptions options,
+                                           ActionListener<FollowStatsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::getFollowStats,
             options,
@@ -524,14 +524,14 @@ public final class CcrClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-follow-info.html">
      * the docs</a> for more.
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @return cancellable that may be used to cancel the request
      */
-    public void getFollowInfoAsync(FollowInfoRequest request,
-                                   RequestOptions options,
-                                   ActionListener<FollowInfoResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable getFollowInfoAsync(FollowInfoRequest request,
+                                          RequestOptions options,
+                                          ActionListener<FollowInfoResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             CcrRequestConverters::getFollowInfo,
             options,

+ 14 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java

@@ -67,10 +67,12 @@ public final class ClusterClient {
      * @param clusterUpdateSettingsRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putSettingsAsync(ClusterUpdateSettingsRequest clusterUpdateSettingsRequest, RequestOptions options,
-                                 ActionListener<ClusterUpdateSettingsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(clusterUpdateSettingsRequest, ClusterRequestConverters::clusterPutSettings,
+    public Cancellable putSettingsAsync(ClusterUpdateSettingsRequest clusterUpdateSettingsRequest, RequestOptions options,
+                                        ActionListener<ClusterUpdateSettingsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(clusterUpdateSettingsRequest,
+                ClusterRequestConverters::clusterPutSettings,
                 options, ClusterUpdateSettingsResponse::fromXContent, listener, emptySet());
     }
 
@@ -96,10 +98,12 @@ public final class ClusterClient {
      * @param clusterGetSettingsRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getSettingsAsync(ClusterGetSettingsRequest clusterGetSettingsRequest, RequestOptions options,
-                                 ActionListener<ClusterGetSettingsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(clusterGetSettingsRequest, ClusterRequestConverters::clusterGetSettings,
+    public Cancellable getSettingsAsync(ClusterGetSettingsRequest clusterGetSettingsRequest, RequestOptions options,
+                                        ActionListener<ClusterGetSettingsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
+            clusterGetSettingsRequest, ClusterRequestConverters::clusterGetSettings,
             options, ClusterGetSettingsResponse::fromXContent, listener, emptySet());
     }
 
@@ -127,9 +131,11 @@ public final class ClusterClient {
      * @param healthRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void healthAsync(ClusterHealthRequest healthRequest, RequestOptions options, ActionListener<ClusterHealthResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(healthRequest, ClusterRequestConverters::clusterHealth, options,
+    public Cancellable healthAsync(ClusterHealthRequest healthRequest, RequestOptions options,
+                                   ActionListener<ClusterHealthResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(healthRequest, ClusterRequestConverters::clusterHealth, options,
                 ClusterHealthResponse::fromXContent, listener, singleton(RestStatus.REQUEST_TIMEOUT.getStatus()));
     }
 }

+ 33 - 33
client/rest-high-level/src/main/java/org/elasticsearch/client/DataFrameClient.java

@@ -74,15 +74,15 @@ public final class DataFrameClient {
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/put-data-frame-transform.html">
      *     Create data frame transform documentation</a>
-     *
      * @param request The PutDataFrameTransformRequest containing the
      * {@link org.elasticsearch.client.dataframe.transforms.DataFrameTransformConfig}.
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putDataFrameTransformAsync(PutDataFrameTransformRequest request, RequestOptions options,
-                                      ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable putDataFrameTransformAsync(PutDataFrameTransformRequest request, RequestOptions options,
+                                                  ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 DataFrameRequestConverters::putDataFrameTransform,
                 options,
                 AcknowledgedResponse::fromXContent,
@@ -118,16 +118,16 @@ public final class DataFrameClient {
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/update-data-frame-transform.html">
      *     Create data frame transform documentation</a>
-     *
      * @param request The UpdateDataFrameTransformRequest containing the
      * {@link org.elasticsearch.client.dataframe.transforms.DataFrameTransformConfigUpdate}.
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void updateDataFrameTransformAsync(UpdateDataFrameTransformRequest request,
-                                              RequestOptions options,
-                                              ActionListener<UpdateDataFrameTransformResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable updateDataFrameTransformAsync(UpdateDataFrameTransformRequest request,
+                                                     RequestOptions options,
+                                                     ActionListener<UpdateDataFrameTransformResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             DataFrameRequestConverters::updateDataFrameTransform,
             options,
             UpdateDataFrameTransformResponse::fromXContent,
@@ -162,14 +162,14 @@ public final class DataFrameClient {
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/get-data-frame-transform-stats.html">
      *     Get data frame transform stats documentation</a>
-     *
      * @param request Specifies the which transforms to get the stats for
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getDataFrameTransformStatsAsync(GetDataFrameTransformStatsRequest request, RequestOptions options,
-                                           ActionListener<GetDataFrameTransformStatsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getDataFrameTransformStatsAsync(GetDataFrameTransformStatsRequest request, RequestOptions options,
+                                                       ActionListener<GetDataFrameTransformStatsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 DataFrameRequestConverters::getDataFrameTransformStats,
                 options,
                 GetDataFrameTransformStatsResponse::fromXContent,
@@ -204,14 +204,14 @@ public final class DataFrameClient {
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/delete-data-frame-transform.html">
      *     Delete data frame transform documentation</a>
-     *
      * @param request The delete data frame transform request
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteDataFrameTransformAsync(DeleteDataFrameTransformRequest request, RequestOptions options,
-                                              ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteDataFrameTransformAsync(DeleteDataFrameTransformRequest request, RequestOptions options,
+                                                     ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 DataFrameRequestConverters::deleteDataFrameTransform,
                 options,
                 AcknowledgedResponse::fromXContent,
@@ -245,14 +245,14 @@ public final class DataFrameClient {
      * <p>
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/preview-data-frame-transform.html">
      *     Preview data frame transform documentation</a>
-     *
      * @param request The preview data frame transform request
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void previewDataFrameTransformAsync(PreviewDataFrameTransformRequest request, RequestOptions options,
-                                             ActionListener<PreviewDataFrameTransformResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable previewDataFrameTransformAsync(PreviewDataFrameTransformRequest request, RequestOptions options,
+                                                      ActionListener<PreviewDataFrameTransformResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 DataFrameRequestConverters::previewDataFrameTransform,
                 options,
                 PreviewDataFrameTransformResponse::fromXContent,
@@ -287,14 +287,14 @@ public final class DataFrameClient {
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/start-data-frame-transform.html">
      *     Start data frame transform documentation</a>
-     *
      * @param request The start data frame transform request
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void startDataFrameTransformAsync(StartDataFrameTransformRequest request, RequestOptions options,
-                                            ActionListener<StartDataFrameTransformResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable startDataFrameTransformAsync(StartDataFrameTransformRequest request, RequestOptions options,
+                                                    ActionListener<StartDataFrameTransformResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 DataFrameRequestConverters::startDataFrameTransform,
                 options,
                 StartDataFrameTransformResponse::fromXContent,
@@ -329,14 +329,14 @@ public final class DataFrameClient {
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/stop-data-frame-transform.html">
      *     Stop data frame transform documentation</a>
-     *
      * @param request The stop data frame transform request
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void stopDataFrameTransformAsync(StopDataFrameTransformRequest request, RequestOptions options,
-                                            ActionListener<StopDataFrameTransformResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable stopDataFrameTransformAsync(StopDataFrameTransformRequest request, RequestOptions options,
+                                                   ActionListener<StopDataFrameTransformResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 DataFrameRequestConverters::stopDataFrameTransform,
                 options,
                 StopDataFrameTransformResponse::fromXContent,
@@ -371,14 +371,14 @@ public final class DataFrameClient {
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/get-data-frame-transform.html">
      *     Get data frame transform documentation</a>
-     *
      * @param request The get data frame transform request
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getDataFrameTransformAsync(GetDataFrameTransformRequest request, RequestOptions options,
-                                           ActionListener<GetDataFrameTransformResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getDataFrameTransformAsync(GetDataFrameTransformRequest request, RequestOptions options,
+                                                  ActionListener<GetDataFrameTransformResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 DataFrameRequestConverters::getDataFrameTransform,
                 options,
                 GetDataFrameTransformResponse::fromXContent,

+ 8 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/GraphClient.java

@@ -34,7 +34,7 @@ public class GraphClient {
     GraphClient(RestHighLevelClient restHighLevelClient) {
         this.restHighLevelClient = restHighLevelClient;
     }
-    
+
     /**
      * Executes an exploration request using the Graph API.
      *
@@ -52,12 +52,13 @@ public class GraphClient {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/graph-explore-api.html">Graph API
      * on elastic.co</a>.
+     * @return cancellable that may be used to cancel the request
      */
-    public final void exploreAsync(GraphExploreRequest graphExploreRequest,
-                                           RequestOptions options,
-                                           ActionListener<GraphExploreResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(graphExploreRequest, GraphRequestConverters::explore,
+    public final Cancellable exploreAsync(GraphExploreRequest graphExploreRequest,
+                                          RequestOptions options,
+                                          ActionListener<GraphExploreResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(graphExploreRequest, GraphRequestConverters::explore,
             options, GraphExploreResponse::fromXContent, listener, emptySet());
-    }    
-    
+    }
+
 }

+ 56 - 38
client/rest-high-level/src/main/java/org/elasticsearch/client/IndexLifecycleClient.java

@@ -74,10 +74,11 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getLifecyclePolicyAsync(GetLifecyclePolicyRequest request, RequestOptions options,
-                                        ActionListener<GetLifecyclePolicyResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::getLifecyclePolicy, options,
+    public Cancellable getLifecyclePolicyAsync(GetLifecyclePolicyRequest request, RequestOptions options,
+                                               ActionListener<GetLifecyclePolicyResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::getLifecyclePolicy, options,
             GetLifecyclePolicyResponse::fromXContent, listener, emptySet());
     }
 
@@ -103,10 +104,11 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putLifecyclePolicyAsync(PutLifecyclePolicyRequest request, RequestOptions options,
-                                        ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::putLifecyclePolicy, options,
+    public Cancellable putLifecyclePolicyAsync(PutLifecyclePolicyRequest request, RequestOptions options,
+                                               ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::putLifecyclePolicy, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -132,10 +134,12 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteLifecyclePolicyAsync(DeleteLifecyclePolicyRequest request, RequestOptions options,
-                                           ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::deleteLifecyclePolicy, options,
+    public Cancellable deleteLifecyclePolicyAsync(DeleteLifecyclePolicyRequest request, RequestOptions options,
+                                                  ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
+            request, IndexLifecycleRequestConverters::deleteLifecyclePolicy, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -161,10 +165,12 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void removeIndexLifecyclePolicyAsync(RemoveIndexLifecyclePolicyRequest request, RequestOptions options,
-            ActionListener<RemoveIndexLifecyclePolicyResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::removeIndexLifecyclePolicy, options,
+    public Cancellable removeIndexLifecyclePolicyAsync(RemoveIndexLifecyclePolicyRequest request, RequestOptions options,
+                                                       ActionListener<RemoveIndexLifecyclePolicyResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
+            request, IndexLifecycleRequestConverters::removeIndexLifecyclePolicy, options,
                 RemoveIndexLifecyclePolicyResponse::fromXContent, listener, emptySet());
     }
 
@@ -189,9 +195,10 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void startILMAsync(StartILMRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::startILM, options,
+    public Cancellable startILMAsync(StartILMRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::startILM, options,
                 AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -227,14 +234,15 @@ public class IndexLifecycleClient {
      * Asynchronously get the status of index lifecycle management
      * See <a href="https://fix-me-when-we-have-docs.com">
      * the docs</a> for more.
-     *
      * @param request  the request
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void lifecycleManagementStatusAsync(LifecycleManagementStatusRequest request, RequestOptions options,
-                                               ActionListener<LifecycleManagementStatusResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::lifecycleManagementStatus, options,
+    public Cancellable lifecycleManagementStatusAsync(LifecycleManagementStatusRequest request, RequestOptions options,
+                                                      ActionListener<LifecycleManagementStatusResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
+            request, IndexLifecycleRequestConverters::lifecycleManagementStatus, options,
             LifecycleManagementStatusResponse::fromXContent, listener, emptySet());
     }
 
@@ -245,9 +253,10 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void stopILMAsync(StopILMRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::stopILM, options,
+    public Cancellable stopILMAsync(StopILMRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::stopILM, options,
                 AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -272,10 +281,11 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void explainLifecycleAsync(ExplainLifecycleRequest request, RequestOptions options,
-                                      ActionListener<ExplainLifecycleResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::explainLifecycle, options,
+    public Cancellable explainLifecycleAsync(ExplainLifecycleRequest request, RequestOptions options,
+                                             ActionListener<ExplainLifecycleResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::explainLifecycle, options,
                 ExplainLifecycleResponse::fromXContent, listener, emptySet());
     }
 
@@ -300,10 +310,11 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void retryLifecyclePolicyAsync(RetryLifecyclePolicyRequest request, RequestOptions options,
-                                          ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::retryLifecycle, options,
+    public Cancellable retryLifecyclePolicyAsync(RetryLifecyclePolicyRequest request, RequestOptions options,
+                                                 ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::retryLifecycle, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -335,10 +346,11 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getSnapshotLifecyclePolicyAsync(GetSnapshotLifecyclePolicyRequest request, RequestOptions options,
-                                                ActionListener<GetSnapshotLifecyclePolicyResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::getSnapshotLifecyclePolicy,
+    public Cancellable getSnapshotLifecyclePolicyAsync(GetSnapshotLifecyclePolicyRequest request, RequestOptions options,
+                                                       ActionListener<GetSnapshotLifecyclePolicyResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::getSnapshotLifecyclePolicy,
             options, GetSnapshotLifecyclePolicyResponse::fromXContent, listener, emptySet());
     }
 
@@ -370,10 +382,11 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putSnapshotLifecyclePolicyAsync(PutSnapshotLifecyclePolicyRequest request, RequestOptions options,
-                                                ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::putSnapshotLifecyclePolicy,
+    public Cancellable putSnapshotLifecyclePolicyAsync(PutSnapshotLifecyclePolicyRequest request, RequestOptions options,
+                                                       ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::putSnapshotLifecyclePolicy,
             options, AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -405,10 +418,12 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteSnapshotLifecyclePolicyAsync(DeleteSnapshotLifecyclePolicyRequest request, RequestOptions options,
-                                                   ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::deleteSnapshotLifecyclePolicy,
+    public Cancellable deleteSnapshotLifecyclePolicyAsync(DeleteSnapshotLifecyclePolicyRequest request,
+                                          RequestOptions options,ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
+            request, IndexLifecycleRequestConverters::deleteSnapshotLifecyclePolicy,
             options, AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -440,10 +455,13 @@ public class IndexLifecycleClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void executeSnapshotLifecyclePolicyAsync(ExecuteSnapshotLifecyclePolicyRequest request, RequestOptions options,
-                                                    ActionListener<ExecuteSnapshotLifecyclePolicyResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndexLifecycleRequestConverters::executeSnapshotLifecyclePolicy,
+    public Cancellable executeSnapshotLifecyclePolicyAsync(
+        ExecuteSnapshotLifecyclePolicyRequest request, RequestOptions options,
+        ActionListener<ExecuteSnapshotLifecyclePolicyResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
+            request, IndexLifecycleRequestConverters::executeSnapshotLifecyclePolicy,
             options, ExecuteSnapshotLifecyclePolicyResponse::fromXContent, listener, emptySet());
     }
 }

+ 200 - 133
client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java

@@ -108,9 +108,12 @@ public final class IndicesClient {
      * @param deleteIndexRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteAsync(DeleteIndexRequest deleteIndexRequest, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(deleteIndexRequest, IndicesRequestConverters::deleteIndex, options,
+    public Cancellable deleteAsync(DeleteIndexRequest deleteIndexRequest, RequestOptions options,
+                                   ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(deleteIndexRequest,
+            IndicesRequestConverters::deleteIndex, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -136,11 +139,12 @@ public final class IndicesClient {
      * @param createIndexRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void createAsync(CreateIndexRequest createIndexRequest,
-                            RequestOptions options,
-                            ActionListener<CreateIndexResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest, IndicesRequestConverters::createIndex, options,
+    public Cancellable createAsync(CreateIndexRequest createIndexRequest,
+                                   RequestOptions options,
+                                   ActionListener<CreateIndexResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest, IndicesRequestConverters::createIndex, options,
             CreateIndexResponse::fromXContent, listener, emptySet());
     }
 
@@ -177,12 +181,13 @@ public final class IndicesClient {
      * @deprecated This method uses an old request object which still refers to types, a deprecated feature. The
      * method {@link #createAsync(CreateIndexRequest, RequestOptions, ActionListener)} should be used instead,
      * which accepts a new request object.
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void createAsync(org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest,
-                            RequestOptions options,
-                            ActionListener<org.elasticsearch.action.admin.indices.create.CreateIndexResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest,
+    public Cancellable createAsync(org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest,
+                                   RequestOptions options,
+                                   ActionListener<org.elasticsearch.action.admin.indices.create.CreateIndexResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest,
             IndicesRequestConverters::createIndex, options,
             org.elasticsearch.action.admin.indices.create.CreateIndexResponse::fromXContent, listener, emptySet());
     }
@@ -208,10 +213,11 @@ public final class IndicesClient {
      * @param putMappingRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putMappingAsync(PutMappingRequest putMappingRequest, RequestOptions options,
-                                ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, IndicesRequestConverters::putMapping, options,
+    public Cancellable putMappingAsync(PutMappingRequest putMappingRequest, RequestOptions options,
+                                       ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, IndicesRequestConverters::putMapping, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -245,12 +251,13 @@ public final class IndicesClient {
      * @deprecated This method uses an old request object which still refers to types, a deprecated feature. The
      * method {@link #putMappingAsync(PutMappingRequest, RequestOptions, ActionListener)} should be used instead,
      * which accepts a new request object.
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void putMappingAsync(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest,
-                                RequestOptions options,
-                                ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, IndicesRequestConverters::putMapping, options,
+    public Cancellable putMappingAsync(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest,
+                                       RequestOptions options,
+                                       ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, IndicesRequestConverters::putMapping, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -278,10 +285,11 @@ public final class IndicesClient {
      * @param getMappingsRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getMappingAsync(GetMappingsRequest getMappingsRequest, RequestOptions options,
-                                ActionListener<GetMappingsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getMappingsRequest,
+    public Cancellable getMappingAsync(GetMappingsRequest getMappingsRequest, RequestOptions options,
+                                       ActionListener<GetMappingsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getMappingsRequest,
             IndicesRequestConverters::getMappings,
             options,
             GetMappingsResponse::fromXContent,
@@ -324,12 +332,13 @@ public final class IndicesClient {
      * @deprecated This method uses old request and response objects which still refer to types, a deprecated feature.
      * The method {@link #getMapping(GetMappingsRequest, RequestOptions)} should be used instead, which accepts a new
      * request object.
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void getMappingAsync(org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest,
-                                RequestOptions options,
-                                ActionListener<org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getMappingsRequest,
+    public Cancellable getMappingAsync(org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest,
+                                       RequestOptions options,
+                                       ActionListener<org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getMappingsRequest,
             IndicesRequestConverters::getMappings,
             options,
             org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse::fromXContent,
@@ -369,13 +378,17 @@ public final class IndicesClient {
      * @deprecated This method uses old request and response objects which still refer to types, a deprecated feature.
      * The method {@link #getFieldMappingAsync(GetFieldMappingsRequest, RequestOptions, ActionListener)} should be
      * used instead, which accepts a new request object.
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void getFieldMappingAsync(org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest getFieldMappingsRequest,
-            RequestOptions options,
-            ActionListener<org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getFieldMappingsRequest, IndicesRequestConverters::getFieldMapping, options,
-            org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse::fromXContent, listener, emptySet());
+    public Cancellable getFieldMappingAsync(
+        org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest getFieldMappingsRequest,
+        RequestOptions options,
+        ActionListener<org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getFieldMappingsRequest,
+            IndicesRequestConverters::getFieldMapping, options,
+            org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse::fromXContent,
+            listener, emptySet());
     }
 
     /**
@@ -401,10 +414,12 @@ public final class IndicesClient {
      * @param getFieldMappingsRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getFieldMappingAsync(GetFieldMappingsRequest getFieldMappingsRequest,
-            RequestOptions options, ActionListener<GetFieldMappingsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getFieldMappingsRequest, IndicesRequestConverters::getFieldMapping, options,
+    public Cancellable getFieldMappingAsync(GetFieldMappingsRequest getFieldMappingsRequest,
+                                            RequestOptions options, ActionListener<GetFieldMappingsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
+            getFieldMappingsRequest, IndicesRequestConverters::getFieldMapping, options,
             GetFieldMappingsResponse::fromXContent, listener, emptySet());
     }
 
@@ -429,10 +444,12 @@ public final class IndicesClient {
      * @param indicesAliasesRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void updateAliasesAsync(IndicesAliasesRequest indicesAliasesRequest, RequestOptions options,
-                                   ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(indicesAliasesRequest, IndicesRequestConverters::updateAliases, options,
+    public Cancellable updateAliasesAsync(IndicesAliasesRequest indicesAliasesRequest, RequestOptions options,
+                                          ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(indicesAliasesRequest,
+            IndicesRequestConverters::updateAliases, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -457,9 +474,10 @@ public final class IndicesClient {
      * @param openIndexRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void openAsync(OpenIndexRequest openIndexRequest, RequestOptions options, ActionListener<OpenIndexResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(openIndexRequest, IndicesRequestConverters::openIndex, options,
+    public Cancellable openAsync(OpenIndexRequest openIndexRequest, RequestOptions options, ActionListener<OpenIndexResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(openIndexRequest, IndicesRequestConverters::openIndex, options,
                 OpenIndexResponse::fromXContent, listener, emptySet());
     }
 
@@ -484,9 +502,12 @@ public final class IndicesClient {
      * @param closeIndexRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void closeAsync(CloseIndexRequest closeIndexRequest, RequestOptions options, ActionListener<CloseIndexResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(closeIndexRequest, IndicesRequestConverters::closeIndex, options,
+    public Cancellable closeAsync(CloseIndexRequest closeIndexRequest, RequestOptions options,
+                                  ActionListener<CloseIndexResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(closeIndexRequest,
+            IndicesRequestConverters::closeIndex, options,
             CloseIndexResponse::fromXContent, listener, emptySet());
     }
 
@@ -512,9 +533,10 @@ public final class IndicesClient {
      * @param getAliasesRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void existsAliasAsync(GetAliasesRequest getAliasesRequest, RequestOptions options, ActionListener<Boolean> listener) {
-        restHighLevelClient.performRequestAsync(getAliasesRequest, IndicesRequestConverters::existsAlias, options,
+    public Cancellable existsAliasAsync(GetAliasesRequest getAliasesRequest, RequestOptions options, ActionListener<Boolean> listener) {
+        return restHighLevelClient.performRequestAsync(getAliasesRequest, IndicesRequestConverters::existsAlias, options,
                 RestHighLevelClient::convertExistsResponse, listener, emptySet());
     }
 
@@ -537,9 +559,10 @@ public final class IndicesClient {
      * @param refreshRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void refreshAsync(RefreshRequest refreshRequest, RequestOptions options, ActionListener<RefreshResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(refreshRequest, IndicesRequestConverters::refresh, options,
+    public Cancellable refreshAsync(RefreshRequest refreshRequest, RequestOptions options, ActionListener<RefreshResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(refreshRequest, IndicesRequestConverters::refresh, options,
                 RefreshResponse::fromXContent, listener, emptySet());
     }
 
@@ -562,9 +585,10 @@ public final class IndicesClient {
      * @param flushRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void flushAsync(FlushRequest flushRequest, RequestOptions options, ActionListener<FlushResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(flushRequest, IndicesRequestConverters::flush, options,
+    public Cancellable flushAsync(FlushRequest flushRequest, RequestOptions options, ActionListener<FlushResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(flushRequest, IndicesRequestConverters::flush, options,
                 FlushResponse::fromXContent, listener, emptySet());
     }
 
@@ -589,10 +613,11 @@ public final class IndicesClient {
      * @param syncedFlushRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void flushSyncedAsync(SyncedFlushRequest syncedFlushRequest, RequestOptions options,
-                                 ActionListener<SyncedFlushResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(syncedFlushRequest, IndicesRequestConverters::flushSynced, options,
+    public Cancellable flushSyncedAsync(SyncedFlushRequest syncedFlushRequest, RequestOptions options,
+                                        ActionListener<SyncedFlushResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(syncedFlushRequest, IndicesRequestConverters::flushSynced, options,
                 SyncedFlushResponse::fromXContent, listener, emptySet());
     }
 
@@ -617,10 +642,11 @@ public final class IndicesClient {
      * @param getSettingsRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getSettingsAsync(GetSettingsRequest getSettingsRequest, RequestOptions options,
-                                 ActionListener<GetSettingsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getSettingsRequest, IndicesRequestConverters::getSettings, options,
+    public Cancellable getSettingsAsync(GetSettingsRequest getSettingsRequest, RequestOptions options,
+                                        ActionListener<GetSettingsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getSettingsRequest, IndicesRequestConverters::getSettings, options,
             GetSettingsResponse::fromXContent, listener, emptySet());
     }
 
@@ -645,10 +671,11 @@ public final class IndicesClient {
      * @param getIndexRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getAsync(GetIndexRequest getIndexRequest, RequestOptions options,
-                         ActionListener<GetIndexResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getIndexRequest, IndicesRequestConverters::getIndex, options,
+    public Cancellable getAsync(GetIndexRequest getIndexRequest, RequestOptions options,
+                                ActionListener<GetIndexResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getIndexRequest, IndicesRequestConverters::getIndex, options,
             GetIndexResponse::fromXContent, listener, emptySet());
     }
 
@@ -679,11 +706,12 @@ public final class IndicesClient {
      * @param listener the listener to be notified upon request completion
      * @deprecated This method uses an old request object which still refers to types, a deprecated feature. The method
      * {@link #getAsync(GetIndexRequest, RequestOptions, ActionListener)} should be used instead, which accepts a new request object.
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void getAsync(org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest, RequestOptions options,
-            ActionListener<org.elasticsearch.action.admin.indices.get.GetIndexResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getIndexRequest, IndicesRequestConverters::getIndex, options,
+    public Cancellable getAsync(org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest, RequestOptions options,
+                                ActionListener<org.elasticsearch.action.admin.indices.get.GetIndexResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getIndexRequest, IndicesRequestConverters::getIndex, options,
                 org.elasticsearch.action.admin.indices.get.GetIndexResponse::fromXContent, listener, emptySet());
     }
 
@@ -724,10 +752,12 @@ public final class IndicesClient {
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
      * @deprecated use {@link #forcemergeAsync(ForceMergeRequest, RequestOptions, ActionListener)} instead
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void forceMergeAsync(ForceMergeRequest forceMergeRequest, RequestOptions options, ActionListener<ForceMergeResponse> listener) {
-        forcemergeAsync(forceMergeRequest, options, listener);
+    public Cancellable forceMergeAsync(ForceMergeRequest forceMergeRequest, RequestOptions options,
+                                       ActionListener<ForceMergeResponse> listener) {
+        return forcemergeAsync(forceMergeRequest, options, listener);
     }
 
     /**
@@ -737,9 +767,12 @@ public final class IndicesClient {
      * @param forceMergeRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void forcemergeAsync(ForceMergeRequest forceMergeRequest, RequestOptions options, ActionListener<ForceMergeResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(forceMergeRequest, IndicesRequestConverters::forceMerge, options,
+    public Cancellable forcemergeAsync(ForceMergeRequest forceMergeRequest, RequestOptions options,
+                                       ActionListener<ForceMergeResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(forceMergeRequest,
+                IndicesRequestConverters::forceMerge, options,
                 ForceMergeResponse::fromXContent, listener, emptySet());
     }
 
@@ -765,10 +798,12 @@ public final class IndicesClient {
      * @param clearIndicesCacheRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void clearCacheAsync(ClearIndicesCacheRequest clearIndicesCacheRequest, RequestOptions options,
-                                ActionListener<ClearIndicesCacheResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(clearIndicesCacheRequest, IndicesRequestConverters::clearCache, options,
+    public Cancellable clearCacheAsync(ClearIndicesCacheRequest clearIndicesCacheRequest, RequestOptions options,
+                                       ActionListener<ClearIndicesCacheResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(clearIndicesCacheRequest,
+                IndicesRequestConverters::clearCache, options,
                 ClearIndicesCacheResponse::fromXContent, listener, emptySet());
     }
 
@@ -798,9 +833,10 @@ public final class IndicesClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void existsAsync(GetIndexRequest request, RequestOptions options, ActionListener<Boolean> listener) {
-        restHighLevelClient.performRequestAsync(
+    public Cancellable existsAsync(GetIndexRequest request, RequestOptions options, ActionListener<Boolean> listener) {
+        return restHighLevelClient.performRequestAsync(
                 request,
                 IndicesRequestConverters::indicesExist,
                 options,
@@ -841,11 +877,12 @@ public final class IndicesClient {
      * @param listener the listener to be notified upon request completion
      * @deprecated This method uses an old request object which still refers to types, a deprecated feature. The method
      * {@link #existsAsync(GetIndexRequest, RequestOptions, ActionListener)} should be used instead, which accepts a new request object.
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void existsAsync(org.elasticsearch.action.admin.indices.get.GetIndexRequest request, RequestOptions options,
-            ActionListener<Boolean> listener) {
-        restHighLevelClient.performRequestAsync(
+    public Cancellable existsAsync(org.elasticsearch.action.admin.indices.get.GetIndexRequest request, RequestOptions options,
+                                   ActionListener<Boolean> listener) {
+        return restHighLevelClient.performRequestAsync(
                 request,
                 IndicesRequestConverters::indicesExist,
                 options,
@@ -876,9 +913,10 @@ public final class IndicesClient {
      * @param resizeRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void shrinkAsync(ResizeRequest resizeRequest, RequestOptions options, ActionListener<ResizeResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, IndicesRequestConverters::shrink, options,
+    public Cancellable shrinkAsync(ResizeRequest resizeRequest, RequestOptions options, ActionListener<ResizeResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, IndicesRequestConverters::shrink, options,
                 ResizeResponse::fromXContent, listener, emptySet());
     }
 
@@ -903,9 +941,10 @@ public final class IndicesClient {
      * @param resizeRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void splitAsync(ResizeRequest resizeRequest, RequestOptions options, ActionListener<ResizeResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, IndicesRequestConverters::split, options,
+    public Cancellable splitAsync(ResizeRequest resizeRequest, RequestOptions options, ActionListener<ResizeResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, IndicesRequestConverters::split, options,
                 ResizeResponse::fromXContent, listener, emptySet());
     }
 
@@ -930,9 +969,10 @@ public final class IndicesClient {
      * @param resizeRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void cloneAsync(ResizeRequest resizeRequest, RequestOptions options, ActionListener<ResizeResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, IndicesRequestConverters::clone, options,
+    public Cancellable cloneAsync(ResizeRequest resizeRequest, RequestOptions options, ActionListener<ResizeResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, IndicesRequestConverters::clone, options,
             ResizeResponse::fromXContent, listener, emptySet());
     }
 
@@ -957,9 +997,10 @@ public final class IndicesClient {
      * @param rolloverRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void rolloverAsync(RolloverRequest rolloverRequest, RequestOptions options, ActionListener<RolloverResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(rolloverRequest, IndicesRequestConverters::rollover, options,
+    public Cancellable rolloverAsync(RolloverRequest rolloverRequest, RequestOptions options, ActionListener<RolloverResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(rolloverRequest, IndicesRequestConverters::rollover, options,
                 RolloverResponse::fromXContent, listener, emptySet());
     }
 
@@ -995,11 +1036,13 @@ public final class IndicesClient {
      * @deprecated This method uses deprecated request and response objects.
      * The method {@link #rolloverAsync(RolloverRequest, RequestOptions, ActionListener)} should be used instead, which
      * accepts a new request object.
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void rolloverAsync(org.elasticsearch.action.admin.indices.rollover.RolloverRequest rolloverRequest,
-            RequestOptions options, ActionListener<org.elasticsearch.action.admin.indices.rollover.RolloverResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(rolloverRequest, IndicesRequestConverters::rollover, options,
+    public Cancellable rolloverAsync(org.elasticsearch.action.admin.indices.rollover.RolloverRequest rolloverRequest,
+            RequestOptions options,
+            ActionListener<org.elasticsearch.action.admin.indices.rollover.RolloverResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(rolloverRequest, IndicesRequestConverters::rollover, options,
             org.elasticsearch.action.admin.indices.rollover.RolloverResponse::fromXContent, listener, emptySet());
     }
 
@@ -1024,10 +1067,13 @@ public final class IndicesClient {
      * @param getAliasesRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getAliasAsync(GetAliasesRequest getAliasesRequest, RequestOptions options, ActionListener<GetAliasesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getAliasesRequest, IndicesRequestConverters::getAlias, options,
-                GetAliasesResponse::fromXContent, listener, singleton(RestStatus.NOT_FOUND.getStatus()));
+    public Cancellable getAliasAsync(GetAliasesRequest getAliasesRequest, RequestOptions options,
+                                     ActionListener<GetAliasesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getAliasesRequest,
+            IndicesRequestConverters::getAlias, options,
+            GetAliasesResponse::fromXContent, listener, singleton(RestStatus.NOT_FOUND.getStatus()));
     }
 
     /**
@@ -1051,10 +1097,12 @@ public final class IndicesClient {
      * @param updateSettingsRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putSettingsAsync(UpdateSettingsRequest updateSettingsRequest, RequestOptions options,
-                                 ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(updateSettingsRequest, IndicesRequestConverters::indexPutSettings, options,
+    public Cancellable putSettingsAsync(UpdateSettingsRequest updateSettingsRequest, RequestOptions options,
+                                        ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(updateSettingsRequest,
+            IndicesRequestConverters::indexPutSettings, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -1088,11 +1136,14 @@ public final class IndicesClient {
      * @deprecated This old form of request allows types in mappings.
      * Use {@link #putTemplateAsync(PutIndexTemplateRequest, RequestOptions, ActionListener)}
      * instead which introduces a new request object without types.
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void putTemplateAsync(org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putIndexTemplateRequest,
-            RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest, IndicesRequestConverters::putTemplate, options,
+    public Cancellable putTemplateAsync(
+                org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putIndexTemplateRequest,
+                RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest,
+            IndicesRequestConverters::putTemplate, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -1120,10 +1171,12 @@ public final class IndicesClient {
      * @param putIndexTemplateRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putTemplateAsync(PutIndexTemplateRequest putIndexTemplateRequest,
-            RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest, IndicesRequestConverters::putTemplate, options,
+    public Cancellable putTemplateAsync(PutIndexTemplateRequest putIndexTemplateRequest,
+                                        RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest,
+            IndicesRequestConverters::putTemplate, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -1137,8 +1190,10 @@ public final class IndicesClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public ValidateQueryResponse validateQuery(ValidateQueryRequest validateQueryRequest, RequestOptions options) throws IOException {
-        return restHighLevelClient.performRequestAndParseEntity(validateQueryRequest, IndicesRequestConverters::validateQuery, options,
+    public ValidateQueryResponse validateQuery(ValidateQueryRequest validateQueryRequest,
+                                               RequestOptions options) throws IOException {
+        return restHighLevelClient.performRequestAndParseEntity(validateQueryRequest,
+            IndicesRequestConverters::validateQuery, options,
             ValidateQueryResponse::fromXContent, emptySet());
     }
 
@@ -1150,10 +1205,12 @@ public final class IndicesClient {
      * @param validateQueryRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void validateQueryAsync(ValidateQueryRequest validateQueryRequest, RequestOptions options,
-                                   ActionListener<ValidateQueryResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(validateQueryRequest, IndicesRequestConverters::validateQuery, options,
+    public Cancellable validateQueryAsync(ValidateQueryRequest validateQueryRequest, RequestOptions options,
+                                          ActionListener<ValidateQueryResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(validateQueryRequest,
+            IndicesRequestConverters::validateQuery, options,
             ValidateQueryResponse::fromXContent, listener, emptySet());
     }
 
@@ -1174,7 +1231,8 @@ public final class IndicesClient {
             GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(getIndexTemplatesRequest,
             IndicesRequestConverters::getTemplatesWithDocumentTypes,
-            options, org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse::fromXContent, emptySet());
+            options,
+            org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse::fromXContent, emptySet());
     }
 
     /**
@@ -1186,8 +1244,8 @@ public final class IndicesClient {
      * @return the response
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public GetIndexTemplatesResponse getIndexTemplate(GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options)
-                                                  throws IOException {
+    public GetIndexTemplatesResponse getIndexTemplate(GetIndexTemplatesRequest getIndexTemplatesRequest,
+                  RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(getIndexTemplatesRequest,
             IndicesRequestConverters::getTemplates,
             options, GetIndexTemplatesResponse::fromXContent, emptySet());
@@ -1203,13 +1261,16 @@ public final class IndicesClient {
      * @param listener the listener to be notified upon request completion
      * @deprecated This method uses an old response object which still refers to types, a deprecated feature. Use
      * {@link #getIndexTemplateAsync(GetIndexTemplatesRequest, RequestOptions, ActionListener)} instead which returns a new response object
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void getTemplateAsync(GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options,
-                                 ActionListener<org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getIndexTemplatesRequest,
+    public Cancellable getTemplateAsync(GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options,
+            ActionListener<org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getIndexTemplatesRequest,
             IndicesRequestConverters::getTemplatesWithDocumentTypes,
-            options, org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse::fromXContent, listener, emptySet());
+            options,
+            org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse::fromXContent,
+            listener, emptySet());
     }
 
     /**
@@ -1219,10 +1280,11 @@ public final class IndicesClient {
      * @param getIndexTemplatesRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getIndexTemplateAsync(GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options,
-                                 ActionListener<GetIndexTemplatesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getIndexTemplatesRequest,
+    public Cancellable getIndexTemplateAsync(GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options,
+                                             ActionListener<GetIndexTemplatesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getIndexTemplatesRequest,
             IndicesRequestConverters::getTemplates,
             options, GetIndexTemplatesResponse::fromXContent, listener, emptySet());
     }
@@ -1235,24 +1297,26 @@ public final class IndicesClient {
      * @return true if any index templates in the request exist, false otherwise
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
-    public boolean existsTemplate(IndexTemplatesExistRequest indexTemplatesRequest, RequestOptions options) throws IOException {
-        return restHighLevelClient.performRequest(indexTemplatesRequest, IndicesRequestConverters::templatesExist, options,
+    public boolean existsTemplate(IndexTemplatesExistRequest indexTemplatesRequest,
+                                  RequestOptions options) throws IOException {
+        return restHighLevelClient.performRequest(indexTemplatesRequest,
+            IndicesRequestConverters::templatesExist, options,
             RestHighLevelClient::convertExistsResponse, emptySet());
     }
 
     /**
      * Uses the Index Templates API to determine if index templates exist
-     *
      * @param indexTemplatesExistRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion. The listener will be called with the value {@code true}
-     *                 if any index templates in the request exist, false otherwise
+     * @return cancellable that may be used to cancel the request
      */
-    public void existsTemplateAsync(IndexTemplatesExistRequest indexTemplatesExistRequest,
-                                    RequestOptions options,
-                                    ActionListener<Boolean> listener) {
+    public Cancellable existsTemplateAsync(IndexTemplatesExistRequest indexTemplatesExistRequest,
+                                           RequestOptions options,
+                                           ActionListener<Boolean> listener) {
 
-        restHighLevelClient.performRequestAsync(indexTemplatesExistRequest, IndicesRequestConverters::templatesExist, options,
+        return restHighLevelClient.performRequestAsync(indexTemplatesExistRequest,
+            IndicesRequestConverters::templatesExist, options,
             RestHighLevelClient::convertExistsResponse, listener, emptySet());
     }
 
@@ -1273,14 +1337,14 @@ public final class IndicesClient {
      * Asynchronously calls the analyze API
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-analyze.html">Analyze API on elastic.co</a>
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void analyzeAsync(AnalyzeRequest request, RequestOptions options,
-                             ActionListener<AnalyzeResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndicesRequestConverters::analyze, options,
+    public Cancellable analyzeAsync(AnalyzeRequest request, RequestOptions options,
+                                    ActionListener<AnalyzeResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndicesRequestConverters::analyze, options,
             AnalyzeResponse::fromXContent, listener, emptySet());
     }
 
@@ -1297,13 +1361,14 @@ public final class IndicesClient {
 
     /**
      * Asynchronously calls the _freeze API
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void freezeAsync(FreezeIndexRequest request, RequestOptions options, ActionListener<ShardsAcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndicesRequestConverters::freezeIndex, options,
+    public Cancellable freezeAsync(FreezeIndexRequest request, RequestOptions options,
+                                   ActionListener<ShardsAcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndicesRequestConverters::freezeIndex, options,
             ShardsAcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -1320,13 +1385,15 @@ public final class IndicesClient {
 
     /**
      * Asynchronously calls the _unfreeze API
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void unfreezeAsync(UnfreezeIndexRequest request, RequestOptions options, ActionListener<ShardsAcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndicesRequestConverters::unfreezeIndex, options,
+    public Cancellable unfreezeAsync(UnfreezeIndexRequest request, RequestOptions options,
+                                     ActionListener<ShardsAcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
+            IndicesRequestConverters::unfreezeIndex, options,
             ShardsAcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -1348,14 +1415,14 @@ public final class IndicesClient {
      * Asynchronously delete an index template using the Index Templates API
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html"> Index Templates API
      * on elastic.co</a>
-     *
      * @param request  the request
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteTemplateAsync(DeleteIndexTemplateRequest request, RequestOptions options,
-                                    ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndicesRequestConverters::deleteTemplate,
+    public Cancellable deleteTemplateAsync(DeleteIndexTemplateRequest request, RequestOptions options,
+                                           ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndicesRequestConverters::deleteTemplate,
             options, AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -1372,14 +1439,14 @@ public final class IndicesClient {
 
     /**
      * Asynchronously calls the _reload_search_analyzers API
-     *
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void reloadAnalyzersAsync(ReloadAnalyzersRequest request, RequestOptions options,
-            ActionListener<ReloadAnalyzersResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, IndicesRequestConverters::reloadAnalyzers, options,
+    public Cancellable reloadAnalyzersAsync(ReloadAnalyzersRequest request, RequestOptions options,
+                                            ActionListener<ReloadAnalyzersResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, IndicesRequestConverters::reloadAnalyzers, options,
                 ReloadAnalyzersResponse::fromXContent, listener, emptySet());
     }
 }

+ 16 - 10
client/rest-high-level/src/main/java/org/elasticsearch/client/IngestClient.java

@@ -67,9 +67,10 @@ public final class IngestClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putPipelineAsync(PutPipelineRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity( request, IngestRequestConverters::putPipeline, options,
+    public Cancellable putPipelineAsync(PutPipelineRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity( request, IngestRequestConverters::putPipeline, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -94,9 +95,10 @@ public final class IngestClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getPipelineAsync(GetPipelineRequest request, RequestOptions options, ActionListener<GetPipelineResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity( request, IngestRequestConverters::getPipeline, options,
+    public Cancellable getPipelineAsync(GetPipelineRequest request, RequestOptions options, ActionListener<GetPipelineResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity( request, IngestRequestConverters::getPipeline, options,
             GetPipelineResponse::fromXContent, listener, Collections.singleton(404));
     }
 
@@ -123,9 +125,12 @@ public final class IngestClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deletePipelineAsync(DeletePipelineRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity( request, IngestRequestConverters::deletePipeline, options,
+    public Cancellable deletePipelineAsync(DeletePipelineRequest request, RequestOptions options,
+                                           ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity( request,
+            IngestRequestConverters::deletePipeline, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -154,11 +159,12 @@ public final class IngestClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void simulateAsync(SimulatePipelineRequest request,
-                              RequestOptions options,
-                              ActionListener<SimulatePipelineResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity( request, IngestRequestConverters::simulatePipeline, options,
+    public Cancellable simulateAsync(SimulatePipelineRequest request,
+                                     RequestOptions options,
+                                     ActionListener<SimulatePipelineResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity( request, IngestRequestConverters::simulatePipeline, options,
             SimulatePipelineResponse::fromXContent, listener, emptySet());
     }
 }

+ 20 - 13
client/rest-high-level/src/main/java/org/elasticsearch/client/LicenseClient.java

@@ -80,9 +80,10 @@ public final class LicenseClient {
      * Asynchronously updates license for the cluster.
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putLicenseAsync(PutLicenseRequest request, RequestOptions options, ActionListener<PutLicenseResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, LicenseRequestConverters::putLicense, options,
+    public Cancellable putLicenseAsync(PutLicenseRequest request, RequestOptions options, ActionListener<PutLicenseResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, LicenseRequestConverters::putLicense, options,
             PutLicenseResponse::fromXContent, listener, emptySet());
     }
 
@@ -101,9 +102,10 @@ public final class LicenseClient {
      * Asynchronously returns the current license for the cluster cluster.
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getLicenseAsync(GetLicenseRequest request, RequestOptions options, ActionListener<GetLicenseResponse> listener) {
-        restHighLevelClient.performRequestAsync(request, LicenseRequestConverters::getLicense, options,
+    public Cancellable getLicenseAsync(GetLicenseRequest request, RequestOptions options, ActionListener<GetLicenseResponse> listener) {
+        return restHighLevelClient.performRequestAsync(request, LicenseRequestConverters::getLicense, options,
             response -> new GetLicenseResponse(convertResponseToJson(response)), listener, emptySet());
     }
 
@@ -122,9 +124,12 @@ public final class LicenseClient {
      * Asynchronously deletes license from the cluster.
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteLicenseAsync(DeleteLicenseRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, LicenseRequestConverters::deleteLicense, options,
+    public Cancellable deleteLicenseAsync(DeleteLicenseRequest request, RequestOptions options,
+                                          ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
+            LicenseRequestConverters::deleteLicense, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -143,12 +148,13 @@ public final class LicenseClient {
      * Asynchronously starts a trial license on the cluster.
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void startTrialAsync(StartTrialRequest request,
-                                RequestOptions options,
-                                ActionListener<StartTrialResponse> listener) {
+    public Cancellable startTrialAsync(StartTrialRequest request,
+                                       RequestOptions options,
+                                       ActionListener<StartTrialResponse> listener) {
 
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, LicenseRequestConverters::startTrial, options,
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, LicenseRequestConverters::startTrial, options,
             StartTrialResponse::fromXContent, listener, singleton(403));
     }
 
@@ -167,10 +173,11 @@ public final class LicenseClient {
      * Asynchronously initiates an indefinite basic license.
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void startBasicAsync(StartBasicRequest request, RequestOptions options,
-                                ActionListener<StartBasicResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, LicenseRequestConverters::startBasic, options,
+    public Cancellable startBasicAsync(StartBasicRequest request, RequestOptions options,
+                                       ActionListener<StartBasicResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, LicenseRequestConverters::startBasic, options,
             StartBasicResponse::fromXContent, listener, emptySet());
     }
 

+ 197 - 137
client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java

@@ -153,13 +153,13 @@ public final class MachineLearningClient {
      * <p>
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-put-job.html">ML PUT job documentation</a>
-     *
      * @param request  The request containing the {@link org.elasticsearch.client.ml.job.config.Job} settings
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putJobAsync(PutJobRequest request, RequestOptions options, ActionListener<PutJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable putJobAsync(PutJobRequest request, RequestOptions options, ActionListener<PutJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::putJob,
                 options,
                 PutJobResponse::fromXContent,
@@ -192,13 +192,13 @@ public final class MachineLearningClient {
      * <p>
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-job.html">ML GET job documentation</a>
-     *
      * @param request  {@link GetJobRequest} Request containing a list of jobId(s) and additional options
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified with {@link GetJobResponse} upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getJobAsync(GetJobRequest request, RequestOptions options, ActionListener<GetJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getJobAsync(GetJobRequest request, RequestOptions options, ActionListener<GetJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::getJob,
                 options,
                 GetJobResponse::fromXContent,
@@ -231,13 +231,13 @@ public final class MachineLearningClient {
      * <p>
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-job-stats.html">Get job stats docs</a>
-     *
      * @param request  {@link GetJobStatsRequest} Request containing a list of jobId(s) and additional options
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified with {@link GetJobStatsResponse} upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getJobStatsAsync(GetJobStatsRequest request, RequestOptions options, ActionListener<GetJobStatsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getJobStatsAsync(GetJobStatsRequest request, RequestOptions options, ActionListener<GetJobStatsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::getJobStats,
                 options,
                 GetJobStatsResponse::fromXContent,
@@ -272,14 +272,14 @@ public final class MachineLearningClient {
      * For additional info
      * see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-expired-data.html">ML Delete Expired Data
      * documentation</a>
-     *
      * @param request  The request to delete expired ML data
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteExpiredDataAsync(DeleteExpiredDataRequest request, RequestOptions options,
-                               ActionListener<DeleteExpiredDataResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteExpiredDataAsync(DeleteExpiredDataRequest request, RequestOptions options,
+                                              ActionListener<DeleteExpiredDataResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::deleteExpiredData,
             options,
             DeleteExpiredDataResponse::fromXContent,
@@ -313,12 +313,13 @@ public final class MachineLearningClient {
      * For additional info
      * see <a href="http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-job.html">ML Delete Job documentation</a>
      *
-     * @param request  The request to delete the job
+     *  @param request  The request to delete the job
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteJobAsync(DeleteJobRequest request, RequestOptions options, ActionListener<DeleteJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteJobAsync(DeleteJobRequest request, RequestOptions options, ActionListener<DeleteJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::deleteJob,
             options,
             DeleteJobResponse::fromXContent,
@@ -360,9 +361,10 @@ public final class MachineLearningClient {
      * @param request  Request containing job_id and additional optional options
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void openJobAsync(OpenJobRequest request, RequestOptions options, ActionListener<OpenJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable openJobAsync(OpenJobRequest request, RequestOptions options, ActionListener<OpenJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::openJob,
                 options,
                 OpenJobResponse::fromXContent,
@@ -400,9 +402,10 @@ public final class MachineLearningClient {
      * @param request  Request containing job_ids and additional options. See {@link CloseJobRequest}
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void closeJobAsync(CloseJobRequest request, RequestOptions options, ActionListener<CloseJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable closeJobAsync(CloseJobRequest request, RequestOptions options, ActionListener<CloseJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::closeJob,
                 options,
                 CloseJobResponse::fromXContent,
@@ -449,9 +452,10 @@ public final class MachineLearningClient {
      * @param request  The {@link FlushJobRequest} object enclosing the `jobId` and additional request options
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void flushJobAsync(FlushJobRequest request, RequestOptions options, ActionListener<FlushJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable flushJobAsync(FlushJobRequest request, RequestOptions options, ActionListener<FlushJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::flushJob,
                 options,
                 FlushJobResponse::fromXContent,
@@ -489,9 +493,10 @@ public final class MachineLearningClient {
      * @param request  ForecastJobRequest with forecasting options
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void forecastJobAsync(ForecastJobRequest request, RequestOptions options, ActionListener<ForecastJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable forecastJobAsync(ForecastJobRequest request, RequestOptions options, ActionListener<ForecastJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::forecastJob,
                 options,
                 ForecastJobResponse::fromXContent,
@@ -529,9 +534,11 @@ public final class MachineLearningClient {
      * @param request  the {@link DeleteForecastRequest} object enclosing the desired jobId, forecastIDs, and other options
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteForecastAsync(DeleteForecastRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteForecastAsync(DeleteForecastRequest request, RequestOptions options,
+                                           ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::deleteForecast,
                 options,
                 AcknowledgedResponse::fromXContent,
@@ -569,10 +576,11 @@ public final class MachineLearningClient {
      * @param request The request to delete the model snapshot
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteModelSnapshotAsync(DeleteModelSnapshotRequest request, RequestOptions options,
-                                         ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteModelSnapshotAsync(DeleteModelSnapshotRequest request, RequestOptions options,
+                                                ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::deleteModelSnapshot,
             options,
             AcknowledgedResponse::fromXContent,
@@ -610,10 +618,11 @@ public final class MachineLearningClient {
      * @param request The request to revert to a previous model snapshot
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void revertModelSnapshotAsync(RevertModelSnapshotRequest request, RequestOptions options,
-                                         ActionListener<RevertModelSnapshotResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable revertModelSnapshotAsync(RevertModelSnapshotRequest request, RequestOptions options,
+                                                ActionListener<RevertModelSnapshotResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::revertModelSnapshot,
             options,
             RevertModelSnapshotResponse::fromXContent,
@@ -649,9 +658,10 @@ public final class MachineLearningClient {
      * @param request The request containing the {@link org.elasticsearch.client.ml.datafeed.DatafeedConfig} settings
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putDatafeedAsync(PutDatafeedRequest request, RequestOptions options, ActionListener<PutDatafeedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable putDatafeedAsync(PutDatafeedRequest request, RequestOptions options, ActionListener<PutDatafeedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::putDatafeed,
                 options,
                 PutDatafeedResponse::fromXContent,
@@ -689,9 +699,11 @@ public final class MachineLearningClient {
      * @param request The request containing the {@link org.elasticsearch.client.ml.datafeed.DatafeedUpdate} settings
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void updateDatafeedAsync(UpdateDatafeedRequest request, RequestOptions options, ActionListener<PutDatafeedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable updateDatafeedAsync(UpdateDatafeedRequest request, RequestOptions options,
+                                           ActionListener<PutDatafeedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::updateDatafeed,
             options,
             PutDatafeedResponse::fromXContent,
@@ -730,9 +742,11 @@ public final class MachineLearningClient {
      * @param request {@link GetDatafeedRequest} Request containing a list of datafeedId(s) and additional options
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified with {@link GetDatafeedResponse} upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getDatafeedAsync(GetDatafeedRequest request, RequestOptions options, ActionListener<GetDatafeedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getDatafeedAsync(GetDatafeedRequest request, RequestOptions options,
+                                        ActionListener<GetDatafeedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::getDatafeed,
                 options,
                 GetDatafeedResponse::fromXContent,
@@ -770,9 +784,11 @@ public final class MachineLearningClient {
      * @param request The request to delete the datafeed
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteDatafeedAsync(DeleteDatafeedRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteDatafeedAsync(DeleteDatafeedRequest request, RequestOptions options,
+                                           ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::deleteDatafeed,
                 options,
                 AcknowledgedResponse::fromXContent,
@@ -810,9 +826,11 @@ public final class MachineLearningClient {
      * @param request The request to start the datafeed
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void startDatafeedAsync(StartDatafeedRequest request, RequestOptions options, ActionListener<StartDatafeedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable startDatafeedAsync(StartDatafeedRequest request, RequestOptions options,
+                                          ActionListener<StartDatafeedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::startDatafeed,
             options,
             StartDatafeedResponse::fromXContent,
@@ -850,9 +868,11 @@ public final class MachineLearningClient {
      * @param request The request to stop the datafeed
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void stopDatafeedAsync(StopDatafeedRequest request, RequestOptions options, ActionListener<StopDatafeedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable stopDatafeedAsync(StopDatafeedRequest request, RequestOptions options,
+                                         ActionListener<StopDatafeedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::stopDatafeed,
             options,
             StopDatafeedResponse::fromXContent,
@@ -910,11 +930,12 @@ public final class MachineLearningClient {
      * @param request  {@link GetDatafeedStatsRequest} Request containing a list of datafeedId(s) and additional options
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified with {@link GetDatafeedStatsResponse} upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getDatafeedStatsAsync(GetDatafeedStatsRequest request,
-                                      RequestOptions options,
-                                      ActionListener<GetDatafeedStatsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getDatafeedStatsAsync(GetDatafeedStatsRequest request,
+                                             RequestOptions options,
+                                             ActionListener<GetDatafeedStatsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::getDatafeedStats,
             options,
             GetDatafeedStatsResponse::fromXContent,
@@ -932,11 +953,12 @@ public final class MachineLearningClient {
      * @param request The request to preview the datafeed
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void previewDatafeedAsync(PreviewDatafeedRequest request,
-                                     RequestOptions options,
-                                     ActionListener<PreviewDatafeedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable previewDatafeedAsync(PreviewDatafeedRequest request,
+                                            RequestOptions options,
+                                            ActionListener<PreviewDatafeedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::previewDatafeed,
             options,
             PreviewDatafeedResponse::fromXContent,
@@ -972,9 +994,10 @@ public final class MachineLearningClient {
      * @param request  the {@link UpdateJobRequest} object enclosing the desired updates
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void updateJobAsync(UpdateJobRequest request, RequestOptions options, ActionListener<PutJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable updateJobAsync(UpdateJobRequest request, RequestOptions options, ActionListener<PutJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::updateJob,
                 options,
                 PutJobResponse::fromXContent,
@@ -1005,12 +1028,13 @@ public final class MachineLearningClient {
      * For additional info
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-bucket.html">ML GET buckets documentation</a>
      *
-     * @param request  The request
+     *  @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getBucketsAsync(GetBucketsRequest request, RequestOptions options, ActionListener<GetBucketsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getBucketsAsync(GetBucketsRequest request, RequestOptions options, ActionListener<GetBucketsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::getBuckets,
                 options,
                 GetBucketsResponse::fromXContent,
@@ -1047,9 +1071,11 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getCategoriesAsync(GetCategoriesRequest request, RequestOptions options, ActionListener<GetCategoriesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getCategoriesAsync(GetCategoriesRequest request, RequestOptions options,
+                                          ActionListener<GetCategoriesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::getCategories,
                 options,
                 GetCategoriesResponse::fromXContent,
@@ -1086,10 +1112,11 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getModelSnapshotsAsync(GetModelSnapshotsRequest request, RequestOptions options,
-                                       ActionListener<GetModelSnapshotsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getModelSnapshotsAsync(GetModelSnapshotsRequest request, RequestOptions options,
+                                              ActionListener<GetModelSnapshotsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::getModelSnapshots,
             options,
             GetModelSnapshotsResponse::fromXContent,
@@ -1127,10 +1154,11 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void updateModelSnapshotAsync(UpdateModelSnapshotRequest request, RequestOptions options,
-                                       ActionListener<UpdateModelSnapshotResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable updateModelSnapshotAsync(UpdateModelSnapshotRequest request, RequestOptions options,
+                                                ActionListener<UpdateModelSnapshotResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::updateModelSnapshot,
             options,
             UpdateModelSnapshotResponse::fromXContent,
@@ -1166,10 +1194,11 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getOverallBucketsAsync(GetOverallBucketsRequest request, RequestOptions options,
-                                       ActionListener<GetOverallBucketsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getOverallBucketsAsync(GetOverallBucketsRequest request, RequestOptions options,
+                                              ActionListener<GetOverallBucketsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::getOverallBuckets,
                 options,
                 GetOverallBucketsResponse::fromXContent,
@@ -1203,9 +1232,10 @@ public final class MachineLearningClient {
      * @param request  the request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getRecordsAsync(GetRecordsRequest request, RequestOptions options, ActionListener<GetRecordsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getRecordsAsync(GetRecordsRequest request, RequestOptions options, ActionListener<GetRecordsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::getRecords,
                 options,
                 GetRecordsResponse::fromXContent,
@@ -1245,9 +1275,10 @@ public final class MachineLearningClient {
      * @param request  PostDataRequest containing the data to post and some additional options
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void postDataAsync(PostDataRequest request, RequestOptions options, ActionListener<PostDataResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable postDataAsync(PostDataRequest request, RequestOptions options, ActionListener<PostDataResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::postData,
                 options,
                 PostDataResponse::fromXContent,
@@ -1283,9 +1314,11 @@ public final class MachineLearningClient {
      * @param request The calendars request
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getCalendarsAsync(GetCalendarsRequest request, RequestOptions options, ActionListener<GetCalendarsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getCalendarsAsync(GetCalendarsRequest request, RequestOptions options,
+                                         ActionListener<GetCalendarsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::getCalendars,
                 options,
                 GetCalendarsResponse::fromXContent,
@@ -1321,10 +1354,11 @@ public final class MachineLearningClient {
      * @param request  the request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getInfluencersAsync(GetInfluencersRequest request, RequestOptions options,
-                                    ActionListener<GetInfluencersResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getInfluencersAsync(GetInfluencersRequest request, RequestOptions options,
+                                           ActionListener<GetInfluencersResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::getInfluencers,
                 options,
                 GetInfluencersResponse::fromXContent,
@@ -1362,9 +1396,10 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putCalendarAsync(PutCalendarRequest request, RequestOptions options, ActionListener<PutCalendarResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable putCalendarAsync(PutCalendarRequest request, RequestOptions options, ActionListener<PutCalendarResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::putCalendar,
                 options,
                 PutCalendarResponse::fromXContent,
@@ -1402,9 +1437,11 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putCalendarJobAsync(PutCalendarJobRequest request, RequestOptions options, ActionListener<PutCalendarResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable putCalendarJobAsync(PutCalendarJobRequest request, RequestOptions options,
+                                           ActionListener<PutCalendarResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::putCalendarJob,
             options,
             PutCalendarResponse::fromXContent,
@@ -1442,11 +1479,12 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteCalendarJobAsync(DeleteCalendarJobRequest request,
-                                       RequestOptions options,
-                                       ActionListener<PutCalendarResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteCalendarJobAsync(DeleteCalendarJobRequest request,
+                                              RequestOptions options,
+                                              ActionListener<PutCalendarResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::deleteCalendarJob,
             options,
             PutCalendarResponse::fromXContent,
@@ -1484,9 +1522,11 @@ public final class MachineLearningClient {
      * @param request  The request to delete the calendar
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteCalendarAsync(DeleteCalendarRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteCalendarAsync(DeleteCalendarRequest request, RequestOptions options,
+                                           ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
                 MLRequestConverters::deleteCalendar,
                 options,
                 AcknowledgedResponse::fromXContent,
@@ -1524,10 +1564,11 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getCalendarEventsAsync(GetCalendarEventsRequest request, RequestOptions options,
-                                       ActionListener<GetCalendarEventsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getCalendarEventsAsync(GetCalendarEventsRequest request, RequestOptions options,
+                                              ActionListener<GetCalendarEventsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::getCalendarEvents,
             options,
             GetCalendarEventsResponse::fromXContent,
@@ -1565,10 +1606,11 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void postCalendarEventAsync(PostCalendarEventRequest request, RequestOptions options,
-                                       ActionListener<PostCalendarEventResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable postCalendarEventAsync(PostCalendarEventRequest request, RequestOptions options,
+                                              ActionListener<PostCalendarEventResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::postCalendarEvents,
             options,
             PostCalendarEventResponse::fromXContent,
@@ -1606,11 +1648,12 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteCalendarEventAsync(DeleteCalendarEventRequest request,
-                                         RequestOptions options,
-                                         ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteCalendarEventAsync(DeleteCalendarEventRequest request,
+                                                RequestOptions options,
+                                                ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::deleteCalendarEvent,
             options,
             AcknowledgedResponse::fromXContent,
@@ -1646,9 +1689,10 @@ public final class MachineLearningClient {
      * @param request  The request containing the {@link org.elasticsearch.client.ml.job.config.MlFilter} settings
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putFilterAsync(PutFilterRequest request, RequestOptions options, ActionListener<PutFilterResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable putFilterAsync(PutFilterRequest request, RequestOptions options, ActionListener<PutFilterResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::putFilter,
             options,
             PutFilterResponse::fromXContent,
@@ -1684,9 +1728,10 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getFilterAsync(GetFiltersRequest request, RequestOptions options, ActionListener<GetFiltersResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getFilterAsync(GetFiltersRequest request, RequestOptions options, ActionListener<GetFiltersResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::getFilter,
             options,
             GetFiltersResponse::fromXContent,
@@ -1724,9 +1769,10 @@ public final class MachineLearningClient {
      * @param request  The request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void updateFilterAsync(UpdateFilterRequest request, RequestOptions options, ActionListener<PutFilterResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable updateFilterAsync(UpdateFilterRequest request, RequestOptions options, ActionListener<PutFilterResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::updateFilter,
             options,
             PutFilterResponse::fromXContent,
@@ -1764,9 +1810,11 @@ public final class MachineLearningClient {
      * @param request The request to delete the filter
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteFilterAsync(DeleteFilterRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteFilterAsync(DeleteFilterRequest request, RequestOptions options,
+                                         ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::deleteFilter,
             options,
             AcknowledgedResponse::fromXContent,
@@ -1802,9 +1850,10 @@ public final class MachineLearningClient {
      * @param request The request of Machine Learning info
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getMlInfoAsync(MlInfoRequest request, RequestOptions options, ActionListener<MlInfoResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getMlInfoAsync(MlInfoRequest request, RequestOptions options, ActionListener<MlInfoResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::mlInfo,
             options,
             MlInfoResponse::fromXContent,
@@ -1842,10 +1891,11 @@ public final class MachineLearningClient {
      * @param request The find file structure request
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void findFileStructureAsync(FindFileStructureRequest request, RequestOptions options,
-                                       ActionListener<FindFileStructureResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable findFileStructureAsync(FindFileStructureRequest request, RequestOptions options,
+                                              ActionListener<FindFileStructureResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::findFileStructure,
             options,
             FindFileStructureResponse::fromXContent,
@@ -1881,9 +1931,11 @@ public final class MachineLearningClient {
      * @param request The request of Machine Learning info
      * @param options  Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void setUpgradeModeAsync(SetUpgradeModeRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable setUpgradeModeAsync(SetUpgradeModeRequest request, RequestOptions options,
+                                           ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::setUpgradeMode,
             options,
             AcknowledgedResponse::fromXContent,
@@ -1925,10 +1977,11 @@ public final class MachineLearningClient {
      * {@link org.elasticsearch.client.ml.dataframe.DataFrameAnalyticsConfig}
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putDataFrameAnalyticsAsync(PutDataFrameAnalyticsRequest request, RequestOptions options,
-                                           ActionListener<PutDataFrameAnalyticsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable putDataFrameAnalyticsAsync(PutDataFrameAnalyticsRequest request, RequestOptions options,
+                                                  ActionListener<PutDataFrameAnalyticsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::putDataFrameAnalytics,
             options,
             PutDataFrameAnalyticsResponse::fromXContent,
@@ -1967,10 +2020,11 @@ public final class MachineLearningClient {
      * @param request The {@link GetDataFrameAnalyticsRequest}
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getDataFrameAnalyticsAsync(GetDataFrameAnalyticsRequest request, RequestOptions options,
-                                           ActionListener<GetDataFrameAnalyticsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getDataFrameAnalyticsAsync(GetDataFrameAnalyticsRequest request, RequestOptions options,
+                                                  ActionListener<GetDataFrameAnalyticsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::getDataFrameAnalytics,
             options,
             GetDataFrameAnalyticsResponse::fromXContent,
@@ -2008,10 +2062,11 @@ public final class MachineLearningClient {
      * @param request The {@link GetDataFrameAnalyticsStatsRequest}
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getDataFrameAnalyticsStatsAsync(GetDataFrameAnalyticsStatsRequest request, RequestOptions options,
-                                                ActionListener<GetDataFrameAnalyticsStatsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getDataFrameAnalyticsStatsAsync(GetDataFrameAnalyticsStatsRequest request, RequestOptions options,
+                                                       ActionListener<GetDataFrameAnalyticsStatsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::getDataFrameAnalyticsStats,
             options,
             GetDataFrameAnalyticsStatsResponse::fromXContent,
@@ -2047,13 +2102,14 @@ public final class MachineLearningClient {
      * see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/start-dfanalytics.html">
      *     Start Data Frame Analytics documentation</a>
      *
-     * @param request The {@link StartDataFrameAnalyticsRequest}
+     *  @param request The {@link StartDataFrameAnalyticsRequest}
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void startDataFrameAnalyticsAsync(StartDataFrameAnalyticsRequest request, RequestOptions options,
-                                             ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable startDataFrameAnalyticsAsync(StartDataFrameAnalyticsRequest request, RequestOptions options,
+                                                    ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::startDataFrameAnalytics,
             options,
             AcknowledgedResponse::fromXContent,
@@ -2092,10 +2148,11 @@ public final class MachineLearningClient {
      * @param request The {@link StopDataFrameAnalyticsRequest}
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void stopDataFrameAnalyticsAsync(StopDataFrameAnalyticsRequest request, RequestOptions options,
-                                            ActionListener<StopDataFrameAnalyticsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable stopDataFrameAnalyticsAsync(StopDataFrameAnalyticsRequest request, RequestOptions options,
+                                                   ActionListener<StopDataFrameAnalyticsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::stopDataFrameAnalytics,
             options,
             StopDataFrameAnalyticsResponse::fromXContent,
@@ -2134,10 +2191,11 @@ public final class MachineLearningClient {
      * @param request The {@link DeleteDataFrameAnalyticsRequest}
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteDataFrameAnalyticsAsync(DeleteDataFrameAnalyticsRequest request, RequestOptions options,
-                                              ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteDataFrameAnalyticsAsync(DeleteDataFrameAnalyticsRequest request, RequestOptions options,
+                                                     ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::deleteDataFrameAnalytics,
             options,
             AcknowledgedResponse::fromXContent,
@@ -2176,10 +2234,11 @@ public final class MachineLearningClient {
      * @param request The {@link EvaluateDataFrameRequest}
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void evaluateDataFrameAsync(EvaluateDataFrameRequest request, RequestOptions options,
-                                       ActionListener<EvaluateDataFrameResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable evaluateDataFrameAsync(EvaluateDataFrameRequest request, RequestOptions options,
+                                              ActionListener<EvaluateDataFrameResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             MLRequestConverters::evaluateDataFrame,
             options,
             EvaluateDataFrameResponse::fromXContent,
@@ -2219,10 +2278,11 @@ public final class MachineLearningClient {
      * @param request The {@link PutDataFrameAnalyticsRequest}
      * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener Listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void estimateMemoryUsageAsync(PutDataFrameAnalyticsRequest request, RequestOptions options,
-                                         ActionListener<EstimateMemoryUsageResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable estimateMemoryUsageAsync(PutDataFrameAnalyticsRequest request, RequestOptions options,
+                                                ActionListener<EstimateMemoryUsageResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             request,
             MLRequestConverters::estimateMemoryUsage,
             options,

+ 4 - 3
client/rest-high-level/src/main/java/org/elasticsearch/client/MigrationClient.java

@@ -58,10 +58,11 @@ public final class MigrationClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getDeprecationInfoAsync(DeprecationInfoRequest request, RequestOptions options,
-                                        ActionListener<DeprecationInfoResponse> listener)  {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, MigrationRequestConverters::getDeprecationInfo, options,
+    public Cancellable getDeprecationInfoAsync(DeprecationInfoRequest request, RequestOptions options,
+                                               ActionListener<DeprecationInfoResponse> listener)  {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, MigrationRequestConverters::getDeprecationInfo, options,
             DeprecationInfoResponse::fromXContent, listener, Collections.emptySet());
     }
 }

+ 177 - 131
client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java

@@ -498,9 +498,11 @@ public class RestHighLevelClient implements Closeable {
      * @param bulkRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void bulkAsync(BulkRequest bulkRequest, RequestOptions options, ActionListener<BulkResponse> listener) {
-        performRequestAsyncAndParseEntity(bulkRequest, RequestConverters::bulk, options, BulkResponse::fromXContent, listener, emptySet());
+    public final Cancellable bulkAsync(BulkRequest bulkRequest, RequestOptions options, ActionListener<BulkResponse> listener) {
+        return performRequestAsyncAndParseEntity(bulkRequest, RequestConverters::bulk, options,
+            BulkResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -535,9 +537,11 @@ public class RestHighLevelClient implements Closeable {
      * @param reindexRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void reindexAsync(ReindexRequest reindexRequest, RequestOptions options, ActionListener<BulkByScrollResponse> listener) {
-        performRequestAsyncAndParseEntity(
+    public final Cancellable reindexAsync(ReindexRequest reindexRequest, RequestOptions options,
+                                          ActionListener<BulkByScrollResponse> listener) {
+        return performRequestAsyncAndParseEntity(
             reindexRequest, RequestConverters::reindex, options, BulkByScrollResponse::fromXContent, listener, singleton(409)
         );
     }
@@ -563,10 +567,11 @@ public class RestHighLevelClient implements Closeable {
      * @param updateByQueryRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void updateByQueryAsync(UpdateByQueryRequest updateByQueryRequest, RequestOptions options,
-                                         ActionListener<BulkByScrollResponse> listener) {
-        performRequestAsyncAndParseEntity(
+    public final Cancellable updateByQueryAsync(UpdateByQueryRequest updateByQueryRequest, RequestOptions options,
+                                                ActionListener<BulkByScrollResponse> listener) {
+        return performRequestAsyncAndParseEntity(
             updateByQueryRequest, RequestConverters::updateByQuery, options, BulkByScrollResponse::fromXContent, listener, singleton(409)
         );
     }
@@ -592,10 +597,11 @@ public class RestHighLevelClient implements Closeable {
      * @param deleteByQueryRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void deleteByQueryAsync(DeleteByQueryRequest deleteByQueryRequest, RequestOptions options,
-                                         ActionListener<BulkByScrollResponse> listener) {
-        performRequestAsyncAndParseEntity(
+    public final Cancellable deleteByQueryAsync(DeleteByQueryRequest deleteByQueryRequest, RequestOptions options,
+                                                ActionListener<BulkByScrollResponse> listener) {
+        return performRequestAsyncAndParseEntity(
             deleteByQueryRequest, RequestConverters::deleteByQuery, options, BulkByScrollResponse::fromXContent, listener, singleton(409)
         );
     }
@@ -620,10 +626,11 @@ public class RestHighLevelClient implements Closeable {
      * @param rethrottleRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void deleteByQueryRethrottleAsync(RethrottleRequest rethrottleRequest, RequestOptions options,
-            ActionListener<ListTasksResponse> listener) {
-        performRequestAsyncAndParseEntity(rethrottleRequest, RequestConverters::rethrottleDeleteByQuery, options,
+    public final Cancellable deleteByQueryRethrottleAsync(RethrottleRequest rethrottleRequest, RequestOptions options,
+                                                          ActionListener<ListTasksResponse> listener) {
+        return performRequestAsyncAndParseEntity(rethrottleRequest, RequestConverters::rethrottleDeleteByQuery, options,
                 ListTasksResponse::fromXContent, listener, emptySet());
     }
 
@@ -647,10 +654,11 @@ public class RestHighLevelClient implements Closeable {
      * @param rethrottleRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void updateByQueryRethrottleAsync(RethrottleRequest rethrottleRequest, RequestOptions options,
-            ActionListener<ListTasksResponse> listener) {
-        performRequestAsyncAndParseEntity(rethrottleRequest, RequestConverters::rethrottleUpdateByQuery, options,
+    public final Cancellable updateByQueryRethrottleAsync(RethrottleRequest rethrottleRequest, RequestOptions options,
+                                                          ActionListener<ListTasksResponse> listener) {
+        return performRequestAsyncAndParseEntity(rethrottleRequest, RequestConverters::rethrottleUpdateByQuery, options,
                 ListTasksResponse::fromXContent, listener, emptySet());
     }
 
@@ -672,15 +680,15 @@ public class RestHighLevelClient implements Closeable {
      * Executes a reindex rethrottling request.
      * See the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html#docs-reindex-rethrottle">
      * Reindex rethrottling API on elastic.co</a>
-     *
      * @param rethrottleRequest the request
      * @param options           the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener          the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void reindexRethrottleAsync(RethrottleRequest rethrottleRequest, RequestOptions options,
-            ActionListener<ListTasksResponse> listener) {
-        performRequestAsyncAndParseEntity(rethrottleRequest, RequestConverters::rethrottleReindex, options, ListTasksResponse::fromXContent,
-                listener, emptySet());
+    public final Cancellable reindexRethrottleAsync(RethrottleRequest rethrottleRequest, RequestOptions options,
+                                                    ActionListener<ListTasksResponse> listener) {
+        return performRequestAsyncAndParseEntity(rethrottleRequest,
+            RequestConverters::rethrottleReindex, options, ListTasksResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -720,9 +728,10 @@ public class RestHighLevelClient implements Closeable {
      * @param getRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void getAsync(GetRequest getRequest, RequestOptions options, ActionListener<GetResponse> listener) {
-        performRequestAsyncAndParseEntity(getRequest, RequestConverters::get, options, GetResponse::fromXContent, listener,
+    public final Cancellable getAsync(GetRequest getRequest, RequestOptions options, ActionListener<GetResponse> listener) {
+        return performRequestAsyncAndParseEntity(getRequest, RequestConverters::get, options, GetResponse::fromXContent, listener,
                 singleton(404));
     }
 
@@ -759,10 +768,12 @@ public class RestHighLevelClient implements Closeable {
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
      * @deprecated use {@link #mgetAsync(MultiGetRequest, RequestOptions, ActionListener)} instead
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public final void multiGetAsync(MultiGetRequest multiGetRequest, RequestOptions options, ActionListener<MultiGetResponse> listener) {
-        mgetAsync(multiGetRequest, options, listener);
+    public final Cancellable multiGetAsync(MultiGetRequest multiGetRequest, RequestOptions options,
+                                           ActionListener<MultiGetResponse> listener) {
+        return mgetAsync(multiGetRequest, options, listener);
     }
 
     /**
@@ -771,10 +782,12 @@ public class RestHighLevelClient implements Closeable {
      * @param multiGetRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void mgetAsync(MultiGetRequest multiGetRequest, RequestOptions options, ActionListener<MultiGetResponse> listener) {
-        performRequestAsyncAndParseEntity(multiGetRequest, RequestConverters::multiGet, options, MultiGetResponse::fromXContent, listener,
-                singleton(404));
+    public final Cancellable mgetAsync(MultiGetRequest multiGetRequest, RequestOptions options,
+                                       ActionListener<MultiGetResponse> listener) {
+        return performRequestAsyncAndParseEntity(multiGetRequest, RequestConverters::multiGet, options,
+            MultiGetResponse::fromXContent, listener, singleton(404));
     }
 
     /**
@@ -794,9 +807,10 @@ public class RestHighLevelClient implements Closeable {
      * @param getRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void existsAsync(GetRequest getRequest, RequestOptions options, ActionListener<Boolean> listener) {
-        performRequestAsync(getRequest, RequestConverters::exists, options, RestHighLevelClient::convertExistsResponse, listener,
+    public final Cancellable existsAsync(GetRequest getRequest, RequestOptions options, ActionListener<Boolean> listener) {
+        return performRequestAsync(getRequest, RequestConverters::exists, options, RestHighLevelClient::convertExistsResponse, listener,
                 emptySet());
     }
 
@@ -819,10 +833,11 @@ public class RestHighLevelClient implements Closeable {
      * @param getRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void existsSourceAsync(GetRequest getRequest, RequestOptions options, ActionListener<Boolean> listener) {
-        performRequestAsync(getRequest, RequestConverters::sourceExists, options, RestHighLevelClient::convertExistsResponse, listener,
-                emptySet());
+    public final Cancellable existsSourceAsync(GetRequest getRequest, RequestOptions options, ActionListener<Boolean> listener) {
+        return performRequestAsync(getRequest, RequestConverters::sourceExists, options,
+            RestHighLevelClient::convertExistsResponse, listener, emptySet());
     }
 
     /**
@@ -833,7 +848,8 @@ public class RestHighLevelClient implements Closeable {
      * @return the response
      */
     public final IndexResponse index(IndexRequest indexRequest, RequestOptions options) throws IOException {
-        return performRequestAndParseEntity(indexRequest, RequestConverters::index, options, IndexResponse::fromXContent, emptySet());
+        return performRequestAndParseEntity(indexRequest, RequestConverters::index, options,
+            IndexResponse::fromXContent, emptySet());
     }
 
     /**
@@ -842,9 +858,10 @@ public class RestHighLevelClient implements Closeable {
      * @param indexRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void indexAsync(IndexRequest indexRequest, RequestOptions options, ActionListener<IndexResponse> listener) {
-        performRequestAsyncAndParseEntity(indexRequest, RequestConverters::index, options, IndexResponse::fromXContent, listener,
+    public final Cancellable indexAsync(IndexRequest indexRequest, RequestOptions options, ActionListener<IndexResponse> listener) {
+        return performRequestAsyncAndParseEntity(indexRequest, RequestConverters::index, options, IndexResponse::fromXContent, listener,
                 emptySet());
     }
 
@@ -866,9 +883,10 @@ public class RestHighLevelClient implements Closeable {
      * @param countRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void countAsync(CountRequest countRequest, RequestOptions options, ActionListener<CountResponse> listener) {
-        performRequestAsyncAndParseEntity(countRequest, RequestConverters::count,  options,CountResponse::fromXContent,
+    public final Cancellable countAsync(CountRequest countRequest, RequestOptions options, ActionListener<CountResponse> listener) {
+        return performRequestAsyncAndParseEntity(countRequest, RequestConverters::count,  options,CountResponse::fromXContent,
             listener, emptySet());
     }
 
@@ -889,9 +907,10 @@ public class RestHighLevelClient implements Closeable {
      * @param updateRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void updateAsync(UpdateRequest updateRequest, RequestOptions options, ActionListener<UpdateResponse> listener) {
-        performRequestAsyncAndParseEntity(updateRequest, RequestConverters::update, options, UpdateResponse::fromXContent, listener,
+    public final Cancellable updateAsync(UpdateRequest updateRequest, RequestOptions options, ActionListener<UpdateResponse> listener) {
+        return performRequestAsyncAndParseEntity(updateRequest, RequestConverters::update, options, UpdateResponse::fromXContent, listener,
                 emptySet());
     }
 
@@ -913,9 +932,10 @@ public class RestHighLevelClient implements Closeable {
      * @param deleteRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void deleteAsync(DeleteRequest deleteRequest, RequestOptions options, ActionListener<DeleteResponse> listener) {
-        performRequestAsyncAndParseEntity(deleteRequest, RequestConverters::delete, options, DeleteResponse::fromXContent, listener,
+    public final Cancellable deleteAsync(DeleteRequest deleteRequest, RequestOptions options, ActionListener<DeleteResponse> listener) {
+        return performRequestAsyncAndParseEntity(deleteRequest, RequestConverters::delete, options, DeleteResponse::fromXContent, listener,
             Collections.singleton(404));
     }
 
@@ -941,9 +961,10 @@ public class RestHighLevelClient implements Closeable {
      * @param searchRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void searchAsync(SearchRequest searchRequest, RequestOptions options, ActionListener<SearchResponse> listener) {
-        performRequestAsyncAndParseEntity(
+    public final Cancellable searchAsync(SearchRequest searchRequest, RequestOptions options, ActionListener<SearchResponse> listener) {
+        return performRequestAsyncAndParseEntity(
                 searchRequest,
                 r -> RequestConverters.search(r, "_search"),
                 options,
@@ -987,11 +1008,12 @@ public class RestHighLevelClient implements Closeable {
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
      * @deprecated use {@link #msearchAsync(MultiSearchRequest, RequestOptions, ActionListener)} instead
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public final void multiSearchAsync(MultiSearchRequest searchRequest, RequestOptions options,
-                                   ActionListener<MultiSearchResponse> listener) {
-        msearchAsync(searchRequest, options, listener);
+    public final Cancellable multiSearchAsync(MultiSearchRequest searchRequest, RequestOptions options,
+                                              ActionListener<MultiSearchResponse> listener) {
+        return msearchAsync(searchRequest, options, listener);
     }
 
     /**
@@ -1001,10 +1023,11 @@ public class RestHighLevelClient implements Closeable {
      * @param searchRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void msearchAsync(MultiSearchRequest searchRequest, RequestOptions options,
-                                   ActionListener<MultiSearchResponse> listener) {
-        performRequestAsyncAndParseEntity(searchRequest, RequestConverters::multiSearch, options, MultiSearchResponse::fromXContext,
+    public final Cancellable msearchAsync(MultiSearchRequest searchRequest, RequestOptions options,
+                                          ActionListener<MultiSearchResponse> listener) {
+        return performRequestAsyncAndParseEntity(searchRequest, RequestConverters::multiSearch, options, MultiSearchResponse::fromXContext,
                 listener, emptySet());
     }
 
@@ -1046,11 +1069,12 @@ public class RestHighLevelClient implements Closeable {
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
      * @deprecated use {@link #scrollAsync(SearchScrollRequest, RequestOptions, ActionListener)} instead
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public final void searchScrollAsync(SearchScrollRequest searchScrollRequest, RequestOptions options,
-                                  ActionListener<SearchResponse> listener) {
-        scrollAsync(searchScrollRequest, options, listener);
+    public final Cancellable searchScrollAsync(SearchScrollRequest searchScrollRequest, RequestOptions options,
+                                               ActionListener<SearchResponse> listener) {
+        return scrollAsync(searchScrollRequest, options, listener);
     }
 
     /**
@@ -1061,11 +1085,12 @@ public class RestHighLevelClient implements Closeable {
      * @param searchScrollRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void scrollAsync(SearchScrollRequest searchScrollRequest, RequestOptions options,
-                                  ActionListener<SearchResponse> listener) {
-        performRequestAsyncAndParseEntity(searchScrollRequest, RequestConverters::searchScroll, options, SearchResponse::fromXContent,
-                listener, emptySet());
+    public final Cancellable scrollAsync(SearchScrollRequest searchScrollRequest, RequestOptions options,
+                                         ActionListener<SearchResponse> listener) {
+        return performRequestAsyncAndParseEntity(searchScrollRequest, RequestConverters::searchScroll,
+            options, SearchResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -1090,11 +1115,12 @@ public class RestHighLevelClient implements Closeable {
      * @param clearScrollRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void clearScrollAsync(ClearScrollRequest clearScrollRequest, RequestOptions options,
-                                       ActionListener<ClearScrollResponse> listener) {
-        performRequestAsyncAndParseEntity(clearScrollRequest, RequestConverters::clearScroll, options, ClearScrollResponse::fromXContent,
-                listener, emptySet());
+    public final Cancellable clearScrollAsync(ClearScrollRequest clearScrollRequest, RequestOptions options,
+                                              ActionListener<ClearScrollResponse> listener) {
+        return performRequestAsyncAndParseEntity(clearScrollRequest, RequestConverters::clearScroll,
+            options, ClearScrollResponse::fromXContent, listener, emptySet());
     }
 
     /**
@@ -1116,10 +1142,11 @@ public class RestHighLevelClient implements Closeable {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html">Search Template API
      * on elastic.co</a>.
+     * @return cancellable that may be used to cancel the request
      */
-    public final void searchTemplateAsync(SearchTemplateRequest searchTemplateRequest, RequestOptions options,
-                                          ActionListener<SearchTemplateResponse> listener) {
-        performRequestAsyncAndParseEntity(searchTemplateRequest, RequestConverters::searchTemplate, options,
+    public final Cancellable searchTemplateAsync(SearchTemplateRequest searchTemplateRequest, RequestOptions options,
+                                                 ActionListener<SearchTemplateResponse> listener) {
+        return performRequestAsyncAndParseEntity(searchTemplateRequest, RequestConverters::searchTemplate, options,
             SearchTemplateResponse::fromXContent, listener, emptySet());
     }
 
@@ -1147,9 +1174,10 @@ public class RestHighLevelClient implements Closeable {
      * @param explainRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void explainAsync(ExplainRequest explainRequest, RequestOptions options, ActionListener<ExplainResponse> listener) {
-        performRequestAsync(explainRequest, RequestConverters::explain, options,
+    public final Cancellable explainAsync(ExplainRequest explainRequest, RequestOptions options, ActionListener<ExplainResponse> listener) {
+        return performRequestAsync(explainRequest, RequestConverters::explain, options,
             response -> {
                 CheckedFunction<XContentParser, ExplainResponse, IOException> entityParser =
                     parser -> ExplainResponse.fromXContent(parser, convertExistsResponse(response));
@@ -1181,9 +1209,12 @@ public class RestHighLevelClient implements Closeable {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void termvectorsAsync(TermVectorsRequest request, RequestOptions options, ActionListener<TermVectorsResponse> listener) {
-        performRequestAsyncAndParseEntity(request, RequestConverters::termVectors, options, TermVectorsResponse::fromXContent, listener,
+    public final Cancellable termvectorsAsync(TermVectorsRequest request, RequestOptions options,
+                                              ActionListener<TermVectorsResponse> listener) {
+        return performRequestAsyncAndParseEntity(request, RequestConverters::termVectors, options,
+            TermVectorsResponse::fromXContent, listener,
             emptySet());
     }
 
@@ -1211,10 +1242,11 @@ public class RestHighLevelClient implements Closeable {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void mtermvectorsAsync(MultiTermVectorsRequest request, RequestOptions options,
-            ActionListener<MultiTermVectorsResponse> listener) {
-        performRequestAsyncAndParseEntity(
+    public final Cancellable mtermvectorsAsync(MultiTermVectorsRequest request, RequestOptions options,
+                                               ActionListener<MultiTermVectorsResponse> listener) {
+        return performRequestAsyncAndParseEntity(
             request, RequestConverters::mtermVectors, options, MultiTermVectorsResponse::fromXContent, listener, emptySet());
     }
 
@@ -1250,11 +1282,12 @@ public class RestHighLevelClient implements Closeable {
      *
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-search-template.html">Multi Search Template API
      * on elastic.co</a>.
+     * @return cancellable that may be used to cancel the request
      */
-    public final void msearchTemplateAsync(MultiSearchTemplateRequest multiSearchTemplateRequest,
-                                           RequestOptions options,
-                                           ActionListener<MultiSearchTemplateResponse> listener) {
-        performRequestAsyncAndParseEntity(multiSearchTemplateRequest, RequestConverters::multiSearchTemplate,
+    public final Cancellable msearchTemplateAsync(MultiSearchTemplateRequest multiSearchTemplateRequest,
+                                                  RequestOptions options,
+                                                  ActionListener<MultiSearchTemplateResponse> listener) {
+        return performRequestAsyncAndParseEntity(multiSearchTemplateRequest, RequestConverters::multiSearchTemplate,
             options, MultiSearchTemplateResponse::fromXContext, listener, emptySet());
     }
 
@@ -1265,9 +1298,12 @@ public class RestHighLevelClient implements Closeable {
      * @param rankEvalRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void rankEvalAsync(RankEvalRequest rankEvalRequest, RequestOptions options,  ActionListener<RankEvalResponse> listener) {
-        performRequestAsyncAndParseEntity(rankEvalRequest, RequestConverters::rankEval, options,  RankEvalResponse::fromXContent, listener,
+    public final Cancellable rankEvalAsync(RankEvalRequest rankEvalRequest, RequestOptions options,
+                                           ActionListener<RankEvalResponse> listener) {
+        return performRequestAsyncAndParseEntity(rankEvalRequest, RequestConverters::rankEval, options,
+            RankEvalResponse::fromXContent, listener,
                 emptySet());
     }
 
@@ -1305,10 +1341,11 @@ public class RestHighLevelClient implements Closeable {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getScriptAsync(GetStoredScriptRequest request, RequestOptions options,
-                               ActionListener<GetStoredScriptResponse> listener) {
-        performRequestAsyncAndParseEntity(request, RequestConverters::getScript, options,
+    public Cancellable getScriptAsync(GetStoredScriptRequest request, RequestOptions options,
+                                      ActionListener<GetStoredScriptResponse> listener) {
+        return performRequestAsyncAndParseEntity(request, RequestConverters::getScript, options,
             GetStoredScriptResponse::fromXContent, listener, emptySet());
     }
 
@@ -1332,10 +1369,11 @@ public class RestHighLevelClient implements Closeable {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteScriptAsync(DeleteStoredScriptRequest request, RequestOptions options,
-                                  ActionListener<AcknowledgedResponse> listener) {
-        performRequestAsyncAndParseEntity(request, RequestConverters::deleteScript, options,
+    public Cancellable deleteScriptAsync(DeleteStoredScriptRequest request, RequestOptions options,
+                                         ActionListener<AcknowledgedResponse> listener) {
+        return performRequestAsyncAndParseEntity(request, RequestConverters::deleteScript, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -1360,10 +1398,11 @@ public class RestHighLevelClient implements Closeable {
      * @param putStoredScriptRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putScriptAsync(PutStoredScriptRequest putStoredScriptRequest, RequestOptions options,
-                               ActionListener<AcknowledgedResponse> listener) {
-        performRequestAsyncAndParseEntity(putStoredScriptRequest, RequestConverters::putScript, options,
+    public Cancellable putScriptAsync(PutStoredScriptRequest putStoredScriptRequest, RequestOptions options,
+                                      ActionListener<AcknowledgedResponse> listener) {
+        return performRequestAsyncAndParseEntity(putStoredScriptRequest, RequestConverters::putScript, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -1374,10 +1413,11 @@ public class RestHighLevelClient implements Closeable {
      * @param fieldCapabilitiesRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public final void fieldCapsAsync(FieldCapabilitiesRequest fieldCapabilitiesRequest, RequestOptions options,
-                                     ActionListener<FieldCapabilitiesResponse> listener) {
-        performRequestAsyncAndParseEntity(fieldCapabilitiesRequest, RequestConverters::fieldCaps, options,
+    public final Cancellable fieldCapsAsync(FieldCapabilitiesRequest fieldCapabilitiesRequest, RequestOptions options,
+                                            ActionListener<FieldCapabilitiesResponse> listener) {
+        return performRequestAsyncAndParseEntity(fieldCapabilitiesRequest, RequestConverters::fieldCaps, options,
             FieldCapabilitiesResponse::fromXContent, listener, emptySet());
     }
 
@@ -1509,26 +1549,28 @@ public class RestHighLevelClient implements Closeable {
     /**
      * @deprecated If creating a new HLRC ReST API call, consider creating new actions instead of reusing server actions. The Validation
      * layer has been added to the ReST client, and requests should extend {@link Validatable} instead of {@link ActionRequest}.
+     * @return Cancellable instance that may be used to cancel the request
      */
     @Deprecated
-    protected final <Req extends ActionRequest, Resp> void performRequestAsyncAndParseEntity(Req request,
-                                                                         CheckedFunction<Req, Request, IOException> requestConverter,
-                                                                         RequestOptions options,
-                                                                         CheckedFunction<XContentParser, Resp, IOException> entityParser,
-                                                                         ActionListener<Resp> listener, Set<Integer> ignores) {
-        performRequestAsync(request, requestConverter, options,
+    protected final <Req extends ActionRequest, Resp> Cancellable performRequestAsyncAndParseEntity(Req request,
+                CheckedFunction<Req, Request, IOException> requestConverter,
+                RequestOptions options,
+                CheckedFunction<XContentParser, Resp, IOException> entityParser,
+                ActionListener<Resp> listener, Set<Integer> ignores) {
+        return performRequestAsync(request, requestConverter, options,
                 response -> parseEntity(response.getEntity(), entityParser), listener, ignores);
     }
 
     /**
      * Defines a helper method for asynchronously performing a request.
-     */
-    protected final <Req extends Validatable, Resp> void performRequestAsyncAndParseEntity(Req request,
-                                                                       CheckedFunction<Req, Request, IOException> requestConverter,
-                                                                       RequestOptions options,
-                                                                       CheckedFunction<XContentParser, Resp, IOException> entityParser,
-                                                                       ActionListener<Resp> listener, Set<Integer> ignores) {
-        performRequestAsync(request, requestConverter, options,
+     * @return Cancellable instance that may be used to cancel the request
+     */
+    protected final <Req extends Validatable, Resp> Cancellable performRequestAsyncAndParseEntity(Req request,
+                CheckedFunction<Req, Request, IOException> requestConverter,
+                RequestOptions options,
+                CheckedFunction<XContentParser, Resp, IOException> entityParser,
+                ActionListener<Resp> listener, Set<Integer> ignores) {
+        return performRequestAsync(request, requestConverter, options,
                 response -> parseEntity(response.getEntity(), entityParser), listener, ignores);
     }
 
@@ -1536,56 +1578,59 @@ public class RestHighLevelClient implements Closeable {
     /**
      * @deprecated If creating a new HLRC ReST API call, consider creating new actions instead of reusing server actions. The Validation
      * layer has been added to the ReST client, and requests should extend {@link Validatable} instead of {@link ActionRequest}.
+     * @return Cancellable instance that may be used to cancel the request
      */
     @Deprecated
-    protected final <Req extends ActionRequest, Resp> void performRequestAsync(Req request,
-                                                                            CheckedFunction<Req, Request, IOException> requestConverter,
-                                                                            RequestOptions options,
-                                                                            CheckedFunction<Response, Resp, IOException> responseConverter,
-                                                                            ActionListener<Resp> listener, Set<Integer> ignores) {
+    protected final <Req extends ActionRequest, Resp> Cancellable performRequestAsync(Req request,
+                CheckedFunction<Req, Request, IOException> requestConverter,
+                RequestOptions options,
+                CheckedFunction<Response, Resp, IOException> responseConverter,
+                ActionListener<Resp> listener, Set<Integer> ignores) {
         ActionRequestValidationException validationException = request.validate();
         if (validationException != null && validationException.validationErrors().isEmpty() == false) {
             listener.onFailure(validationException);
-            return;
+            return Cancellable.NO_OP;
         }
-        internalPerformRequestAsync(request, requestConverter, options, responseConverter, listener, ignores);
+        return internalPerformRequestAsync(request, requestConverter, options, responseConverter, listener, ignores);
     }
 
     /**
      * Defines a helper method for asynchronously performing a request.
+     * @return Cancellable instance that may be used to cancel the request
      */
-    protected final <Req extends Validatable, Resp> void performRequestAsync(Req request,
-                                                                          CheckedFunction<Req, Request, IOException> requestConverter,
-                                                                          RequestOptions options,
-                                                                          CheckedFunction<Response, Resp, IOException> responseConverter,
-                                                                          ActionListener<Resp> listener, Set<Integer> ignores) {
+    protected final <Req extends Validatable, Resp> Cancellable performRequestAsync(Req request,
+                CheckedFunction<Req, Request, IOException> requestConverter,
+                RequestOptions options,
+                CheckedFunction<Response, Resp, IOException> responseConverter,
+                ActionListener<Resp> listener, Set<Integer> ignores) {
         Optional<ValidationException> validationException = request.validate();
         if (validationException != null && validationException.isPresent()) {
             listener.onFailure(validationException.get());
-            return;
+            return Cancellable.NO_OP;
         }
-        internalPerformRequestAsync(request, requestConverter, options, responseConverter, listener, ignores);
+        return internalPerformRequestAsync(request, requestConverter, options, responseConverter, listener, ignores);
     }
 
     /**
      * Provides common functionality for asynchronously performing a request.
+     * @return Cancellable instance that may be used to cancel the request
      */
-    private <Req, Resp> void internalPerformRequestAsync(Req request,
-                                                 CheckedFunction<Req, Request, IOException> requestConverter,
-                                                 RequestOptions options,
-                                                 CheckedFunction<Response, Resp, IOException> responseConverter,
-                                                 ActionListener<Resp> listener, Set<Integer> ignores) {
+    private <Req, Resp> Cancellable internalPerformRequestAsync(Req request,
+                 CheckedFunction<Req, Request, IOException> requestConverter,
+                 RequestOptions options,
+                 CheckedFunction<Response, Resp, IOException> responseConverter,
+                 ActionListener<Resp> listener, Set<Integer> ignores) {
         Request req;
         try {
             req = requestConverter.apply(request);
         } catch (Exception e) {
             listener.onFailure(e);
-            return;
+            return Cancellable.NO_OP;
         }
         req.setOptions(options);
 
         ResponseListener responseListener = wrapResponseListener(responseConverter, listener, ignores);
-        client.performRequestAsync(req, responseListener);
+        return client.performRequestAsync(req, responseListener);
     }
 
 
@@ -1629,28 +1674,29 @@ public class RestHighLevelClient implements Closeable {
 
     /**
      * Asynchronous request which returns empty {@link Optional}s in the case of 404s or parses entity into an Optional
+     * @return Cancellable instance that may be used to cancel the request
      */
-    protected final <Req extends Validatable, Resp> void performRequestAsyncAndParseOptionalEntity(Req request,
-            CheckedFunction<Req, Request, IOException> requestConverter,
-            RequestOptions options,
-            CheckedFunction<XContentParser, Resp, IOException> entityParser,
-            ActionListener<Optional<Resp>> listener) {
+    protected final <Req extends Validatable, Resp> Cancellable performRequestAsyncAndParseOptionalEntity(Req request,
+              CheckedFunction<Req, Request, IOException> requestConverter,
+              RequestOptions options,
+              CheckedFunction<XContentParser, Resp, IOException> entityParser,
+              ActionListener<Optional<Resp>> listener) {
         Optional<ValidationException> validationException = request.validate();
         if (validationException != null && validationException.isPresent()) {
             listener.onFailure(validationException.get());
-            return;
+            return Cancellable.NO_OP;
         }
         Request req;
         try {
             req = requestConverter.apply(request);
         } catch (Exception e) {
             listener.onFailure(e);
-            return;
+            return Cancellable.NO_OP;
         }
         req.setOptions(options);
         ResponseListener responseListener = wrapResponseListener404sOptional(response -> parseEntity(response.getEntity(),
                 entityParser), listener);
-        client.performRequestAsync(req, responseListener);
+        return client.performRequestAsync(req, responseListener);
     }
 
     final <Resp> ResponseListener wrapResponseListener404sOptional(CheckedFunction<Response, Resp, IOException> responseConverter,

+ 32 - 26
client/rest-high-level/src/main/java/org/elasticsearch/client/RollupClient.java

@@ -30,8 +30,6 @@ import org.elasticsearch.client.rollup.GetRollupJobRequest;
 import org.elasticsearch.client.rollup.GetRollupJobResponse;
 import org.elasticsearch.client.rollup.GetRollupCapsRequest;
 import org.elasticsearch.client.rollup.GetRollupCapsResponse;
-import org.elasticsearch.client.rollup.GetRollupJobRequest;
-import org.elasticsearch.client.rollup.GetRollupJobResponse;
 import org.elasticsearch.client.rollup.PutRollupJobRequest;
 import org.elasticsearch.client.rollup.StartRollupJobRequest;
 import org.elasticsearch.client.rollup.StartRollupJobResponse;
@@ -80,9 +78,11 @@ public class RollupClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putRollupJobAsync(PutRollupJobRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable putRollupJobAsync(PutRollupJobRequest request, RequestOptions options,
+                                         ActionListener<AcknowledgedResponse> listener) {
+       return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             RollupRequestConverters::putJob,
             options,
             AcknowledgedResponse::fromXContent,
@@ -113,10 +113,11 @@ public class RollupClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void startRollupJobAsync(StartRollupJobRequest request, RequestOptions options,
-            ActionListener<StartRollupJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable startRollupJobAsync(StartRollupJobRequest request, RequestOptions options,
+                                           ActionListener<StartRollupJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             RollupRequestConverters::startJob,
             options,
             StartRollupJobResponse::fromXContent,
@@ -147,10 +148,11 @@ public class RollupClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void stopRollupJobAsync(StopRollupJobRequest request, RequestOptions options,
-            ActionListener<StopRollupJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable stopRollupJobAsync(StopRollupJobRequest request, RequestOptions options,
+                                          ActionListener<StopRollupJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             RollupRequestConverters::stopJob,
             options,
             StopRollupJobResponse::fromXContent,
@@ -180,11 +182,12 @@ public class RollupClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteRollupJobAsync(DeleteRollupJobRequest request,
-                                     RequestOptions options,
-                                     ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable deleteRollupJobAsync(DeleteRollupJobRequest request,
+                                            RequestOptions options,
+                                            ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             RollupRequestConverters::deleteJob,
             options,
             AcknowledgedResponse::fromXContent,
@@ -215,11 +218,11 @@ public class RollupClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-
-
-    public void getRollupJobAsync(GetRollupJobRequest request, RequestOptions options, ActionListener<GetRollupJobResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getRollupJobAsync(GetRollupJobRequest request, RequestOptions options,
+                                         ActionListener<GetRollupJobResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             RollupRequestConverters::getJob,
             options,
             GetRollupJobResponse::fromXContent,
@@ -251,9 +254,10 @@ public class RollupClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void searchAsync(SearchRequest request, RequestOptions options, ActionListener<SearchResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable searchAsync(SearchRequest request, RequestOptions options, ActionListener<SearchResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
                 request,
                 RollupRequestConverters::search,
                 options,
@@ -286,10 +290,11 @@ public class RollupClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getRollupCapabilitiesAsync(GetRollupCapsRequest request, RequestOptions options,
-                                           ActionListener<GetRollupCapsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getRollupCapabilitiesAsync(GetRollupCapsRequest request, RequestOptions options,
+                                                  ActionListener<GetRollupCapsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             RollupRequestConverters::getRollupCaps,
             options,
             GetRollupCapsResponse::fromXContent,
@@ -322,10 +327,11 @@ public class RollupClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getRollupIndexCapabilitiesAsync(GetRollupIndexCapsRequest request, RequestOptions options,
-                                           ActionListener<GetRollupIndexCapsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request,
+    public Cancellable getRollupIndexCapabilitiesAsync(GetRollupIndexCapsRequest request, RequestOptions options,
+                                                       ActionListener<GetRollupIndexCapsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
             RollupRequestConverters::getRollupIndexCaps,
             options,
             GetRollupIndexCapsResponse::fromXContent,

+ 120 - 84
client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java

@@ -111,9 +111,10 @@ public final class SecurityClient {
      * @param request the request with the user's name
      * @param options the request options (e.g., headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getUsersAsync(GetUsersRequest request, RequestOptions options, ActionListener<GetUsersResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getUsers, options,
+    public Cancellable getUsersAsync(GetUsersRequest request, RequestOptions options, ActionListener<GetUsersResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getUsers, options,
             GetUsersResponse::fromXContent, listener, emptySet());
     }
 
@@ -140,9 +141,10 @@ public final class SecurityClient {
      * @param request  the request with the user's information
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putUserAsync(PutUserRequest request, RequestOptions options, ActionListener<PutUserResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putUser, options,
+    public Cancellable putUserAsync(PutUserRequest request, RequestOptions options, ActionListener<PutUserResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putUser, options,
             PutUserResponse::fromXContent, listener, emptySet());
     }
 
@@ -167,9 +169,10 @@ public final class SecurityClient {
      * @param request the request with the user to delete
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteUserAsync(DeleteUserRequest request, RequestOptions options, ActionListener<DeleteUserResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deleteUser, options,
+    public Cancellable deleteUserAsync(DeleteUserRequest request, RequestOptions options, ActionListener<DeleteUserResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deleteUser, options,
             DeleteUserResponse::fromXContent, listener, singleton(404));
     }
 
@@ -194,10 +197,11 @@ public final class SecurityClient {
      * @param request the request with the role mapping information
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putRoleMappingAsync(final PutRoleMappingRequest request, final RequestOptions options,
-            final ActionListener<PutRoleMappingResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putRoleMapping, options,
+    public Cancellable putRoleMappingAsync(final PutRoleMappingRequest request, final RequestOptions options,
+                                           final ActionListener<PutRoleMappingResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putRoleMapping, options,
                 PutRoleMappingResponse::fromXContent, listener, emptySet());
     }
 
@@ -214,7 +218,8 @@ public final class SecurityClient {
      * @throws IOException in case there is a problem sending the request or
      * parsing back the response
      */
-    public GetRoleMappingsResponse getRoleMappings(final GetRoleMappingsRequest request, final RequestOptions options) throws IOException {
+    public GetRoleMappingsResponse getRoleMappings(final GetRoleMappingsRequest request,
+                                                   final RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::getRoleMappings,
             options, GetRoleMappingsResponse::fromXContent, emptySet());
     }
@@ -228,10 +233,11 @@ public final class SecurityClient {
      * If no role mapping name is provided then retrieves all role mappings.
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getRoleMappingsAsync(final GetRoleMappingsRequest request, final RequestOptions options,
-            final ActionListener<GetRoleMappingsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getRoleMappings,
+    public Cancellable getRoleMappingsAsync(final GetRoleMappingsRequest request, final RequestOptions options,
+                                            final ActionListener<GetRoleMappingsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getRoleMappings,
                 options, GetRoleMappingsResponse::fromXContent, listener, emptySet());
     }
 
@@ -274,10 +280,11 @@ public final class SecurityClient {
      * @param request  the request with the user to enable
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void enableUserAsync(EnableUserRequest request, RequestOptions options,
-                                ActionListener<Boolean> listener) {
-        restHighLevelClient.performRequestAsync(request, SecurityRequestConverters::enableUser, options,
+    public Cancellable enableUserAsync(EnableUserRequest request, RequestOptions options,
+                                       ActionListener<Boolean> listener) {
+        return restHighLevelClient.performRequestAsync(request, SecurityRequestConverters::enableUser, options,
             RestHighLevelClient::convertExistsResponse, listener, emptySet());
     }
 
@@ -290,11 +297,12 @@ public final class SecurityClient {
      * @param request  the request with the user to enable
      * @param listener the listener to be notified upon request completion
      * @deprecated use {@link #enableUserAsync(EnableUserRequest, RequestOptions, ActionListener)} instead
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void enableUserAsync(RequestOptions options, EnableUserRequest request,
-                                ActionListener<Boolean> listener) {
-        enableUserAsync(request, options, listener);
+    public Cancellable enableUserAsync(RequestOptions options, EnableUserRequest request,
+                                       ActionListener<Boolean> listener) {
+        return enableUserAsync(request, options, listener);
     }
 
     /**
@@ -336,10 +344,11 @@ public final class SecurityClient {
      * @param request  the request with the user to disable
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void disableUserAsync(DisableUserRequest request, RequestOptions options,
-                                 ActionListener<Boolean> listener) {
-        restHighLevelClient.performRequestAsync(request, SecurityRequestConverters::disableUser, options,
+    public Cancellable disableUserAsync(DisableUserRequest request, RequestOptions options,
+                                        ActionListener<Boolean> listener) {
+        return restHighLevelClient.performRequestAsync(request, SecurityRequestConverters::disableUser, options,
             RestHighLevelClient::convertExistsResponse, listener, emptySet());
     }
 
@@ -352,11 +361,12 @@ public final class SecurityClient {
      * @param request  the request with the user to disable
      * @param listener the listener to be notified upon request completion
      * @deprecated use {@link #disableUserAsync(DisableUserRequest, RequestOptions, ActionListener)} instead
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void disableUserAsync(RequestOptions options, DisableUserRequest request,
-                                 ActionListener<Boolean> listener) {
-        disableUserAsync(request, options, listener);
+    public Cancellable disableUserAsync(RequestOptions options, DisableUserRequest request,
+                                        ActionListener<Boolean> listener) {
+        return disableUserAsync(request, options, listener);
     }
 
     /**
@@ -379,9 +389,10 @@ public final class SecurityClient {
      *
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void authenticateAsync(RequestOptions options, ActionListener<AuthenticateResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(AuthenticateRequest.INSTANCE, AuthenticateRequest::getRequest, options,
+    public Cancellable authenticateAsync(RequestOptions options, ActionListener<AuthenticateResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(AuthenticateRequest.INSTANCE, AuthenticateRequest::getRequest, options,
                 AuthenticateResponse::fromXContent, listener, emptySet());
     }
 
@@ -403,13 +414,14 @@ public final class SecurityClient {
      * Asynchronously determine whether the current user has a specified list of privileges
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-has-privileges.html">
      * the docs</a> for more.
-     *
      * @param request the request with the privileges to check
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void hasPrivilegesAsync(HasPrivilegesRequest request, RequestOptions options, ActionListener<HasPrivilegesResponse> listener) {
-         restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::hasPrivileges, options,
+    public Cancellable hasPrivilegesAsync(HasPrivilegesRequest request, RequestOptions options,
+                                          ActionListener<HasPrivilegesResponse> listener) {
+         return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::hasPrivileges, options,
             HasPrivilegesResponse::fromXContent, listener, emptySet());
     }
 
@@ -426,9 +438,11 @@ public final class SecurityClient {
      * Asynchronously retrieve the set of effective privileges held by the current user.
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getUserPrivilegesAsync(RequestOptions options, ActionListener<GetUserPrivilegesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(GetUserPrivilegesRequest.INSTANCE, GetUserPrivilegesRequest::getRequest,
+    public Cancellable getUserPrivilegesAsync(RequestOptions options, ActionListener<GetUserPrivilegesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
+            GetUserPrivilegesRequest.INSTANCE, GetUserPrivilegesRequest::getRequest,
             options, GetUserPrivilegesResponse::fromXContent, listener, emptySet());
     }
 
@@ -455,10 +469,11 @@ public final class SecurityClient {
      * @param request  the request with the realm names and usernames to clear the cache for
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void clearRealmCacheAsync(ClearRealmCacheRequest request, RequestOptions options,
-                                     ActionListener<ClearRealmCacheResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::clearRealmCache, options,
+    public Cancellable clearRealmCacheAsync(ClearRealmCacheRequest request, RequestOptions options,
+                                            ActionListener<ClearRealmCacheResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::clearRealmCache, options,
             ClearRealmCacheResponse::fromXContent, listener, emptySet());
     }
 
@@ -485,10 +500,11 @@ public final class SecurityClient {
      * @param request  the request with the roles for which the cache should be cleared.
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void clearRolesCacheAsync(ClearRolesCacheRequest request, RequestOptions options,
-                                     ActionListener<ClearRolesCacheResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::clearRolesCache, options,
+    public Cancellable clearRolesCacheAsync(ClearRolesCacheRequest request, RequestOptions options,
+                                            ActionListener<ClearRolesCacheResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::clearRolesCache, options,
             ClearRolesCacheResponse::fromXContent, listener, emptySet());
     }
 
@@ -513,9 +529,11 @@ public final class SecurityClient {
      *
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getSslCertificatesAsync(RequestOptions options, ActionListener<GetSslCertificatesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(GetSslCertificatesRequest.INSTANCE, GetSslCertificatesRequest::getRequest,
+    public Cancellable getSslCertificatesAsync(RequestOptions options, ActionListener<GetSslCertificatesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
+            GetSslCertificatesRequest.INSTANCE, GetSslCertificatesRequest::getRequest,
             options, GetSslCertificatesResponse::fromXContent, listener, emptySet());
     }
 
@@ -558,10 +576,11 @@ public final class SecurityClient {
      * @param request  the request with the user's new password
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void changePasswordAsync(ChangePasswordRequest request, RequestOptions options,
-                                    ActionListener<Boolean> listener) {
-        restHighLevelClient.performRequestAsync(request, SecurityRequestConverters::changePassword, options,
+    public Cancellable changePasswordAsync(ChangePasswordRequest request, RequestOptions options,
+                                           ActionListener<Boolean> listener) {
+        return restHighLevelClient.performRequestAsync(request, SecurityRequestConverters::changePassword, options,
             RestHighLevelClient::convertExistsResponse, listener, emptySet());
     }
 
@@ -574,11 +593,12 @@ public final class SecurityClient {
      * @param request  the request with the user's new password
      * @param listener the listener to be notified upon request completion
      * @deprecated use {@link #changePasswordAsync(ChangePasswordRequest, RequestOptions, ActionListener)} instead
+     * @return cancellable that may be used to cancel the request
      */
     @Deprecated
-    public void changePasswordAsync(RequestOptions options, ChangePasswordRequest request,
-                                    ActionListener<Boolean> listener) {
-        changePasswordAsync(request, options, listener);
+    public Cancellable changePasswordAsync(RequestOptions options, ChangePasswordRequest request,
+                                           ActionListener<Boolean> listener) {
+        return changePasswordAsync(request, options, listener);
     }
 
     /**
@@ -603,9 +623,10 @@ public final class SecurityClient {
      * @param request  the request with the roles to get
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getRolesAsync(GetRolesRequest request, RequestOptions options, ActionListener<GetRolesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getRoles, options,
+    public Cancellable getRolesAsync(GetRolesRequest request, RequestOptions options, ActionListener<GetRolesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getRoles, options,
             GetRolesResponse::fromXContent, listener, emptySet());
     }
 
@@ -632,9 +653,10 @@ public final class SecurityClient {
      * @param request  the request containing the role to create or update
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putRoleAsync(PutRoleRequest request, RequestOptions options, ActionListener<PutRoleResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putRole, options,
+    public Cancellable putRoleAsync(PutRoleRequest request, RequestOptions options, ActionListener<PutRoleResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putRole, options,
                 PutRoleResponse::fromXContent, listener, emptySet());
     }
 
@@ -660,10 +682,12 @@ public final class SecurityClient {
      * @param request the request with the role mapping name to be deleted.
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteRoleMappingAsync(DeleteRoleMappingRequest request, RequestOptions options,
-            ActionListener<DeleteRoleMappingResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deleteRoleMapping, options,
+    public Cancellable deleteRoleMappingAsync(DeleteRoleMappingRequest request, RequestOptions options,
+                                              ActionListener<DeleteRoleMappingResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request,
+            SecurityRequestConverters::deleteRoleMapping, options,
                 DeleteRoleMappingResponse::fromXContent, listener, emptySet());
     }
 
@@ -688,9 +712,11 @@ public final class SecurityClient {
      * @param request the request with the role to delete
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteRoleAsync(DeleteRoleRequest request, RequestOptions options, ActionListener<DeleteRoleResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deleteRole, options,
+    public Cancellable deleteRoleAsync(DeleteRoleRequest request, RequestOptions options,
+                                       ActionListener<DeleteRoleResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deleteRole, options,
             DeleteRoleResponse::fromXContent, listener, singleton(404));
     }
 
@@ -717,9 +743,11 @@ public final class SecurityClient {
      * @param request the request for the token
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void createTokenAsync(CreateTokenRequest request, RequestOptions options, ActionListener<CreateTokenResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::createToken, options,
+    public Cancellable createTokenAsync(CreateTokenRequest request, RequestOptions options,
+                                        ActionListener<CreateTokenResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::createToken, options,
             CreateTokenResponse::fromXContent, listener, emptySet());
     }
 
@@ -742,14 +770,14 @@ public final class SecurityClient {
      * Asynchronously invalidates an OAuth2 token.
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-invalidate-token.html">
      * the docs</a> for more.
-     *
      * @param request the request to invalidate the token
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void invalidateTokenAsync(InvalidateTokenRequest request, RequestOptions options,
-                                     ActionListener<InvalidateTokenResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::invalidateToken, options,
+    public Cancellable invalidateTokenAsync(InvalidateTokenRequest request, RequestOptions options,
+                                            ActionListener<InvalidateTokenResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::invalidateToken, options,
             InvalidateTokenResponse::fromXContent, listener, emptySet());
     }
 
@@ -775,10 +803,13 @@ public final class SecurityClient {
      *
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getBuiltinPrivilegesAsync(final RequestOptions options, final ActionListener<GetBuiltinPrivilegesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(GetBuiltinPrivilegesRequest.INSTANCE,
-            GetBuiltinPrivilegesRequest::getRequest, options, GetBuiltinPrivilegesResponse::fromXContent, listener, emptySet());
+    public Cancellable getBuiltinPrivilegesAsync(final RequestOptions options,
+                                                 final ActionListener<GetBuiltinPrivilegesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(GetBuiltinPrivilegesRequest.INSTANCE,
+            GetBuiltinPrivilegesRequest::getRequest, options, GetBuiltinPrivilegesResponse::fromXContent,
+            listener, emptySet());
     }
 
     /**
@@ -804,16 +835,16 @@ public final class SecurityClient {
      * Asynchronously get application privilege(s).
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-privileges.html">
      * the docs</a> for more.
-     *
-     * @param request  {@link GetPrivilegesRequest} with the application name and the privilege name.
+     *  @param request  {@link GetPrivilegesRequest} with the application name and the privilege name.
      *                 If no application name is provided, information about all privileges for all applications is retrieved.
      *                 If no privilege name is provided, information about all privileges of the specified application is retrieved.
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getPrivilegesAsync(final GetPrivilegesRequest request, final RequestOptions options,
-                                   final ActionListener<GetPrivilegesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getPrivileges,
+    public Cancellable getPrivilegesAsync(final GetPrivilegesRequest request, final RequestOptions options,
+                                          final ActionListener<GetPrivilegesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getPrivileges,
             options, GetPrivilegesResponse::fromXContent, listener, emptySet());
     }
 
@@ -842,10 +873,11 @@ public final class SecurityClient {
      * @param options the request options (e.g. headers), use
      * {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putPrivilegesAsync(final PutPrivilegesRequest request, final RequestOptions options,
-            final ActionListener<PutPrivilegesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putPrivileges, options,
+    public Cancellable putPrivilegesAsync(final PutPrivilegesRequest request, final RequestOptions options,
+                                          final ActionListener<PutPrivilegesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putPrivileges, options,
                 PutPrivilegesResponse::fromXContent, listener, emptySet());
     }
 
@@ -872,10 +904,11 @@ public final class SecurityClient {
      * @param request  the request with the application privilege to delete
      * @param options  the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deletePrivilegesAsync(DeletePrivilegesRequest request, RequestOptions options,
-                                      ActionListener<DeletePrivilegesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deletePrivileges, options,
+    public Cancellable deletePrivilegesAsync(DeletePrivilegesRequest request, RequestOptions options,
+                                             ActionListener<DeletePrivilegesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deletePrivileges, options,
             DeletePrivilegesResponse::fromXContent, listener, singleton(404));
     }
 
@@ -902,10 +935,11 @@ public final class SecurityClient {
      * @param request the request to create a API key
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void createApiKeyAsync(final CreateApiKeyRequest request, final RequestOptions options,
-            final ActionListener<CreateApiKeyResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::createApiKey, options,
+    public Cancellable createApiKeyAsync(final CreateApiKeyRequest request, final RequestOptions options,
+                                         final ActionListener<CreateApiKeyResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::createApiKey, options,
                 CreateApiKeyResponse::fromXContent, listener, emptySet());
     }
 
@@ -932,10 +966,11 @@ public final class SecurityClient {
      * @param request the request to retrieve API key(s)
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getApiKeyAsync(final GetApiKeyRequest request, final RequestOptions options,
-            final ActionListener<GetApiKeyResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getApiKey, options,
+    public Cancellable getApiKeyAsync(final GetApiKeyRequest request, final RequestOptions options,
+                                      final ActionListener<GetApiKeyResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getApiKey, options,
                 GetApiKeyResponse::fromXContent, listener, emptySet());
     }
 
@@ -963,10 +998,11 @@ public final class SecurityClient {
      * @param request the request to invalidate API key(s)
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void invalidateApiKeyAsync(final InvalidateApiKeyRequest request, final RequestOptions options,
-                                      final ActionListener<InvalidateApiKeyResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::invalidateApiKey, options,
+    public Cancellable invalidateApiKeyAsync(final InvalidateApiKeyRequest request, final RequestOptions options,
+                                             final ActionListener<InvalidateApiKeyResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::invalidateApiKey, options,
                 InvalidateApiKeyResponse::fromXContent, listener, emptySet());
     }
 }

+ 51 - 31
client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java

@@ -79,10 +79,12 @@ public final class SnapshotClient {
      * @param getRepositoriesRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getRepositoryAsync(GetRepositoriesRequest getRepositoriesRequest, RequestOptions options,
-                                   ActionListener<GetRepositoriesResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getRepositoriesRequest, SnapshotRequestConverters::getRepositories, options,
+    public Cancellable getRepositoryAsync(GetRepositoriesRequest getRepositoriesRequest, RequestOptions options,
+                                          ActionListener<GetRepositoriesResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getRepositoriesRequest,
+            SnapshotRequestConverters::getRepositories, options,
             GetRepositoriesResponse::fromXContent, listener, emptySet());
     }
 
@@ -107,10 +109,12 @@ public final class SnapshotClient {
      * @param putRepositoryRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void createRepositoryAsync(PutRepositoryRequest putRepositoryRequest, RequestOptions options,
-                                      ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(putRepositoryRequest, SnapshotRequestConverters::createRepository, options,
+    public Cancellable createRepositoryAsync(PutRepositoryRequest putRepositoryRequest, RequestOptions options,
+                                             ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(putRepositoryRequest,
+            SnapshotRequestConverters::createRepository, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -136,10 +140,12 @@ public final class SnapshotClient {
      * @param deleteRepositoryRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteRepositoryAsync(DeleteRepositoryRequest deleteRepositoryRequest, RequestOptions options,
-                                      ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(deleteRepositoryRequest, SnapshotRequestConverters::deleteRepository, options,
+    public Cancellable deleteRepositoryAsync(DeleteRepositoryRequest deleteRepositoryRequest, RequestOptions options,
+                                             ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(deleteRepositoryRequest,
+            SnapshotRequestConverters::deleteRepository, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -165,10 +171,12 @@ public final class SnapshotClient {
      * @param verifyRepositoryRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void verifyRepositoryAsync(VerifyRepositoryRequest verifyRepositoryRequest, RequestOptions options,
-                                      ActionListener<VerifyRepositoryResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest, SnapshotRequestConverters::verifyRepository, options,
+    public Cancellable verifyRepositoryAsync(VerifyRepositoryRequest verifyRepositoryRequest, RequestOptions options,
+                                             ActionListener<VerifyRepositoryResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest,
+            SnapshotRequestConverters::verifyRepository, options,
             VerifyRepositoryResponse::fromXContent, listener, emptySet());
     }
 
@@ -194,10 +202,11 @@ public final class SnapshotClient {
      * @param cleanupRepositoryRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void cleanupRepositoryAsync(CleanupRepositoryRequest cleanupRepositoryRequest, RequestOptions options,
+    public Cancellable cleanupRepositoryAsync(CleanupRepositoryRequest cleanupRepositoryRequest, RequestOptions options,
                                        ActionListener<CleanupRepositoryResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(cleanupRepositoryRequest, SnapshotRequestConverters::cleanupRepository,
+        return restHighLevelClient.performRequestAsyncAndParseEntity(cleanupRepositoryRequest, SnapshotRequestConverters::cleanupRepository,
             options, CleanupRepositoryResponse::fromXContent, listener, emptySet());
     }
 
@@ -218,10 +227,12 @@ public final class SnapshotClient {
      * <p>
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
      * API on elastic.co</a>
+     * @return cancellable that may be used to cancel the request
      */
-    public void createAsync(CreateSnapshotRequest createSnapshotRequest, RequestOptions options,
-                                    ActionListener<CreateSnapshotResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(createSnapshotRequest, SnapshotRequestConverters::createSnapshot, options,
+    public Cancellable createAsync(CreateSnapshotRequest createSnapshotRequest, RequestOptions options,
+                                   ActionListener<CreateSnapshotResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(createSnapshotRequest,
+            SnapshotRequestConverters::createSnapshot, options,
             CreateSnapshotResponse::fromXContent, listener, emptySet());
     }
 
@@ -244,13 +255,15 @@ public final class SnapshotClient {
      * Asynchronously get snapshots.
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html"> Snapshot and Restore
      * API on elastic.co</a>
-     *
-     * @param getSnapshotsRequest the request
+     *  @param getSnapshotsRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getAsync(GetSnapshotsRequest getSnapshotsRequest, RequestOptions options, ActionListener<GetSnapshotsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(getSnapshotsRequest, SnapshotRequestConverters::getSnapshots, options,
+    public Cancellable getAsync(GetSnapshotsRequest getSnapshotsRequest, RequestOptions options,
+                                ActionListener<GetSnapshotsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(getSnapshotsRequest,
+            SnapshotRequestConverters::getSnapshots, options,
             GetSnapshotsResponse::fromXContent, listener, emptySet());
     }
 
@@ -276,10 +289,12 @@ public final class SnapshotClient {
      * @param snapshotsStatusRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void statusAsync(SnapshotsStatusRequest snapshotsStatusRequest, RequestOptions options,
-                            ActionListener<SnapshotsStatusResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(snapshotsStatusRequest, SnapshotRequestConverters::snapshotsStatus, options,
+    public Cancellable statusAsync(SnapshotsStatusRequest snapshotsStatusRequest, RequestOptions options,
+                                   ActionListener<SnapshotsStatusResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(snapshotsStatusRequest,
+            SnapshotRequestConverters::snapshotsStatus, options,
             SnapshotsStatusResponse::fromXContent, listener, emptySet());
     }
 
@@ -306,10 +321,12 @@ public final class SnapshotClient {
      * @param restoreSnapshotRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void restoreAsync(RestoreSnapshotRequest restoreSnapshotRequest, RequestOptions options,
-                            ActionListener<RestoreSnapshotResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(restoreSnapshotRequest, SnapshotRequestConverters::restoreSnapshot, options,
+    public Cancellable restoreAsync(RestoreSnapshotRequest restoreSnapshotRequest, RequestOptions options,
+                                    ActionListener<RestoreSnapshotResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(restoreSnapshotRequest,
+            SnapshotRequestConverters::restoreSnapshot, options,
             RestoreSnapshotResponse::fromXContent, listener, emptySet());
     }
 
@@ -324,7 +341,8 @@ public final class SnapshotClient {
      * @throws IOException in case there is a problem sending the request or parsing back the response
      */
     public AcknowledgedResponse delete(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options) throws IOException {
-        return restHighLevelClient.performRequestAndParseEntity(deleteSnapshotRequest, SnapshotRequestConverters::deleteSnapshot, options,
+        return restHighLevelClient.performRequestAndParseEntity(deleteSnapshotRequest,
+            SnapshotRequestConverters::deleteSnapshot, options,
             AcknowledgedResponse::fromXContent, emptySet());
     }
 
@@ -336,10 +354,12 @@ public final class SnapshotClient {
      * @param deleteSnapshotRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteAsync(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options,
-                            ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(deleteSnapshotRequest, SnapshotRequestConverters::deleteSnapshot, options,
+    public Cancellable deleteAsync(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options,
+                                   ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(deleteSnapshotRequest,
+            SnapshotRequestConverters::deleteSnapshot, options,
             AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 }

+ 17 - 12
client/rest-high-level/src/main/java/org/elasticsearch/client/TasksClient.java

@@ -65,12 +65,13 @@ public final class TasksClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void listAsync(ListTasksRequest request, RequestOptions options, ActionListener<ListTasksResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, TasksRequestConverters::listTasks, options,
+    public Cancellable listAsync(ListTasksRequest request, RequestOptions options, ActionListener<ListTasksResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, TasksRequestConverters::listTasks, options,
                 ListTasksResponse::fromXContent, listener, emptySet());
     }
-    
+
     /**
      * Get a task using the Task Management API.
      * See
@@ -82,9 +83,9 @@ public final class TasksClient {
      */
     public Optional<GetTaskResponse> get(GetTaskRequest request, RequestOptions options) throws IOException {
         return restHighLevelClient.performRequestAndParseOptionalEntity(request, TasksRequestConverters::getTask, options,
-                GetTaskResponse::fromXContent);        
-    }   
-    
+                GetTaskResponse::fromXContent);
+    }
+
     /**
      * Get a task using the Task Management API.
      * See
@@ -92,12 +93,14 @@ public final class TasksClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener an actionlistener that takes an optional response (404s are returned as an empty Optional)
+     * @return cancellable that may be used to cancel the request
      */
-    public void getAsync(GetTaskRequest request, RequestOptions options, ActionListener<Optional<GetTaskResponse>> listener) {
-        
-        restHighLevelClient.performRequestAsyncAndParseOptionalEntity(request, TasksRequestConverters::getTask, options,
+    public Cancellable getAsync(GetTaskRequest request, RequestOptions options,
+                                ActionListener<Optional<GetTaskResponse>> listener) {
+
+        return restHighLevelClient.performRequestAsyncAndParseOptionalEntity(request, TasksRequestConverters::getTask, options,
                 GetTaskResponse::fromXContent, listener);
-    }    
+    }
 
     /**
      * Cancel one or more cluster tasks using the Task Management API.
@@ -128,9 +131,11 @@ public final class TasksClient {
      * @param cancelTasksRequest the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void cancelAsync(CancelTasksRequest cancelTasksRequest, RequestOptions options, ActionListener<CancelTasksResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable cancelAsync(CancelTasksRequest cancelTasksRequest, RequestOptions options,
+                                   ActionListener<CancelTasksResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
             cancelTasksRequest,
             TasksRequestConverters::cancelTasks,
             options,

+ 38 - 25
client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherClient.java

@@ -71,10 +71,11 @@ public final class WatcherClient {
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-start.html">
      * the docs</a> for more.
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @return cancellable that may be used to cancel the request
      */
-    public void startWatchServiceAsync(StartWatchServiceRequest request, RequestOptions options,
-            ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable startWatchServiceAsync(StartWatchServiceRequest request, RequestOptions options,
+                                              ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
                 request, WatcherRequestConverters::startWatchService, options, AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -98,10 +99,11 @@ public final class WatcherClient {
      * the docs</a> for more.
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @return cancellable that may be used to cancel the request
      */
-    public void stopWatchServiceAsync(StopWatchServiceRequest request, RequestOptions options,
-            ActionListener<AcknowledgedResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(
+    public Cancellable stopWatchServiceAsync(StopWatchServiceRequest request, RequestOptions options,
+                                             ActionListener<AcknowledgedResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(
                 request, WatcherRequestConverters::stopWatchService, options, AcknowledgedResponse::fromXContent, listener, emptySet());
     }
 
@@ -126,10 +128,11 @@ public final class WatcherClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void putWatchAsync(PutWatchRequest request, RequestOptions options,
-                              ActionListener<PutWatchResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::putWatch, options,
+    public Cancellable putWatchAsync(PutWatchRequest request, RequestOptions options,
+                                     ActionListener<PutWatchResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::putWatch, options,
             PutWatchResponse::fromXContent, listener, emptySet());
     }
 
@@ -154,10 +157,11 @@ public final class WatcherClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void getWatchAsync(GetWatchRequest request, RequestOptions options,
-                              ActionListener<GetWatchResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::getWatch, options,
+    public Cancellable getWatchAsync(GetWatchRequest request, RequestOptions options,
+                                     ActionListener<GetWatchResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::getWatch, options,
             GetWatchResponse::fromXContent, listener, emptySet());
     }
 
@@ -183,10 +187,11 @@ public final class WatcherClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deactivateWatchAsync(DeactivateWatchRequest request, RequestOptions options,
-                                     ActionListener<DeactivateWatchResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::deactivateWatch, options,
+    public Cancellable deactivateWatchAsync(DeactivateWatchRequest request, RequestOptions options,
+                                            ActionListener<DeactivateWatchResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::deactivateWatch, options,
             DeactivateWatchResponse::fromXContent, listener, emptySet());
     }
 
@@ -211,9 +216,10 @@ public final class WatcherClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void deleteWatchAsync(DeleteWatchRequest request, RequestOptions options, ActionListener<DeleteWatchResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::deleteWatch, options,
+    public Cancellable deleteWatchAsync(DeleteWatchRequest request, RequestOptions options, ActionListener<DeleteWatchResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::deleteWatch, options,
             DeleteWatchResponse::fromXContent, listener, singleton(404));
     }
 
@@ -238,9 +244,10 @@ public final class WatcherClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon completion of the request
+     * @return cancellable that may be used to cancel the request
      */
-    public void ackWatchAsync(AckWatchRequest request, RequestOptions options, ActionListener<AckWatchResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::ackWatch, options,
+    public Cancellable ackWatchAsync(AckWatchRequest request, RequestOptions options, ActionListener<AckWatchResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::ackWatch, options,
             AckWatchResponse::fromXContent, listener, emptySet());
     }
 
@@ -265,9 +272,11 @@ public final class WatcherClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void activateWatchAsync(ActivateWatchRequest request, RequestOptions options, ActionListener<ActivateWatchResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::activateWatch, options,
+    public Cancellable activateWatchAsync(ActivateWatchRequest request, RequestOptions options,
+                                          ActionListener<ActivateWatchResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::activateWatch, options,
             ActivateWatchResponse::fromXContent, listener, singleton(404));
     }
 
@@ -292,9 +301,11 @@ public final class WatcherClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notifed upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void executeWatchAsync(ExecuteWatchRequest request, RequestOptions options, ActionListener<ExecuteWatchResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::executeWatch, options,
+    public Cancellable executeWatchAsync(ExecuteWatchRequest request, RequestOptions options,
+                                         ActionListener<ExecuteWatchResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::executeWatch, options,
             ExecuteWatchResponse::fromXContent, listener, emptySet());
     }
 
@@ -319,9 +330,11 @@ public final class WatcherClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void watcherStatsAsync(WatcherStatsRequest request, RequestOptions options, ActionListener<WatcherStatsResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::watcherStats, options,
+    public Cancellable watcherStatsAsync(WatcherStatsRequest request, RequestOptions options,
+                                         ActionListener<WatcherStatsResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::watcherStats, options,
             WatcherStatsResponse::fromXContent, listener, emptySet());
     }
 

+ 7 - 5
client/rest-high-level/src/main/java/org/elasticsearch/client/XPackClient.java

@@ -67,10 +67,11 @@ public final class XPackClient {
      * @param request the request
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void infoAsync(XPackInfoRequest request, RequestOptions options,
-                                  ActionListener<XPackInfoResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, XPackRequestConverters::info, options,
+    public Cancellable infoAsync(XPackInfoRequest request, RequestOptions options,
+                                 ActionListener<XPackInfoResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, XPackRequestConverters::info, options,
             XPackInfoResponse::fromXContent, listener, emptySet());
     }
 
@@ -89,9 +90,10 @@ public final class XPackClient {
      * Asynchronously fetch usage information about X-Pack features from the cluster.
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @param listener the listener to be notified upon request completion
+     * @return cancellable that may be used to cancel the request
      */
-    public void usageAsync(XPackUsageRequest request, RequestOptions options, ActionListener<XPackUsageResponse> listener) {
-        restHighLevelClient.performRequestAsyncAndParseEntity(request, XPackRequestConverters::usage, options,
+    public Cancellable usageAsync(XPackUsageRequest request, RequestOptions options, ActionListener<XPackUsageResponse> listener) {
+        return restHighLevelClient.performRequestAsyncAndParseEntity(request, XPackRequestConverters::usage, options,
             XPackUsageResponse::fromXContent, listener, emptySet());
     }
 }

+ 1 - 1
client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java

@@ -900,7 +900,7 @@ public class RestHighLevelClientTests extends ESTestCase {
     private static void assertAsyncMethod(Map<String, Set<Method>> methods, Method method, String apiName) {
         assertTrue("async method [" + method.getName() + "] doesn't have corresponding sync method",
                 methods.containsKey(apiName.substring(0, apiName.length() - 6)));
-        assertThat("async method [" + method + "] should return void", method.getReturnType(), equalTo(Void.TYPE));
+        assertThat("async method [" + method + "] should return Cancellable", method.getReturnType(), equalTo(Cancellable.class));
         assertEquals("async method [" + method + "] should not throw any exceptions", 0, method.getExceptionTypes().length);
         if (APIS_WITHOUT_REQUEST_OBJECT.contains(apiName.replaceAll("_async$", ""))) {
             assertEquals(2, method.getParameterTypes().length);