Browse Source

Replace ActionRequest usage with Validatable for HLRC request classes (#46837)

Some hlrc request classes extend from ActionRequest
instead of implementing Validatable. ActionRequest
is a base class for server side request classes and
there should be no need to extend from this class
on the hlrc side.

Also usages of IndicesRequest / IndicesRequest.Replaceable
were removed, because implementing this interface on
the hlrc side does not make sense. Note that the indices()
methods were not removed from request classes implementing
this interface, because this how indices are passed to
the request classes.
Martijn van Groningen 6 years ago
parent
commit
3fa722e233
46 changed files with 172 additions and 417 deletions
  1. 2 9
      client/rest-high-level/src/main/java/org/elasticsearch/client/core/CountRequest.java
  2. 22 23
      client/rest-high-level/src/main/java/org/elasticsearch/client/indices/PutIndexTemplateRequest.java
  3. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/CloseJobRequest.java
  4. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteCalendarEventRequest.java
  5. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteCalendarJobRequest.java
  6. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteCalendarRequest.java
  7. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteDatafeedRequest.java
  8. 2 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteExpiredDataRequest.java
  9. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteForecastRequest.java
  10. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobRequest.java
  11. 2 9
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteModelSnapshotRequest.java
  12. 2 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/FlushJobRequest.java
  13. 2 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/ForecastJobRequest.java
  14. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetBucketsRequest.java
  15. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetCalendarEventsRequest.java
  16. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetCalendarsRequest.java
  17. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetCategoriesRequest.java
  18. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedRequest.java
  19. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedStatsRequest.java
  20. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetFiltersRequest.java
  21. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetInfluencersRequest.java
  22. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobRequest.java
  23. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsRequest.java
  24. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetModelSnapshotsRequest.java
  25. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetOverallBucketsRequest.java
  26. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/OpenJobRequest.java
  27. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostCalendarEventRequest.java
  28. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostDataRequest.java
  29. 3 9
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PreviewDatafeedRequest.java
  30. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutCalendarJobRequest.java
  31. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutCalendarRequest.java
  32. 2 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutDatafeedRequest.java
  33. 2 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutFilterRequest.java
  34. 2 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutJobRequest.java
  35. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/RevertModelSnapshotRequest.java
  36. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/SetUpgradeModeRequest.java
  37. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/StartDatafeedRequest.java
  38. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/StopDatafeedRequest.java
  39. 2 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateDatafeedRequest.java
  40. 2 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateFilterRequest.java
  41. 2 7
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateJobRequest.java
  42. 2 8
      client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateModelSnapshotRequest.java
  43. 12 18
      client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java
  44. 3 3
      client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java
  45. 12 11
      client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java
  46. 40 40
      client/rest-high-level/src/test/java/org/elasticsearch/client/indices/PutIndexTemplateRequestTests.java

+ 2 - 9
client/rest-high-level/src/main/java/org/elasticsearch/client/core/CountRequest.java

@@ -19,10 +19,8 @@
 
 package org.elasticsearch.client.core;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
-import org.elasticsearch.action.IndicesRequest;
 import org.elasticsearch.action.support.IndicesOptions;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.xcontent.ToXContentObject;
 import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -39,7 +37,7 @@ import static org.elasticsearch.action.search.SearchRequest.DEFAULT_INDICES_OPTI
 /**
  * Encapsulates a request to _count API against one, several or all indices.
  */
-public final class CountRequest extends ActionRequest implements IndicesRequest.Replaceable, ToXContentObject {
+public final class CountRequest implements Validatable, ToXContentObject {
 
     private String[] indices = Strings.EMPTY_ARRAY;
     private String[] types = Strings.EMPTY_ARRAY;
@@ -78,11 +76,6 @@ public final class CountRequest extends ActionRequest implements IndicesRequest.
         this.query = Objects.requireNonNull(query, "query must not be null");;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     /**
      * Sets the indices the count will be executed on.
      */

+ 22 - 23
client/rest-high-level/src/main/java/org/elasticsearch/client/indices/PutIndexTemplateRequest.java

@@ -20,15 +20,13 @@ package org.elasticsearch.client.indices;
 
 import org.elasticsearch.ElasticsearchGenerationException;
 import org.elasticsearch.ElasticsearchParseException;
-import org.elasticsearch.action.ActionRequestValidationException;
-import org.elasticsearch.action.IndicesRequest;
 import org.elasticsearch.action.admin.indices.alias.Alias;
-import org.elasticsearch.action.support.IndicesOptions;
-import org.elasticsearch.action.support.master.MasterNodeRequest;
+import org.elasticsearch.client.TimedRequest;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.bytes.BytesReference;
 import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.common.xcontent.DeprecationHandler;
 import org.elasticsearch.common.xcontent.NamedXContentRegistry;
 import org.elasticsearch.common.xcontent.ToXContentFragment;
@@ -50,13 +48,12 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-import static org.elasticsearch.action.ValidateActions.addValidationError;
 import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
 
 /**
  * A request to create an index template.
  */
-public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateRequest> implements IndicesRequest, ToXContentFragment {
+public class PutIndexTemplateRequest extends TimedRequest implements ToXContentFragment {
 
     private String name;
 
@@ -77,19 +74,11 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
     private Integer version;
 
     /**
-     * Constructs a new put index template request with the provided name.
+     * Constructs a new put index template request with the provided name and patterns.
      */
-    public PutIndexTemplateRequest(String name) {
+    public PutIndexTemplateRequest(String name, List<String> indexPatterns) {
         this.name(name);
-    }
-
-    @Override
-    public ActionRequestValidationException validate() {
-        ActionRequestValidationException validationException = null;
-        if (indexPatterns == null || indexPatterns.size() == 0) {
-            validationException = addValidationError("index patterns are missing", validationException);
-        }
-        return validationException;
+        this.patterns(indexPatterns);
     }
 
     /**
@@ -111,6 +100,9 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
     }
 
     public PutIndexTemplateRequest patterns(List<String> indexPatterns) {
+        if (indexPatterns == null || indexPatterns.size() == 0) {
+            throw new IllegalArgumentException("index patterns are missing");
+        }
         this.indexPatterns = indexPatterns;
         return this;
     }
@@ -412,14 +404,21 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
         return this;
     }
 
-    @Override
-    public String[] indices() {
-        return indexPatterns.toArray(new String[indexPatterns.size()]);
+    /**
+     * @deprecated Use {@link #setMasterTimeout(TimeValue)} instead
+     */
+    @Deprecated
+    public final PutIndexTemplateRequest masterNodeTimeout(TimeValue timeout) {
+        setMasterTimeout(timeout);
+        return this;
     }
 
-    @Override
-    public IndicesOptions indicesOptions() {
-        return IndicesOptions.strictExpand();
+    /**
+     * @deprecated Use {@link #setMasterTimeout(TimeValue)} instead
+     */
+    @Deprecated
+    public final PutIndexTemplateRequest masterNodeTimeout(String timeout) {
+        return masterNodeTimeout(TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + ".masterNodeTimeout"));
     }
 
     @Override

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/CloseJobRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.unit.TimeValue;
@@ -38,7 +37,7 @@ import java.util.Objects;
 /**
  * Request to close Machine Learning Jobs
  */
-public class CloseJobRequest extends ActionRequest implements ToXContentObject {
+public class CloseJobRequest implements ToXContentObject, Validatable {
 
     public static final ParseField JOB_ID = new ParseField("job_id");
     public static final ParseField TIMEOUT = new ParseField("timeout");
@@ -144,11 +143,6 @@ public class CloseJobRequest extends ActionRequest implements ToXContentObject {
         this.allowNoJobs = allowNoJobs;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(jobIds, timeout, force, allowNoJobs);

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteCalendarEventRequest.java

@@ -18,15 +18,14 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 
 import java.util.Objects;
 
 /**
  * Request class for removing an event from an existing calendar
  */
-public class DeleteCalendarEventRequest extends ActionRequest {
+public class DeleteCalendarEventRequest implements Validatable {
 
     private final String eventId;
     private final String calendarId;
@@ -51,11 +50,6 @@ public class DeleteCalendarEventRequest extends ActionRequest {
         return calendarId;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(eventId, calendarId);

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteCalendarJobRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 
 import java.security.InvalidParameterException;
 import java.util.Arrays;
@@ -29,7 +28,7 @@ import java.util.Objects;
 /**
  * Request class for removing Machine Learning Jobs from an existing calendar
  */
-public class DeleteCalendarJobRequest extends ActionRequest {
+public class DeleteCalendarJobRequest implements Validatable {
 
     private final List<String> jobIds;
     private final String calendarId;
@@ -61,11 +60,6 @@ public class DeleteCalendarJobRequest extends ActionRequest {
         return calendarId;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(jobIds, calendarId);

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteCalendarRequest.java

@@ -19,15 +19,14 @@
 
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 
 import java.util.Objects;
 
 /**
  * Request to delete a Machine Learning Calendar
  */
-public class DeleteCalendarRequest extends ActionRequest {
+public class DeleteCalendarRequest implements Validatable {
 
     private final String calendarId;
 
@@ -43,11 +42,6 @@ public class DeleteCalendarRequest extends ActionRequest {
         return calendarId;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(calendarId);

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteDatafeedRequest.java

@@ -18,15 +18,14 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 
 import java.util.Objects;
 
 /**
  * Request to delete a Machine Learning Datafeed via its ID
  */
-public class DeleteDatafeedRequest extends ActionRequest {
+public class DeleteDatafeedRequest implements Validatable {
 
     private String datafeedId;
     private Boolean force;
@@ -53,11 +52,6 @@ public class DeleteDatafeedRequest extends ActionRequest {
         this.force = force;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-       return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(datafeedId, force);

+ 2 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteExpiredDataRequest.java

@@ -18,13 +18,12 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 
 /**
  * Request to delete expired model snapshots and forecasts
  */
-public class DeleteExpiredDataRequest extends ActionRequest {
+public class DeleteExpiredDataRequest implements Validatable {
 
    /**
      * Create a new request to delete expired data
@@ -32,8 +31,4 @@ public class DeleteExpiredDataRequest extends ActionRequest {
     public DeleteExpiredDataRequest() {
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
 }

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteForecastRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.Strings;
@@ -37,7 +36,7 @@ import java.util.Objects;
 /**
  * POJO for a delete forecast request
  */
-public class DeleteForecastRequest extends ActionRequest implements ToXContentObject {
+public class DeleteForecastRequest implements Validatable, ToXContentObject {
 
     public static final ParseField FORECAST_ID = new ParseField("forecast_id");
     public static final ParseField ALLOW_NO_FORECASTS = new ParseField("allow_no_forecasts");
@@ -159,11 +158,6 @@ public class DeleteForecastRequest extends ActionRequest implements ToXContentOb
         return Objects.hash(jobId, forecastIds, allowNoForecasts, timeout);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobRequest.java

@@ -18,15 +18,14 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 
 import java.util.Objects;
 
 /**
  * Request to delete a Machine Learning Job via its ID
  */
-public class DeleteJobRequest extends ActionRequest {
+public class DeleteJobRequest implements Validatable {
 
     private String jobId;
     private Boolean force;
@@ -76,11 +75,6 @@ public class DeleteJobRequest extends ActionRequest {
         this.waitForCompletion = waitForCompletion;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-       return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(jobId, force);

+ 2 - 9
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteModelSnapshotRequest.java

@@ -18,18 +18,16 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.client.ml.job.process.ModelSnapshot;
 
-
 import java.util.Objects;
 
 /**
  * Request to delete a Machine Learning Model Snapshot Job via its Job and Snapshot IDs
  */
-public class DeleteModelSnapshotRequest extends ActionRequest {
+public class DeleteModelSnapshotRequest implements Validatable {
 
     private final String jobId;
     private final String snapshotId;
@@ -47,11 +45,6 @@ public class DeleteModelSnapshotRequest extends ActionRequest {
         return snapshotId;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-       return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(jobId, snapshotId);

+ 2 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/FlushJobRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.xcontent.ConstructingObjectParser;
@@ -32,7 +31,7 @@ import java.util.Objects;
 /**
  * Request object to flush a given Machine Learning job.
  */
-public class FlushJobRequest extends ActionRequest implements ToXContentObject {
+public class FlushJobRequest implements Validatable, ToXContentObject {
 
     public static final ParseField CALC_INTERIM = new ParseField("calc_interim");
     public static final ParseField START = new ParseField("start");
@@ -188,8 +187,4 @@ public class FlushJobRequest extends ActionRequest implements ToXContentObject {
         return builder;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
 }

+ 2 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/ForecastJobRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.unit.TimeValue;
@@ -34,7 +33,7 @@ import java.util.Objects;
 /**
  * Pojo for forecasting an existing and open Machine Learning Job
  */
-public class ForecastJobRequest extends ActionRequest implements ToXContentObject {
+public class ForecastJobRequest implements Validatable, ToXContentObject {
 
     public static final ParseField DURATION = new ParseField("duration");
     public static final ParseField EXPIRES_IN = new ParseField("expires_in");
@@ -133,8 +132,4 @@ public class ForecastJobRequest extends ActionRequest implements ToXContentObjec
         return builder;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
 }

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetBucketsRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.core.PageParams;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.client.ml.job.results.Result;
@@ -34,7 +33,7 @@ import java.util.Objects;
 /**
  * A request to retrieve buckets of a given job
  */
-public class GetBucketsRequest extends ActionRequest implements ToXContentObject {
+public class GetBucketsRequest implements Validatable, ToXContentObject {
 
     public static final ParseField EXPAND = new ParseField("expand");
     public static final ParseField EXCLUDE_INTERIM = new ParseField("exclude_interim");
@@ -199,11 +198,6 @@ public class GetBucketsRequest extends ActionRequest implements ToXContentObject
         this.descending = descending;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetCalendarEventsRequest.java

@@ -19,8 +19,7 @@
 
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.core.PageParams;
 import org.elasticsearch.client.ml.calendars.Calendar;
 import org.elasticsearch.client.ml.job.config.Job;
@@ -35,7 +34,7 @@ import java.util.Objects;
 /**
  * Get the Scheduled Events for a Calendar
  */
-public class GetCalendarEventsRequest extends ActionRequest implements ToXContentObject {
+public class GetCalendarEventsRequest implements Validatable, ToXContentObject {
 
     public static final ParseField START = new ParseField("start");
     public static final ParseField END = new ParseField("end");
@@ -121,11 +120,6 @@ public class GetCalendarEventsRequest extends ActionRequest implements ToXConten
         this.jobId = jobId;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetCalendarsRequest.java

@@ -19,8 +19,7 @@
 
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.core.PageParams;
 import org.elasticsearch.client.ml.calendars.Calendar;
 import org.elasticsearch.common.xcontent.ObjectParser;
@@ -30,7 +29,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
 import java.io.IOException;
 import java.util.Objects;
 
-public class GetCalendarsRequest extends ActionRequest implements ToXContentObject {
+public class GetCalendarsRequest implements Validatable, ToXContentObject {
 
     public static final ObjectParser<GetCalendarsRequest, Void> PARSER =
             new ObjectParser<>("get_calendars_request", GetCalendarsRequest::new);
@@ -66,11 +65,6 @@ public class GetCalendarsRequest extends ActionRequest implements ToXContentObje
         this.pageParams = pageParams;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetCategoriesRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.core.PageParams;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
@@ -33,7 +32,7 @@ import java.util.Objects;
 /**
  * A request to retrieve categories of a given job
  */
-public class GetCategoriesRequest extends ActionRequest implements ToXContentObject {
+public class GetCategoriesRequest implements Validatable, ToXContentObject {
 
 
     public static final ParseField CATEGORY_ID = new ParseField("category_id");
@@ -88,11 +87,6 @@ public class GetCategoriesRequest extends ActionRequest implements ToXContentObj
         this.pageParams = pageParams;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.xcontent.ConstructingObjectParser;
@@ -38,7 +37,7 @@ import java.util.Objects;
  * {@code _all} explicitly gets all the datafeeds in the cluster
  * An empty request (no {@code datafeedId}s) implicitly gets all the datafeeds in the cluster
  */
-public class GetDatafeedRequest extends ActionRequest implements ToXContentObject {
+public class GetDatafeedRequest implements Validatable, ToXContentObject {
 
     public static final ParseField DATAFEED_IDS = new ParseField("datafeed_ids");
     public static final ParseField ALLOW_NO_DATAFEEDS = new ParseField("allow_no_datafeeds");
@@ -101,11 +100,6 @@ public class GetDatafeedRequest extends ActionRequest implements ToXContentObjec
         return allowNoDatafeeds;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(datafeedIds, allowNoDatafeeds);

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedStatsRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.Strings;
@@ -41,7 +40,7 @@ import java.util.Objects;
  * {@code _all} explicitly gets all the datafeeds' statistics in the cluster
  * An empty request (no {@code datafeedId}s) implicitly gets all the datafeeds' statistics in the cluster
  */
-public class GetDatafeedStatsRequest extends ActionRequest implements ToXContentObject {
+public class GetDatafeedStatsRequest implements Validatable, ToXContentObject {
 
     public static final ParseField ALLOW_NO_DATAFEEDS = new ParseField("allow_no_datafeeds");
 
@@ -128,11 +127,6 @@ public class GetDatafeedStatsRequest extends ActionRequest implements ToXContent
             Objects.equals(allowNoDatafeeds, that.allowNoDatafeeds);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetFiltersRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.core.PageParams;
 import org.elasticsearch.client.ml.job.config.MlFilter;
 import org.elasticsearch.common.xcontent.ObjectParser;
@@ -32,7 +31,7 @@ import java.util.Objects;
 /**
  * A request to retrieve {@link MlFilter}s
  */
-public class GetFiltersRequest extends ActionRequest implements ToXContentObject {
+public class GetFiltersRequest implements Validatable, ToXContentObject {
 
     public static final ObjectParser<GetFiltersRequest, Void> PARSER =
         new ObjectParser<>("get_filters_request", GetFiltersRequest::new);
@@ -83,11 +82,6 @@ public class GetFiltersRequest extends ActionRequest implements ToXContentObject
         this.size = size;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetInfluencersRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.core.PageParams;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
@@ -33,7 +32,7 @@ import java.util.Objects;
 /**
  * A request to retrieve influencers of a given job
  */
-public class GetInfluencersRequest extends ActionRequest implements ToXContentObject {
+public class GetInfluencersRequest implements Validatable, ToXContentObject {
 
     public static final ParseField EXCLUDE_INTERIM = new ParseField("exclude_interim");
     public static final ParseField START = new ParseField("start");
@@ -167,11 +166,6 @@ public class GetInfluencersRequest extends ActionRequest implements ToXContentOb
         this.descending = descending;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.xcontent.ConstructingObjectParser;
@@ -39,7 +38,7 @@ import java.util.Objects;
  * {@code _all} explicitly gets all the jobs in the cluster
  * An empty request (no {@code jobId}s) implicitly gets all the jobs in the cluster
  */
-public class GetJobRequest extends ActionRequest implements ToXContentObject {
+public class GetJobRequest implements Validatable, ToXContentObject {
 
     public static final ParseField JOB_IDS = new ParseField("job_ids");
     public static final ParseField ALLOW_NO_JOBS = new ParseField("allow_no_jobs");
@@ -101,11 +100,6 @@ public class GetJobRequest extends ActionRequest implements ToXContentObject {
         return allowNoJobs;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(jobIds, allowNoJobs);

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.Strings;
@@ -41,7 +40,7 @@ import java.util.Objects;
  * {@code _all} explicitly gets all the jobs' statistics in the cluster
  * An empty request (no {@code jobId}s) implicitly gets all the jobs' statistics in the cluster
  */
-public class GetJobStatsRequest extends ActionRequest implements ToXContentObject {
+public class GetJobStatsRequest implements Validatable, ToXContentObject {
 
     public static final ParseField ALLOW_NO_JOBS = new ParseField("allow_no_jobs");
 
@@ -128,11 +127,6 @@ public class GetJobStatsRequest extends ActionRequest implements ToXContentObjec
             Objects.equals(allowNoJobs, that.allowNoJobs);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetModelSnapshotsRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.core.PageParams;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
@@ -33,7 +32,7 @@ import java.util.Objects;
 /**
  * A request to retrieve information about model snapshots for a given job
  */
-public class GetModelSnapshotsRequest extends ActionRequest implements ToXContentObject {
+public class GetModelSnapshotsRequest implements Validatable, ToXContentObject {
 
 
     public static final ParseField SNAPSHOT_ID = new ParseField("snapshot_id");
@@ -153,11 +152,6 @@ public class GetModelSnapshotsRequest extends ActionRequest implements ToXConten
         this.desc = desc;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetOverallBucketsRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.Strings;
@@ -37,7 +36,7 @@ import java.util.Objects;
 /**
  * A request to retrieve overall buckets of set of jobs
  */
-public class GetOverallBucketsRequest extends ActionRequest implements ToXContentObject {
+public class GetOverallBucketsRequest implements Validatable, ToXContentObject {
 
     public static final ParseField TOP_N = new ParseField("top_n");
     public static final ParseField BUCKET_SPAN = new ParseField("bucket_span");
@@ -203,11 +202,6 @@ public class GetOverallBucketsRequest extends ActionRequest implements ToXConten
         return allowNoJobs;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/OpenJobRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.Strings;
@@ -35,7 +34,7 @@ import java.util.Objects;
 /**
  * Request to open a Machine Learning Job
  */
-public class OpenJobRequest extends ActionRequest implements ToXContentObject {
+public class OpenJobRequest implements Validatable, ToXContentObject {
 
     public static final ParseField TIMEOUT = new ParseField("timeout");
     public static final ConstructingObjectParser<OpenJobRequest, Void> PARSER = new ConstructingObjectParser<>(
@@ -88,11 +87,6 @@ public class OpenJobRequest extends ActionRequest implements ToXContentObject {
         this.timeout = timeout;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostCalendarEventRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.calendars.Calendar;
 import org.elasticsearch.client.ml.calendars.ScheduledEvent;
 import org.elasticsearch.common.ParseField;
@@ -35,7 +34,7 @@ import java.util.Objects;
 /**
  * Request to add a ScheduledEvent to a Machine Learning calendar
  */
-public class PostCalendarEventRequest extends ActionRequest implements ToXContentObject {
+public class PostCalendarEventRequest implements Validatable, ToXContentObject {
 
     private final String calendarId;
     private final List<ScheduledEvent> scheduledEvents;
@@ -78,11 +77,6 @@ public class PostCalendarEventRequest extends ActionRequest implements ToXConten
         return scheduledEvents;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostDataRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.bytes.BytesArray;
@@ -40,7 +39,7 @@ import java.util.Objects;
 /**
  * Request to post data to a Machine Learning job
  */
-public class PostDataRequest extends ActionRequest implements ToXContentObject {
+public class PostDataRequest implements Validatable, ToXContentObject {
 
     public static final ParseField RESET_START = new ParseField("reset_start");
     public static final ParseField RESET_END = new ParseField("reset_end");
@@ -159,11 +158,6 @@ public class PostDataRequest extends ActionRequest implements ToXContentObject {
             Objects.equals(xContentType, other.xContentType);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 3 - 9
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PreviewDatafeedRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.xcontent.ConstructingObjectParser;
@@ -31,9 +30,9 @@ import java.io.IOException;
 import java.util.Objects;
 
 /**
- * Request to preview a MachineLearning Datafeed 
+ * Request to preview a MachineLearning Datafeed
  */
-public class PreviewDatafeedRequest extends ActionRequest implements ToXContentObject {
+public class PreviewDatafeedRequest implements Validatable, ToXContentObject {
 
     public static final ConstructingObjectParser<PreviewDatafeedRequest, Void> PARSER = new ConstructingObjectParser<>(
         "open_datafeed_request", true, a -> new PreviewDatafeedRequest((String) a[0]));
@@ -61,11 +60,6 @@ public class PreviewDatafeedRequest extends ActionRequest implements ToXContentO
         return datafeedId;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutCalendarJobRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 
 import java.security.InvalidParameterException;
 import java.util.Arrays;
@@ -29,7 +28,7 @@ import java.util.Objects;
 /**
  * Request class for adding Machine Learning Jobs to an existing calendar
  */
-public class PutCalendarJobRequest extends ActionRequest {
+public class PutCalendarJobRequest implements Validatable {
 
     private final List<String> jobIds;
     private final String calendarId;
@@ -61,11 +60,6 @@ public class PutCalendarJobRequest extends ActionRequest {
         return calendarId;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(jobIds, calendarId);

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutCalendarRequest.java

@@ -19,8 +19,7 @@
 
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.calendars.Calendar;
 import org.elasticsearch.common.xcontent.ToXContentObject;
 import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -31,7 +30,7 @@ import java.util.Objects;
 /**
  * Request to create a new Machine Learning calendar
  */
-public class PutCalendarRequest extends ActionRequest implements ToXContentObject {
+public class PutCalendarRequest implements Validatable, ToXContentObject {
 
     private final Calendar calendar;
 
@@ -43,11 +42,6 @@ public class PutCalendarRequest extends ActionRequest implements ToXContentObjec
         return calendar;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         calendar.toXContent(builder, params);

+ 2 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutDatafeedRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.xcontent.ToXContentObject;
@@ -31,7 +30,7 @@ import java.util.Objects;
 /**
  * Request to create a new Machine Learning Datafeed given a {@link DatafeedConfig} configuration
  */
-public class PutDatafeedRequest extends ActionRequest implements ToXContentObject {
+public class PutDatafeedRequest implements Validatable, ToXContentObject {
 
     private final DatafeedConfig datafeed;
 
@@ -77,8 +76,4 @@ public class PutDatafeedRequest extends ActionRequest implements ToXContentObjec
         return Strings.toString(this);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
 }

+ 2 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutFilterRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.MlFilter;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.xcontent.ToXContentObject;
@@ -31,7 +30,7 @@ import java.util.Objects;
 /**
  * Request to create a new Machine Learning MlFilter given a {@link MlFilter} configuration
  */
-public class PutFilterRequest extends ActionRequest implements ToXContentObject {
+public class PutFilterRequest implements Validatable, ToXContentObject {
 
     private final MlFilter filter;
 
@@ -77,8 +76,4 @@ public class PutFilterRequest extends ActionRequest implements ToXContentObject
         return Strings.toString(this);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
 }

+ 2 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PutJobRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.xcontent.ToXContentObject;
@@ -31,7 +30,7 @@ import java.util.Objects;
 /**
  * Request to create a new Machine Learning Job given a {@link Job} configuration
  */
-public class PutJobRequest extends ActionRequest implements ToXContentObject {
+public class PutJobRequest implements Validatable, ToXContentObject {
 
     private final Job job;
 
@@ -77,8 +76,4 @@ public class PutJobRequest extends ActionRequest implements ToXContentObject {
         return Strings.toString(this);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
 }

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/RevertModelSnapshotRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.client.ml.job.process.ModelSnapshot;
 import org.elasticsearch.common.ParseField;
@@ -33,7 +32,7 @@ import java.util.Objects;
 /**
  * A request to revert to a specific model snapshot for a given job
  */
-public class RevertModelSnapshotRequest extends ActionRequest implements ToXContentObject {
+public class RevertModelSnapshotRequest implements Validatable, ToXContentObject {
 
 
     public static final ParseField DELETE_INTERVENING = new ParseField("delete_intervening_results");
@@ -82,11 +81,6 @@ public class RevertModelSnapshotRequest extends ActionRequest implements ToXCont
         this.deleteInterveningResults = deleteInterveningResults;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/SetUpgradeModeRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.unit.TimeValue;
 
@@ -28,7 +27,7 @@ import java.util.Objects;
 /**
  * Sets ML into upgrade_mode
  */
-public class SetUpgradeModeRequest extends ActionRequest {
+public class SetUpgradeModeRequest implements Validatable {
 
 
     public static final ParseField ENABLED = new ParseField("enabled");
@@ -67,11 +66,6 @@ public class SetUpgradeModeRequest extends ActionRequest {
         this.timeout = timeout;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(enabled, timeout);

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/StartDatafeedRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.unit.TimeValue;
@@ -33,7 +32,7 @@ import java.util.Objects;
 /**
  * Request to start a Datafeed
  */
-public class StartDatafeedRequest extends ActionRequest implements ToXContentObject {
+public class StartDatafeedRequest implements Validatable, ToXContentObject {
 
     public static final ParseField START = new ParseField("start");
     public static final ParseField END = new ParseField("end");
@@ -114,11 +113,6 @@ public class StartDatafeedRequest extends ActionRequest implements ToXContentObj
         this.timeout = timeout;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-       return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(datafeedId, start, end, timeout);

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/StopDatafeedRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.Strings;
@@ -39,7 +38,7 @@ import java.util.Objects;
 /**
  * Request to stop Machine Learning Datafeeds
  */
-public class StopDatafeedRequest extends ActionRequest implements ToXContentObject {
+public class StopDatafeedRequest implements Validatable, ToXContentObject {
 
     public static final ParseField TIMEOUT = new ParseField("timeout");
     public static final ParseField FORCE = new ParseField("force");
@@ -144,11 +143,6 @@ public class StopDatafeedRequest extends ActionRequest implements ToXContentObje
         this.allowNoDatafeeds = allowNoDatafeeds;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public int hashCode() {
         return Objects.hash(datafeedIds, timeout, force, allowNoDatafeeds);

+ 2 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateDatafeedRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.datafeed.DatafeedUpdate;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.xcontent.ToXContentObject;
@@ -32,7 +31,7 @@ import java.util.Objects;
  * Requests an update to a {@link org.elasticsearch.client.ml.datafeed.DatafeedConfig} with the passed {@link DatafeedUpdate}
  * settings
  */
-public class UpdateDatafeedRequest extends ActionRequest implements ToXContentObject {
+public class UpdateDatafeedRequest implements Validatable, ToXContentObject {
 
     private final DatafeedUpdate update;
 
@@ -73,8 +72,4 @@ public class UpdateDatafeedRequest extends ActionRequest implements ToXContentOb
         return Strings.toString(this);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
 }

+ 2 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateFilterRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.MlFilter;
 import org.elasticsearch.common.ParseField;
 import org.elasticsearch.common.Strings;
@@ -36,7 +35,7 @@ import java.util.TreeSet;
 /**
  * Updates an existing {@link MlFilter} configuration
  */
-public class UpdateFilterRequest extends ActionRequest implements ToXContentObject {
+public class UpdateFilterRequest implements Validatable, ToXContentObject {
 
     public static final ParseField ADD_ITEMS = new ParseField("add_items");
     public static final ParseField REMOVE_ITEMS = new ParseField("remove_items");
@@ -149,8 +148,4 @@ public class UpdateFilterRequest extends ActionRequest implements ToXContentObje
         return Strings.toString(this);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
 }

+ 2 - 7
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateJobRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.JobUpdate;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.xcontent.ToXContentObject;
@@ -32,7 +31,7 @@ import java.util.Objects;
  * Updates a {@link org.elasticsearch.client.ml.job.config.Job} with the passed {@link JobUpdate}
  * settings
  */
-public class UpdateJobRequest extends ActionRequest implements ToXContentObject {
+public class UpdateJobRequest implements Validatable, ToXContentObject {
 
     private final JobUpdate update;
 
@@ -73,8 +72,4 @@ public class UpdateJobRequest extends ActionRequest implements ToXContentObject
         return Strings.toString(this);
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
 }

+ 2 - 8
client/rest-high-level/src/main/java/org/elasticsearch/client/ml/UpdateModelSnapshotRequest.java

@@ -18,8 +18,7 @@
  */
 package org.elasticsearch.client.ml;
 
-import org.elasticsearch.action.ActionRequest;
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.Validatable;
 import org.elasticsearch.client.ml.job.config.Job;
 import org.elasticsearch.client.ml.job.process.ModelSnapshot;
 import org.elasticsearch.common.xcontent.ConstructingObjectParser;
@@ -32,7 +31,7 @@ import java.util.Objects;
 /**
  * A request to update information about an existing model snapshot for a given job
  */
-public class UpdateModelSnapshotRequest extends ActionRequest implements ToXContentObject {
+public class UpdateModelSnapshotRequest implements Validatable, ToXContentObject {
 
 
     public static final ConstructingObjectParser<UpdateModelSnapshotRequest, Void> PARSER = new ConstructingObjectParser<>(
@@ -93,11 +92,6 @@ public class UpdateModelSnapshotRequest extends ActionRequest implements ToXCont
         this.retain = retain;
     }
 
-    @Override
-    public ActionRequestValidationException validate() {
-        return null;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();

+ 12 - 18
client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java

@@ -83,7 +83,6 @@ import org.elasticsearch.cluster.metadata.AliasMetaData;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.cluster.metadata.MappingMetaData;
 import org.elasticsearch.common.Strings;
-import org.elasticsearch.common.ValidationException;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.settings.Setting;
 import org.elasticsearch.common.settings.Settings;
@@ -1451,8 +1450,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
 
     @SuppressWarnings("unchecked")
     public void testPutTemplate() throws Exception {
-        PutIndexTemplateRequest putTemplateRequest = new PutIndexTemplateRequest("my-template")
-            .patterns(Arrays.asList("pattern-1", "name-*"))
+        PutIndexTemplateRequest putTemplateRequest = new PutIndexTemplateRequest("my-template", List.of("pattern-1", "name-*"))
             .order(10)
             .create(randomBoolean())
             .settings(Settings.builder().put("number_of_shards", "3").put("number_of_replicas", "0"))
@@ -1478,8 +1476,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
     }
 
     public void testPutTemplateWithTypesUsingUntypedAPI() throws Exception {
-        PutIndexTemplateRequest putTemplateRequest = new PutIndexTemplateRequest("my-template")
-            .patterns(Arrays.asList("pattern-1", "name-*"))
+        PutIndexTemplateRequest putTemplateRequest = new PutIndexTemplateRequest("my-template", List.of("pattern-1", "name-*"))
             .order(10)
             .create(randomBoolean())
             .settings(Settings.builder().put("number_of_shards", "3").put("number_of_replicas", "0"))
@@ -1541,13 +1538,12 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         RestHighLevelClient client = highLevelClient();
 
         // Failed to validate because index patterns are missing
-        PutIndexTemplateRequest withoutPattern = new PutIndexTemplateRequest("t1");
-        ValidationException withoutPatternError = expectThrows(ValidationException.class,
-            () -> execute(withoutPattern, client.indices()::putTemplate, client.indices()::putTemplateAsync));
-        assertThat(withoutPatternError.validationErrors(), contains("index patterns are missing"));
+        IllegalArgumentException withoutPatternError = expectThrows(IllegalArgumentException.class,
+            () -> new PutIndexTemplateRequest("t1", randomBoolean() ? null : List.of()));
+        assertThat(withoutPatternError.getMessage(), containsString("index patterns are missing"));
 
         // Create-only specified but an template exists already
-        PutIndexTemplateRequest goodTemplate = new PutIndexTemplateRequest("t2").patterns(Arrays.asList("qa-*", "prod-*"));
+        PutIndexTemplateRequest goodTemplate = new PutIndexTemplateRequest("t2", List.of("qa-*", "prod-*"));
         assertTrue(execute(goodTemplate, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged());
         goodTemplate.create(true);
         ElasticsearchException alreadyExistsError = expectThrows(ElasticsearchException.class,
@@ -1558,8 +1554,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         assertTrue(execute(goodTemplate, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged());
 
         // Rejected due to unknown settings
-        PutIndexTemplateRequest unknownSettingTemplate = new PutIndexTemplateRequest("t3")
-            .patterns(Collections.singletonList("any"))
+        PutIndexTemplateRequest unknownSettingTemplate = new PutIndexTemplateRequest("t3", List.of("any"))
             .settings(Settings.builder().put("this-setting-does-not-exist", 100));
         ElasticsearchStatusException unknownSettingError = expectThrows(ElasticsearchStatusException.class,
             () -> execute(unknownSettingTemplate, client.indices()::putTemplate, client.indices()::putTemplateAsync));
@@ -1690,12 +1685,11 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
     public void testCRUDIndexTemplate() throws Exception {
         RestHighLevelClient client = highLevelClient();
 
-        PutIndexTemplateRequest putTemplate1 = new PutIndexTemplateRequest("template-1")
-            .patterns(Arrays.asList("pattern-1", "name-1")).alias(new Alias("alias-1"));
+        PutIndexTemplateRequest putTemplate1 = new PutIndexTemplateRequest("template-1", List.of("pattern-1", "name-1"))
+            .alias(new Alias("alias-1"));
         assertThat(execute(putTemplate1, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged(),
             equalTo(true));
-        PutIndexTemplateRequest putTemplate2 = new PutIndexTemplateRequest("template-2")
-            .patterns(Arrays.asList("pattern-2", "name-2"))
+        PutIndexTemplateRequest putTemplate2 = new PutIndexTemplateRequest("template-2", List.of("pattern-2", "name-2"))
             .mapping("{\"properties\": { \"name\": { \"type\": \"text\" }}}", XContentType.JSON)
             .settings(Settings.builder().put("number_of_shards", "2").put("number_of_replicas", "0"));
         assertThat(execute(putTemplate2, client.indices()::putTemplate, client.indices()::putTemplateAsync)
@@ -1770,8 +1764,8 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
         {
             for (String suffix : Arrays.asList("1", "2")) {
 
-                final PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("template-" + suffix)
-                    .patterns(Arrays.asList("pattern-" + suffix, "name-" + suffix))
+                final PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("template-" + suffix,
+                    List.of("pattern-" + suffix, "name-" + suffix))
                     .alias(new Alias("alias-" + suffix));
                 assertTrue(execute(putRequest, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged());
 

+ 3 - 3
client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java

@@ -1088,8 +1088,8 @@ public class IndicesRequestConvertersTests extends ESTestCase {
         names.put("foo^bar", "foo%5Ebar");
 
         PutIndexTemplateRequest putTemplateRequest =
-                new PutIndexTemplateRequest(ESTestCase.randomFrom(names.keySet()))
-                .patterns(Arrays.asList(ESTestCase.generateRandomStringArray(20, 100, false, false)));
+                new PutIndexTemplateRequest(ESTestCase.randomFrom(names.keySet()),
+                    List.of(ESTestCase.generateRandomStringArray(20, 100, false, false)));
         if (ESTestCase.randomBoolean()) {
             putTemplateRequest.order(ESTestCase.randomInt());
         }
@@ -1116,7 +1116,7 @@ public class IndicesRequestConvertersTests extends ESTestCase {
             putTemplateRequest.cause(cause);
             expectedParams.put("cause", cause);
         }
-        RequestConvertersTests.setRandomMasterTimeout(putTemplateRequest, expectedParams);
+        RequestConvertersTests.setRandomMasterTimeout(putTemplateRequest::masterNodeTimeout, expectedParams);
 
         Request request = IndicesRequestConverters.putTemplate(putTemplateRequest);
         Assert.assertThat(request.getEndpoint(), equalTo("/_template/" + names.get(putTemplateRequest.name())));

+ 12 - 11
client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java

@@ -100,7 +100,6 @@ import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.rest.RestStatus;
 
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -2144,8 +2143,10 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
         RestHighLevelClient client = highLevelClient();
 
         // tag::put-template-request
-        PutIndexTemplateRequest request = new PutIndexTemplateRequest("my-template"); // <1>
-        request.patterns(Arrays.asList("pattern-1", "log-*")); // <2>
+        PutIndexTemplateRequest request = new PutIndexTemplateRequest(
+            "my-template", // <1>
+            List.of("pattern-1", "log-*") // <2>
+        );
         // end::put-template-request
 
         // tag::put-template-request-settings
@@ -2292,8 +2293,8 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
     public void testGetTemplates() throws Exception {
         RestHighLevelClient client = highLevelClient();
         {
-            PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("my-template");
-            putRequest.patterns(Arrays.asList("pattern-1", "log-*"));
+            PutIndexTemplateRequest putRequest =
+                new PutIndexTemplateRequest("my-template", List.of("pattern-1", "log-*"));
             putRequest.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 1));
             putRequest.mapping(
                     "{\n" +
@@ -2357,8 +2358,8 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
     public void testTemplatesExist() throws Exception {
         final RestHighLevelClient client = highLevelClient();
         {
-            final PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("my-template");
-            putRequest.patterns(Collections.singletonList("foo"));
+            final PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("my-template",
+                List.of("foo"));
             assertTrue(client.indices().putTemplate(putRequest, RequestOptions.DEFAULT).isAcknowledged());
         }
 
@@ -2767,8 +2768,8 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
     public void testDeleteTemplate() throws Exception {
         RestHighLevelClient client = highLevelClient();
         {
-            PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("my-template");
-            putRequest.patterns(Arrays.asList("pattern-1", "log-*"));
+            PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("my-template",
+                List.of("pattern-1", "log-*"));
             putRequest.settings(Settings.builder().put("index.number_of_shards", 3));
             assertTrue(client.indices().putTemplate(putRequest, RequestOptions.DEFAULT).isAcknowledged());
         }
@@ -2793,8 +2794,8 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
         assertThat(acknowledged, equalTo(true));
 
         {
-            PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("my-template");
-            putRequest.patterns(Arrays.asList("pattern-1", "log-*"));
+            PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("my-template",
+                List.of("pattern-1", "log-*"));
             putRequest.settings(Settings.builder().put("index.number_of_shards", 3));
             assertTrue(client.indices().putTemplate(putRequest, RequestOptions.DEFAULT).isAcknowledged());
         }

+ 40 - 40
client/rest-high-level/src/test/java/org/elasticsearch/client/indices/PutIndexTemplateRequestTests.java

@@ -18,52 +18,45 @@
  */
 package org.elasticsearch.client.indices;
 
-import org.elasticsearch.action.ActionRequestValidationException;
 import org.elasticsearch.action.admin.indices.alias.Alias;
+import org.elasticsearch.client.AbstractRequestTestCase;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentHelper;
 import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.test.AbstractXContentTestCase;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.test.ESTestCase;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
-import java.util.Arrays;
-import java.util.Collections;
+import java.util.List;
 
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.nullValue;
-import static org.hamcrest.core.Is.is;
 
-public class PutIndexTemplateRequestTests extends AbstractXContentTestCase<PutIndexTemplateRequest> {
-    public void testValidateErrorMessage() throws Exception {
-        expectThrows(IllegalArgumentException.class, () -> new PutIndexTemplateRequest(null));
-        expectThrows(IllegalArgumentException.class, () -> new PutIndexTemplateRequest("test").name(null));
-        PutIndexTemplateRequest request = new PutIndexTemplateRequest("test");
-        ActionRequestValidationException withoutPattern = request.validate();
-        assertThat(withoutPattern.getMessage(), containsString("index patterns are missing"));
-
-        request.name("foo");
-        ActionRequestValidationException withoutIndexPatterns = request.validate();
-        assertThat(withoutIndexPatterns.validationErrors(), hasSize(1));
-        assertThat(withoutIndexPatterns.getMessage(), containsString("index patterns are missing"));
+public class PutIndexTemplateRequestTests extends AbstractRequestTestCase<PutIndexTemplateRequest,
+    org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest> {
 
-        request.patterns(Collections.singletonList("test-*"));
-        ActionRequestValidationException noError = request.validate();
-        assertThat(noError, is(nullValue()));
+    public void testValidateErrorMessage() throws Exception {
+        expectThrows(IllegalArgumentException.class, () -> new PutIndexTemplateRequest(null, null));
+        expectThrows(IllegalArgumentException.class, () -> new PutIndexTemplateRequest("test", List.of("index")).name(null));
+        Exception e = expectThrows(IllegalArgumentException.class, () -> new PutIndexTemplateRequest("test", null));
+        assertThat(e.getMessage(), containsString("index patterns are missing"));
+        e = expectThrows(IllegalArgumentException.class, () -> new PutIndexTemplateRequest("test", List.of()));
+        assertThat(e.getMessage(), containsString("index patterns are missing"));
+        new PutIndexTemplateRequest("test", List.of("index"));
     }
 
     @Override
-    protected PutIndexTemplateRequest createTestInstance() {
-        PutIndexTemplateRequest request = new PutIndexTemplateRequest("test");
+    protected PutIndexTemplateRequest createClientTestInstance() {
+        PutIndexTemplateRequest request = new PutIndexTemplateRequest("test",
+            List.of(ESTestCase.generateRandomStringArray(20, 100, false, false)));
         if (randomBoolean()) {
             request.version(randomInt());
         }
         if (randomBoolean()) {
             request.order(randomInt());
         }
-        request.patterns(Arrays.asList(generateRandomStringArray(20, 100, false, false)));
         int numAlias = between(0, 5);
         for (int i = 0; i < numAlias; i++) {
             // some ASCII or Latin-1 control characters, especially newline, can lead to
@@ -80,9 +73,10 @@ public class PutIndexTemplateRequestTests extends AbstractXContentTestCase<PutIn
         if (randomBoolean()) {
             try {
                 request.mapping(XContentFactory.jsonBuilder().startObject()
+                    .startObject("_doc")
                     .startObject("properties")
                     .startObject("field-" + randomInt()).field("type", randomFrom("keyword", "text")).endObject()
-                    .endObject().endObject());
+                    .endObject().endObject().endObject());
             } catch (IOException ex) {
                 throw new UncheckedIOException(ex);
             }
@@ -94,23 +88,29 @@ public class PutIndexTemplateRequestTests extends AbstractXContentTestCase<PutIn
     }
 
     @Override
-    protected PutIndexTemplateRequest doParseInstance(XContentParser parser) throws IOException {
-        return new PutIndexTemplateRequest("test").source(parser.map());
+    protected org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest doParseToServerInstance(
+        XContentParser parser) throws IOException {
+        return new org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest("test").source(parser.map());
     }
 
     @Override
-    protected void assertEqualInstances(PutIndexTemplateRequest expected, PutIndexTemplateRequest actual) {
-        assertNotSame(expected, actual);
-        assertThat(actual.version(), equalTo(expected.version()));
-        assertThat(actual.order(), equalTo(expected.order()));
-        assertThat(actual.patterns(), equalTo(expected.patterns()));
-        assertThat(actual.aliases(), equalTo(expected.aliases()));
-        assertThat(actual.mappings(), equalTo(expected.mappings()));
-        assertThat(actual.settings(), equalTo(expected.settings()));
+    protected void assertInstances(org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest serverInstance,
+                                   PutIndexTemplateRequest clientTestInstance) {
+        assertNotSame(serverInstance, clientTestInstance);
+        assertThat(serverInstance.version(), equalTo(clientTestInstance.version()));
+        assertThat(serverInstance.order(), equalTo(clientTestInstance.order()));
+        assertThat(serverInstance.patterns(), equalTo(clientTestInstance.patterns()));
+        assertThat(serverInstance.aliases(), equalTo(clientTestInstance.aliases()));
+        String mapping = null;
+        if (clientTestInstance.mappings() != null) {
+            try {
+                mapping = XContentHelper.convertToJson(clientTestInstance.mappings(), false, XContentType.JSON);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+        assertThat(serverInstance.mappings().get("_doc"), equalTo(mapping));
+        assertThat(serverInstance.settings(), equalTo(clientTestInstance.settings()));
     }
 
-    @Override
-    protected boolean supportsUnknownFields() {
-        return false;
-    }
 }