Browse Source

[Connectors API] Relax strict response parsing for get/list operations (#104909)

Jedr Blaszyk 1 year ago
parent
commit
d2d28ecc4f
20 changed files with 455 additions and 167 deletions
  1. 5 0
      docs/changelog/104909.yaml
  2. 28 24
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/Connector.java
  3. 16 12
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorIndexService.java
  4. 51 0
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorSearchResult.java
  5. 89 0
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorsAPISearchResult.java
  6. 4 8
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/GetConnectorAction.java
  7. 5 5
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/ListConnectorAction.java
  8. 65 63
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJob.java
  9. 15 15
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobIndexService.java
  10. 52 0
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobSearchResult.java
  11. 4 4
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/action/GetConnectorSyncJobAction.java
  12. 4 3
      x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/action/ListConnectorSyncJobsAction.java
  13. 8 1
      x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/ConnectorIndexServiceTests.java
  14. 28 0
      x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/ConnectorTestUtils.java
  15. 3 13
      x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/action/GetConnectorActionResponseBWCSerializingTests.java
  16. 4 1
      x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/action/ListConnectorActionResponseBWCSerializingTests.java
  17. 40 10
      x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobIndexServiceTests.java
  18. 30 1
      x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobTestUtils.java
  19. 3 6
      x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobTests.java
  20. 1 1
      x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/syncjob/action/ListConnectorSyncJobsActionResponseBWCSerializingTests.java

+ 5 - 0
docs/changelog/104909.yaml

@@ -0,0 +1,5 @@
+pr: 104909
+summary: "[Connectors API] Relax strict response parsing for get/list operations"
+area: Application
+type: enhancement
+issues: []

+ 28 - 24
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/Connector.java

@@ -356,34 +356,38 @@ public class Connector implements NamedWriteable, ToXContentObject {
         return PARSER.parse(parser, docId);
     }
 
+    public void toInnerXContent(XContentBuilder builder, Params params) throws IOException {
+        // The "id": connectorId is included in GET and LIST responses to provide the connector's docID.
+        // Note: This ID is not written to the Elasticsearch index; it's only for API response purposes.
+        if (connectorId != null) {
+            builder.field(ID_FIELD.getPreferredName(), connectorId);
+        }
+        builder.field(API_KEY_ID_FIELD.getPreferredName(), apiKeyId);
+        builder.xContentValuesMap(CONFIGURATION_FIELD.getPreferredName(), configuration);
+        builder.xContentValuesMap(CUSTOM_SCHEDULING_FIELD.getPreferredName(), customScheduling);
+        builder.field(DESCRIPTION_FIELD.getPreferredName(), description);
+        builder.field(ERROR_FIELD.getPreferredName(), error);
+        builder.field(FEATURES_FIELD.getPreferredName(), features);
+        builder.xContentList(FILTERING_FIELD.getPreferredName(), filtering);
+        builder.field(INDEX_NAME_FIELD.getPreferredName(), indexName);
+        builder.field(IS_NATIVE_FIELD.getPreferredName(), isNative);
+        builder.field(LANGUAGE_FIELD.getPreferredName(), language);
+        builder.field(LAST_SEEN_FIELD.getPreferredName(), lastSeen);
+        syncInfo.toXContent(builder, params);
+        builder.field(NAME_FIELD.getPreferredName(), name);
+        builder.field(PIPELINE_FIELD.getPreferredName(), pipeline);
+        builder.field(SCHEDULING_FIELD.getPreferredName(), scheduling);
+        builder.field(SERVICE_TYPE_FIELD.getPreferredName(), serviceType);
+        builder.field(SYNC_CURSOR_FIELD.getPreferredName(), syncCursor);
+        builder.field(STATUS_FIELD.getPreferredName(), status.toString());
+        builder.field(SYNC_NOW_FIELD.getPreferredName(), syncNow);
+    }
+
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();
         {
-            // The "id": connectorId is included in GET and LIST responses to provide the connector's docID.
-            // Note: This ID is not written to the Elasticsearch index; it's only for API response purposes.
-            if (connectorId != null) {
-                builder.field(ID_FIELD.getPreferredName(), connectorId);
-            }
-            builder.field(API_KEY_ID_FIELD.getPreferredName(), apiKeyId);
-            builder.xContentValuesMap(CONFIGURATION_FIELD.getPreferredName(), configuration);
-            builder.xContentValuesMap(CUSTOM_SCHEDULING_FIELD.getPreferredName(), customScheduling);
-            builder.field(DESCRIPTION_FIELD.getPreferredName(), description);
-            builder.field(ERROR_FIELD.getPreferredName(), error);
-            builder.field(FEATURES_FIELD.getPreferredName(), features);
-            builder.xContentList(FILTERING_FIELD.getPreferredName(), filtering);
-            builder.field(INDEX_NAME_FIELD.getPreferredName(), indexName);
-            builder.field(IS_NATIVE_FIELD.getPreferredName(), isNative);
-            builder.field(LANGUAGE_FIELD.getPreferredName(), language);
-            builder.field(LAST_SEEN_FIELD.getPreferredName(), lastSeen);
-            syncInfo.toXContent(builder, params);
-            builder.field(NAME_FIELD.getPreferredName(), name);
-            builder.field(PIPELINE_FIELD.getPreferredName(), pipeline);
-            builder.field(SCHEDULING_FIELD.getPreferredName(), scheduling);
-            builder.field(SERVICE_TYPE_FIELD.getPreferredName(), serviceType);
-            builder.field(SYNC_CURSOR_FIELD.getPreferredName(), syncCursor);
-            builder.field(STATUS_FIELD.getPreferredName(), status.toString());
-            builder.field(SYNC_NOW_FIELD.getPreferredName(), syncNow);
+            toInnerXContent(builder, params);
         }
         builder.endObject();
         return builder;

+ 16 - 12
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorIndexService.java

@@ -30,7 +30,6 @@ import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
 import org.elasticsearch.search.sort.SortOrder;
 import org.elasticsearch.xcontent.ToXContent;
-import org.elasticsearch.xcontent.XContentType;
 import org.elasticsearch.xpack.application.connector.action.PostConnectorAction;
 import org.elasticsearch.xpack.application.connector.action.PutConnectorAction;
 import org.elasticsearch.xpack.application.connector.action.UpdateConnectorConfigurationAction;
@@ -175,7 +174,7 @@ public class ConnectorIndexService {
      * @param connectorId The id of the connector object.
      * @param listener    The action listener to invoke on response/failure.
      */
-    public void getConnector(String connectorId, ActionListener<Connector> listener) {
+    public void getConnector(String connectorId, ActionListener<ConnectorSearchResult> listener) {
         try {
             final GetRequest getRequest = new GetRequest(CONNECTOR_INDEX_NAME).id(connectorId).realtime(true);
 
@@ -185,11 +184,11 @@ public class ConnectorIndexService {
                     return;
                 }
                 try {
-                    final Connector connector = Connector.fromXContentBytes(
-                        getResponse.getSourceAsBytesRef(),
-                        connectorId,
-                        XContentType.JSON
-                    );
+                    final ConnectorSearchResult connector = new ConnectorSearchResult.Builder().setId(connectorId)
+                        .setResultBytes(getResponse.getSourceAsBytesRef())
+                        .setResultMap(getResponse.getSourceAsMap())
+                        .build();
+
                     l.onResponse(connector);
                 } catch (Exception e) {
                     listener.onFailure(e);
@@ -567,7 +566,9 @@ public class ConnectorIndexService {
             String connectorId = request.getConnectorId();
             getConnector(connectorId, listener.delegateFailure((l, connector) -> {
 
-                ConnectorStatus prevStatus = connector.getStatus();
+                ConnectorStatus prevStatus = ConnectorStatus.connectorStatus(
+                    (String) connector.getResultMap().get(Connector.STATUS_FIELD.getPreferredName())
+                );
                 ConnectorStatus newStatus = prevStatus == ConnectorStatus.CREATED
                     ? ConnectorStatus.CREATED
                     : ConnectorStatus.NEEDS_CONFIGURATION;
@@ -603,20 +604,23 @@ public class ConnectorIndexService {
     }
 
     private static ConnectorIndexService.ConnectorResult mapSearchResponseToConnectorList(SearchResponse response) {
-        final List<Connector> connectorResults = Arrays.stream(response.getHits().getHits())
+        final List<ConnectorSearchResult> connectorResults = Arrays.stream(response.getHits().getHits())
             .map(ConnectorIndexService::hitToConnector)
             .toList();
         return new ConnectorIndexService.ConnectorResult(connectorResults, (int) response.getHits().getTotalHits().value);
     }
 
-    private static Connector hitToConnector(SearchHit searchHit) {
+    private static ConnectorSearchResult hitToConnector(SearchHit searchHit) {
 
         // todo: don't return sensitive data from configuration in list endpoint
 
-        return Connector.fromXContentBytes(searchHit.getSourceRef(), searchHit.getId(), XContentType.JSON);
+        return new ConnectorSearchResult.Builder().setId(searchHit.getId())
+            .setResultBytes(searchHit.getSourceRef())
+            .setResultMap(searchHit.getSourceAsMap())
+            .build();
     }
 
-    public record ConnectorResult(List<Connector> connectors, long totalResults) {}
+    public record ConnectorResult(List<ConnectorSearchResult> connectors, long totalResults) {}
 
     /**
      * Listeners that checks failures for IndexNotFoundException, and transforms them in ResourceNotFoundException,

+ 51 - 0
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorSearchResult.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.application.connector;
+
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.io.stream.StreamInput;
+
+import java.io.IOException;
+import java.util.Map;
+
+public class ConnectorSearchResult extends ConnectorsAPISearchResult {
+
+    public ConnectorSearchResult(StreamInput in) throws IOException {
+        super(in);
+    }
+
+    private ConnectorSearchResult(BytesReference resultBytes, Map<String, Object> resultMap, String id) {
+        super(resultBytes, resultMap, id);
+    }
+
+    public static class Builder {
+
+        private BytesReference resultBytes;
+        private Map<String, Object> resultMap;
+        private String id;
+
+        public Builder setResultBytes(BytesReference resultBytes) {
+            this.resultBytes = resultBytes;
+            return this;
+        }
+
+        public Builder setResultMap(Map<String, Object> resultMap) {
+            this.resultMap = resultMap;
+            return this;
+        }
+
+        public Builder setId(String id) {
+            this.id = id;
+            return this;
+        }
+
+        public ConnectorSearchResult build() {
+            return new ConnectorSearchResult(resultBytes, resultMap, id);
+        }
+    }
+}

+ 89 - 0
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorsAPISearchResult.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.application.connector;
+
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.common.io.stream.Writeable;
+import org.elasticsearch.xcontent.ToXContentObject;
+import org.elasticsearch.xcontent.XContentBuilder;
+import org.elasticsearch.xpack.application.connector.syncjob.ConnectorSyncJob;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Represents the outcome of a search query in the connectors and sync job index, encapsulating the search result.
+ * It includes a raw byte reference to the result which can be deserialized into a {@link Connector} or {@link ConnectorSyncJob} object,
+ * and a result map for returning the data without strict deserialization.
+ */
+public class ConnectorsAPISearchResult implements Writeable, ToXContentObject {
+
+    private final BytesReference resultBytes;
+    private final Map<String, Object> resultMap;
+    private final String docId;
+
+    protected ConnectorsAPISearchResult(BytesReference resultBytes, Map<String, Object> resultMap, String id) {
+        this.resultBytes = resultBytes;
+        this.resultMap = resultMap;
+        this.docId = id;
+    }
+
+    public ConnectorsAPISearchResult(StreamInput in) throws IOException {
+        this.resultBytes = in.readBytesReference();
+        this.resultMap = in.readGenericMap();
+        this.docId = in.readString();
+    }
+
+    public BytesReference getSourceRef() {
+        return resultBytes;
+    }
+
+    public Map<String, Object> getResultMap() {
+        return resultMap;
+    }
+
+    public String getDocId() {
+        return docId;
+    }
+
+    @Override
+    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+        builder.startObject();
+        {
+            builder.field("id", docId);
+            builder.mapContents(resultMap);
+        }
+        builder.endObject();
+        return builder;
+    }
+
+    @Override
+    public void writeTo(StreamOutput out) throws IOException {
+        out.writeBytesReference(resultBytes);
+        out.writeGenericMap(resultMap);
+        out.writeString(docId);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ConnectorsAPISearchResult that = (ConnectorsAPISearchResult) o;
+        return Objects.equals(resultBytes, that.resultBytes)
+            && Objects.equals(resultMap, that.resultMap)
+            && Objects.equals(docId, that.docId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(resultBytes, resultMap, docId);
+    }
+}

+ 4 - 8
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/GetConnectorAction.java

@@ -19,7 +19,7 @@ import org.elasticsearch.xcontent.ParseField;
 import org.elasticsearch.xcontent.ToXContentObject;
 import org.elasticsearch.xcontent.XContentBuilder;
 import org.elasticsearch.xcontent.XContentParser;
-import org.elasticsearch.xpack.application.connector.Connector;
+import org.elasticsearch.xpack.application.connector.ConnectorSearchResult;
 
 import java.io.IOException;
 import java.util.Objects;
@@ -110,15 +110,15 @@ public class GetConnectorAction {
 
     public static class Response extends ActionResponse implements ToXContentObject {
 
-        private final Connector connector;
+        private final ConnectorSearchResult connector;
 
-        public Response(Connector connector) {
+        public Response(ConnectorSearchResult connector) {
             this.connector = connector;
         }
 
         public Response(StreamInput in) throws IOException {
             super(in);
-            this.connector = new Connector(in);
+            this.connector = new ConnectorSearchResult(in);
         }
 
         @Override
@@ -131,10 +131,6 @@ public class GetConnectorAction {
             return connector.toXContent(builder, params);
         }
 
-        public static GetConnectorAction.Response fromXContent(XContentParser parser, String docId) throws IOException {
-            return new GetConnectorAction.Response(Connector.fromXContent(parser, docId));
-        }
-
         @Override
         public boolean equals(Object o) {
             if (this == o) return true;

+ 5 - 5
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/action/ListConnectorAction.java

@@ -18,7 +18,7 @@ import org.elasticsearch.xcontent.ParseField;
 import org.elasticsearch.xcontent.ToXContentObject;
 import org.elasticsearch.xcontent.XContentBuilder;
 import org.elasticsearch.xcontent.XContentParser;
-import org.elasticsearch.xpack.application.connector.Connector;
+import org.elasticsearch.xpack.application.connector.ConnectorSearchResult;
 import org.elasticsearch.xpack.core.action.util.PageParams;
 import org.elasticsearch.xpack.core.action.util.QueryPage;
 
@@ -105,14 +105,14 @@ public class ListConnectorAction {
 
         public static final ParseField RESULT_FIELD = new ParseField("results");
 
-        final QueryPage<Connector> queryPage;
+        final QueryPage<ConnectorSearchResult> queryPage;
 
         public Response(StreamInput in) throws IOException {
             super(in);
-            this.queryPage = new QueryPage<>(in, Connector::new);
+            this.queryPage = new QueryPage<>(in, ConnectorSearchResult::new);
         }
 
-        public Response(List<Connector> items, Long totalResults) {
+        public Response(List<ConnectorSearchResult> items, Long totalResults) {
             this.queryPage = new QueryPage<>(items, totalResults, RESULT_FIELD);
         }
 
@@ -126,7 +126,7 @@ public class ListConnectorAction {
             return queryPage.toXContent(builder, params);
         }
 
-        public QueryPage<Connector> queryPage() {
+        public QueryPage<ConnectorSearchResult> queryPage() {
             return queryPage;
         }
 

+ 65 - 63
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJob.java

@@ -200,7 +200,7 @@ public class ConnectorSyncJob implements Writeable, ToXContentObject {
         this.createdAt = createdAt;
         this.deletedDocumentCount = deletedDocumentCount;
         this.error = error;
-        this.id = Objects.requireNonNull(id, "[id] cannot be null");
+        this.id = id;
         this.indexedDocumentCount = indexedDocumentCount;
         this.indexedDocumentVolume = indexedDocumentVolume;
         this.jobType = Objects.requireNonNullElse(jobType, ConnectorSyncJobType.FULL);
@@ -235,10 +235,10 @@ public class ConnectorSyncJob implements Writeable, ToXContentObject {
     }
 
     @SuppressWarnings("unchecked")
-    private static final ConstructingObjectParser<ConnectorSyncJob, Void> PARSER = new ConstructingObjectParser<>(
+    private static final ConstructingObjectParser<ConnectorSyncJob, String> PARSER = new ConstructingObjectParser<>(
         "connector_sync_job",
         true,
-        (args) -> {
+        (args, docId) -> {
             int i = 0;
             return new Builder().setCancellationRequestedAt((Instant) args[i++])
                 .setCanceledAt((Instant) args[i++])
@@ -247,7 +247,7 @@ public class ConnectorSyncJob implements Writeable, ToXContentObject {
                 .setCreatedAt((Instant) args[i++])
                 .setDeletedDocumentCount((Long) args[i++])
                 .setError((String) args[i++])
-                .setId((String) args[i++])
+                .setId(docId)
                 .setIndexedDocumentCount((Long) args[i++])
                 .setIndexedDocumentVolume((Long) args[i++])
                 .setJobType((ConnectorSyncJobType) args[i++])
@@ -295,7 +295,6 @@ public class ConnectorSyncJob implements Writeable, ToXContentObject {
         );
         PARSER.declareLong(constructorArg(), DELETED_DOCUMENT_COUNT_FIELD);
         PARSER.declareStringOrNull(optionalConstructorArg(), ERROR_FIELD);
-        PARSER.declareString(constructorArg(), ID_FIELD);
         PARSER.declareLong(constructorArg(), INDEXED_DOCUMENT_COUNT_FIELD);
         PARSER.declareLong(constructorArg(), INDEXED_DOCUMENT_VOLUME_FIELD);
         PARSER.declareField(
@@ -383,16 +382,16 @@ public class ConnectorSyncJob implements Writeable, ToXContentObject {
         );
     }
 
-    public static ConnectorSyncJob fromXContentBytes(BytesReference source, XContentType xContentType) {
+    public static ConnectorSyncJob fromXContentBytes(BytesReference source, String docId, XContentType xContentType) {
         try (XContentParser parser = XContentHelper.createParser(XContentParserConfiguration.EMPTY, source, xContentType)) {
-            return ConnectorSyncJob.fromXContent(parser);
+            return ConnectorSyncJob.fromXContent(parser, docId);
         } catch (IOException e) {
             throw new ElasticsearchParseException("Failed to parse a connector sync job document.", e);
         }
     }
 
-    public static ConnectorSyncJob fromXContent(XContentParser parser) throws IOException {
-        return PARSER.parse(parser, null);
+    public static ConnectorSyncJob fromXContent(XContentParser parser, String docId) throws IOException {
+        return PARSER.parse(parser, docId);
     }
 
     public static Connector syncJobConnectorFromXContentBytes(BytesReference source, String connectorId, XContentType xContentType) {
@@ -479,70 +478,73 @@ public class ConnectorSyncJob implements Writeable, ToXContentObject {
         return workerHostname;
     }
 
-    @Override
-    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
-        builder.startObject();
+    public void toInnerXContent(XContentBuilder builder, Params params) throws IOException {
+        if (cancelationRequestedAt != null) {
+            builder.field(CANCELATION_REQUESTED_AT_FIELD.getPreferredName(), cancelationRequestedAt);
+        }
+        if (canceledAt != null) {
+            builder.field(CANCELED_AT_FIELD.getPreferredName(), canceledAt);
+        }
+        if (completedAt != null) {
+            builder.field(COMPLETED_AT_FIELD.getPreferredName(), completedAt);
+        }
+
+        builder.startObject(CONNECTOR_FIELD.getPreferredName());
         {
-            if (cancelationRequestedAt != null) {
-                builder.field(CANCELATION_REQUESTED_AT_FIELD.getPreferredName(), cancelationRequestedAt);
-            }
-            if (canceledAt != null) {
-                builder.field(CANCELED_AT_FIELD.getPreferredName(), canceledAt);
+            if (connector.getConnectorId() != null) {
+                builder.field(Connector.ID_FIELD.getPreferredName(), connector.getConnectorId());
             }
-            if (completedAt != null) {
-                builder.field(COMPLETED_AT_FIELD.getPreferredName(), completedAt);
+            if (connector.getSyncJobFiltering() != null) {
+                builder.field(Connector.FILTERING_FIELD.getPreferredName(), connector.getSyncJobFiltering());
             }
-
-            builder.startObject(CONNECTOR_FIELD.getPreferredName());
-            {
-                if (connector.getConnectorId() != null) {
-                    builder.field(Connector.ID_FIELD.getPreferredName(), connector.getConnectorId());
-                }
-                if (connector.getSyncJobFiltering() != null) {
-                    builder.field(Connector.FILTERING_FIELD.getPreferredName(), connector.getSyncJobFiltering());
-                }
-                if (connector.getIndexName() != null) {
-                    builder.field(Connector.INDEX_NAME_FIELD.getPreferredName(), connector.getIndexName());
-                }
-                if (connector.getLanguage() != null) {
-                    builder.field(Connector.LANGUAGE_FIELD.getPreferredName(), connector.getLanguage());
-                }
-                if (connector.getPipeline() != null) {
-                    builder.field(Connector.PIPELINE_FIELD.getPreferredName(), connector.getPipeline());
-                }
-                if (connector.getServiceType() != null) {
-                    builder.field(Connector.SERVICE_TYPE_FIELD.getPreferredName(), connector.getServiceType());
-                }
-                if (connector.getConfiguration() != null) {
-                    builder.field(Connector.CONFIGURATION_FIELD.getPreferredName(), connector.getConfiguration());
-                }
+            if (connector.getIndexName() != null) {
+                builder.field(Connector.INDEX_NAME_FIELD.getPreferredName(), connector.getIndexName());
             }
-            builder.endObject();
-
-            builder.field(CREATED_AT_FIELD.getPreferredName(), createdAt);
-            builder.field(DELETED_DOCUMENT_COUNT_FIELD.getPreferredName(), deletedDocumentCount);
-            if (error != null) {
-                builder.field(ERROR_FIELD.getPreferredName(), error);
+            if (connector.getLanguage() != null) {
+                builder.field(Connector.LANGUAGE_FIELD.getPreferredName(), connector.getLanguage());
             }
-            builder.field(ID_FIELD.getPreferredName(), id);
-            builder.field(INDEXED_DOCUMENT_COUNT_FIELD.getPreferredName(), indexedDocumentCount);
-            builder.field(INDEXED_DOCUMENT_VOLUME_FIELD.getPreferredName(), indexedDocumentVolume);
-            builder.field(JOB_TYPE_FIELD.getPreferredName(), jobType);
-            if (lastSeen != null) {
-                builder.field(LAST_SEEN_FIELD.getPreferredName(), lastSeen);
+            if (connector.getPipeline() != null) {
+                builder.field(Connector.PIPELINE_FIELD.getPreferredName(), connector.getPipeline());
             }
-            builder.field(METADATA_FIELD.getPreferredName(), metadata);
-            if (startedAt != null) {
-                builder.field(STARTED_AT_FIELD.getPreferredName(), startedAt);
+            if (connector.getServiceType() != null) {
+                builder.field(Connector.SERVICE_TYPE_FIELD.getPreferredName(), connector.getServiceType());
             }
-            builder.field(STATUS_FIELD.getPreferredName(), status);
-            builder.field(TOTAL_DOCUMENT_COUNT_FIELD.getPreferredName(), totalDocumentCount);
-            builder.field(TRIGGER_METHOD_FIELD.getPreferredName(), triggerMethod);
-            if (workerHostname != null) {
-                builder.field(WORKER_HOSTNAME_FIELD.getPreferredName(), workerHostname);
+            if (connector.getConfiguration() != null) {
+                builder.field(Connector.CONFIGURATION_FIELD.getPreferredName(), connector.getConfiguration());
             }
         }
         builder.endObject();
+
+        builder.field(CREATED_AT_FIELD.getPreferredName(), createdAt);
+        builder.field(DELETED_DOCUMENT_COUNT_FIELD.getPreferredName(), deletedDocumentCount);
+        if (error != null) {
+            builder.field(ERROR_FIELD.getPreferredName(), error);
+        }
+        builder.field(INDEXED_DOCUMENT_COUNT_FIELD.getPreferredName(), indexedDocumentCount);
+        builder.field(INDEXED_DOCUMENT_VOLUME_FIELD.getPreferredName(), indexedDocumentVolume);
+        builder.field(JOB_TYPE_FIELD.getPreferredName(), jobType);
+        if (lastSeen != null) {
+            builder.field(LAST_SEEN_FIELD.getPreferredName(), lastSeen);
+        }
+        builder.field(METADATA_FIELD.getPreferredName(), metadata);
+        if (startedAt != null) {
+            builder.field(STARTED_AT_FIELD.getPreferredName(), startedAt);
+        }
+        builder.field(STATUS_FIELD.getPreferredName(), status);
+        builder.field(TOTAL_DOCUMENT_COUNT_FIELD.getPreferredName(), totalDocumentCount);
+        builder.field(TRIGGER_METHOD_FIELD.getPreferredName(), triggerMethod);
+        if (workerHostname != null) {
+            builder.field(WORKER_HOSTNAME_FIELD.getPreferredName(), workerHostname);
+        }
+    }
+
+    @Override
+    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+        builder.startObject();
+        {
+            toInnerXContent(builder, params);
+        }
+        builder.endObject();
         return builder;
     }
 

+ 15 - 15
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobIndexService.java

@@ -97,14 +97,11 @@ public class ConnectorSyncJobIndexService {
                 );
 
                 try {
-                    String syncJobId = generateId();
 
-                    final IndexRequest indexRequest = new IndexRequest(CONNECTOR_SYNC_JOB_INDEX_NAME).id(syncJobId)
-                        .opType(DocWriteRequest.OpType.INDEX)
+                    final IndexRequest indexRequest = new IndexRequest(CONNECTOR_SYNC_JOB_INDEX_NAME).opType(DocWriteRequest.OpType.INDEX)
                         .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
 
-                    ConnectorSyncJob syncJob = new ConnectorSyncJob.Builder().setId(syncJobId)
-                        .setJobType(jobType)
+                    ConnectorSyncJob syncJob = new ConnectorSyncJob.Builder().setJobType(jobType)
                         .setTriggerMethod(triggerMethod)
                         .setStatus(ConnectorSyncJob.DEFAULT_INITIAL_STATUS)
                         .setConnector(connector)
@@ -195,7 +192,7 @@ public class ConnectorSyncJobIndexService {
      * @param connectorSyncJobId The id of the connector sync job object.
      * @param listener           The action listener to invoke on response/failure.
      */
-    public void getConnectorSyncJob(String connectorSyncJobId, ActionListener<ConnectorSyncJob> listener) {
+    public void getConnectorSyncJob(String connectorSyncJobId, ActionListener<ConnectorSyncJobSearchResult> listener) {
         final GetRequest getRequest = new GetRequest(CONNECTOR_SYNC_JOB_INDEX_NAME).id(connectorSyncJobId).realtime(true);
 
         try {
@@ -208,11 +205,10 @@ public class ConnectorSyncJobIndexService {
                     }
 
                     try {
-                        final ConnectorSyncJob syncJob = ConnectorSyncJob.fromXContentBytes(
-                            getResponse.getSourceAsBytesRef(),
-                            XContentType.JSON
-                        );
-                        l.onResponse(syncJob);
+                        ConnectorSyncJobSearchResult syncJobSearchResult = new ConnectorSyncJobSearchResult.Builder().setId(
+                            getResponse.getId()
+                        ).setResultBytes(getResponse.getSourceAsBytesRef()).setResultMap(getResponse.getSourceAsMap()).build();
+                        l.onResponse(syncJobSearchResult);
                     } catch (Exception e) {
                         listener.onFailure(e);
                     }
@@ -336,7 +332,7 @@ public class ConnectorSyncJobIndexService {
     }
 
     private ConnectorSyncJobsResult mapSearchResponseToConnectorSyncJobsList(SearchResponse searchResponse) {
-        final List<ConnectorSyncJob> connectorSyncJobs = Arrays.stream(searchResponse.getHits().getHits())
+        final List<ConnectorSyncJobSearchResult> connectorSyncJobs = Arrays.stream(searchResponse.getHits().getHits())
             .map(ConnectorSyncJobIndexService::hitToConnectorSyncJob)
             .toList();
 
@@ -346,13 +342,17 @@ public class ConnectorSyncJobIndexService {
         );
     }
 
-    private static ConnectorSyncJob hitToConnectorSyncJob(SearchHit searchHit) {
+    private static ConnectorSyncJobSearchResult hitToConnectorSyncJob(SearchHit searchHit) {
         // TODO: don't return sensitive data from configuration inside connector in list endpoint
 
-        return ConnectorSyncJob.fromXContentBytes(searchHit.getSourceRef(), XContentType.JSON);
+        return new ConnectorSyncJobSearchResult.Builder().setId(searchHit.getId())
+            .setResultBytes(searchHit.getSourceRef())
+            .setResultMap(searchHit.getSourceAsMap())
+            .build();
+
     }
 
-    public record ConnectorSyncJobsResult(List<ConnectorSyncJob> connectorSyncJobs, long totalResults) {}
+    public record ConnectorSyncJobsResult(List<ConnectorSyncJobSearchResult> connectorSyncJobs, long totalResults) {}
 
     /**
     * Updates the ingestion stats of the {@link ConnectorSyncJob} in the underlying index.

+ 52 - 0
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobSearchResult.java

@@ -0,0 +1,52 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.application.connector.syncjob;
+
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.xpack.application.connector.ConnectorsAPISearchResult;
+
+import java.io.IOException;
+import java.util.Map;
+
+public class ConnectorSyncJobSearchResult extends ConnectorsAPISearchResult {
+
+    public ConnectorSyncJobSearchResult(StreamInput in) throws IOException {
+        super(in);
+    }
+
+    private ConnectorSyncJobSearchResult(BytesReference resultBytes, Map<String, Object> resultMap, String id) {
+        super(resultBytes, resultMap, id);
+    }
+
+    public static class Builder {
+
+        private BytesReference resultBytes;
+        private Map<String, Object> resultMap;
+        private String id;
+
+        public Builder setResultBytes(BytesReference resultBytes) {
+            this.resultBytes = resultBytes;
+            return this;
+        }
+
+        public Builder setResultMap(Map<String, Object> resultMap) {
+            this.resultMap = resultMap;
+            return this;
+        }
+
+        public Builder setId(String id) {
+            this.id = id;
+            return this;
+        }
+
+        public ConnectorSyncJobSearchResult build() {
+            return new ConnectorSyncJobSearchResult(resultBytes, resultMap, id);
+        }
+    }
+}

+ 4 - 4
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/action/GetConnectorSyncJobAction.java

@@ -19,8 +19,8 @@ import org.elasticsearch.xcontent.ParseField;
 import org.elasticsearch.xcontent.ToXContentObject;
 import org.elasticsearch.xcontent.XContentBuilder;
 import org.elasticsearch.xcontent.XContentParser;
-import org.elasticsearch.xpack.application.connector.syncjob.ConnectorSyncJob;
 import org.elasticsearch.xpack.application.connector.syncjob.ConnectorSyncJobConstants;
+import org.elasticsearch.xpack.application.connector.syncjob.ConnectorSyncJobSearchResult;
 
 import java.io.IOException;
 import java.util.Objects;
@@ -110,15 +110,15 @@ public class GetConnectorSyncJobAction {
     }
 
     public static class Response extends ActionResponse implements ToXContentObject {
-        private final ConnectorSyncJob connectorSyncJob;
+        private final ConnectorSyncJobSearchResult connectorSyncJob;
 
-        public Response(ConnectorSyncJob connectorSyncJob) {
+        public Response(ConnectorSyncJobSearchResult connectorSyncJob) {
             this.connectorSyncJob = connectorSyncJob;
         }
 
         public Response(StreamInput in) throws IOException {
             super(in);
-            this.connectorSyncJob = new ConnectorSyncJob(in);
+            this.connectorSyncJob = new ConnectorSyncJobSearchResult(in);
         }
 
         @Override

+ 4 - 3
x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/syncjob/action/ListConnectorSyncJobsAction.java

@@ -20,6 +20,7 @@ import org.elasticsearch.xcontent.XContentBuilder;
 import org.elasticsearch.xcontent.XContentParser;
 import org.elasticsearch.xpack.application.connector.ConnectorSyncStatus;
 import org.elasticsearch.xpack.application.connector.syncjob.ConnectorSyncJob;
+import org.elasticsearch.xpack.application.connector.syncjob.ConnectorSyncJobSearchResult;
 import org.elasticsearch.xpack.core.action.util.PageParams;
 import org.elasticsearch.xpack.core.action.util.QueryPage;
 
@@ -133,14 +134,14 @@ public class ListConnectorSyncJobsAction {
     public static class Response extends ActionResponse implements ToXContentObject {
         public static final ParseField RESULTS_FIELD = new ParseField("results");
 
-        final QueryPage<ConnectorSyncJob> queryPage;
+        final QueryPage<ConnectorSyncJobSearchResult> queryPage;
 
         public Response(StreamInput in) throws IOException {
             super(in);
-            this.queryPage = new QueryPage<>(in, ConnectorSyncJob::new);
+            this.queryPage = new QueryPage<>(in, ConnectorSyncJobSearchResult::new);
         }
 
-        public Response(List<ConnectorSyncJob> items, Long totalResults) {
+        public Response(List<ConnectorSyncJobSearchResult> items, Long totalResults) {
             this.queryPage = new QueryPage<>(items, totalResults, RESULTS_FIELD);
         }
 

+ 8 - 1
x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/ConnectorIndexServiceTests.java

@@ -14,6 +14,7 @@ import org.elasticsearch.action.delete.DeleteResponse;
 import org.elasticsearch.action.update.UpdateResponse;
 import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.test.ESSingleNodeTestCase;
+import org.elasticsearch.xcontent.XContentType;
 import org.elasticsearch.xpack.application.connector.action.PostConnectorAction;
 import org.elasticsearch.xpack.application.connector.action.PutConnectorAction;
 import org.elasticsearch.xpack.application.connector.action.UpdateConnectorConfigurationAction;
@@ -401,7 +402,13 @@ public class ConnectorIndexServiceTests extends ESSingleNodeTestCase {
         final AtomicReference<Exception> exc = new AtomicReference<>(null);
         connectorIndexService.getConnector(connectorId, new ActionListener<>() {
             @Override
-            public void onResponse(Connector connector) {
+            public void onResponse(ConnectorSearchResult connectorResult) {
+                // Serialize the sourceRef to Connector class for unit tests
+                Connector connector = Connector.fromXContentBytes(
+                    connectorResult.getSourceRef(),
+                    connectorResult.getDocId(),
+                    XContentType.JSON
+                );
                 resp.set(connector);
                 latch.countDown();
             }

+ 28 - 0
x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/ConnectorTestUtils.java

@@ -7,6 +7,9 @@
 
 package org.elasticsearch.xpack.application.connector;
 
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.xcontent.XContentHelper;
+import org.elasticsearch.xcontent.XContentType;
 import org.elasticsearch.xpack.application.connector.action.PostConnectorAction;
 import org.elasticsearch.xpack.application.connector.action.PutConnectorAction;
 import org.elasticsearch.xpack.application.connector.configuration.ConfigurationDependency;
@@ -24,6 +27,7 @@ import org.elasticsearch.xpack.application.connector.filtering.FilteringValidati
 import org.elasticsearch.xpack.application.connector.filtering.FilteringValidationState;
 import org.elasticsearch.xpack.core.scheduler.Cron;
 
+import java.io.IOException;
 import java.time.Instant;
 import java.util.Collections;
 import java.util.HashMap;
@@ -262,6 +266,30 @@ public final class ConnectorTestUtils {
             .build();
     }
 
+    private static BytesReference convertConnectorToBytesReference(Connector connector) {
+        try {
+            return XContentHelper.toXContent((builder, params) -> {
+                connector.toInnerXContent(builder, params);
+                return builder;
+            }, XContentType.JSON, null, false);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static Map<String, Object> convertConnectorToGenericMap(Connector connector) {
+        return XContentHelper.convertToMap(convertConnectorToBytesReference(connector), true, XContentType.JSON).v2();
+    }
+
+    public static ConnectorSearchResult getRandomConnectorSearchResult() {
+        Connector connector = getRandomConnector();
+
+        return new ConnectorSearchResult.Builder().setResultBytes(convertConnectorToBytesReference(connector))
+            .setResultMap(convertConnectorToGenericMap(connector))
+            .setId(randomAlphaOfLength(10))
+            .build();
+    }
+
     private static ConnectorFeatures.FeatureEnabled randomConnectorFeatureEnabled() {
         return new ConnectorFeatures.FeatureEnabled(randomBoolean());
     }

+ 3 - 13
x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/action/GetConnectorActionResponseBWCSerializingTests.java

@@ -9,16 +9,12 @@ package org.elasticsearch.xpack.application.connector.action;
 
 import org.elasticsearch.TransportVersion;
 import org.elasticsearch.common.io.stream.Writeable;
-import org.elasticsearch.xcontent.XContentParser;
-import org.elasticsearch.xpack.application.connector.Connector;
 import org.elasticsearch.xpack.application.connector.ConnectorTestUtils;
-import org.elasticsearch.xpack.core.ml.AbstractBWCSerializationTestCase;
+import org.elasticsearch.xpack.core.ml.AbstractBWCWireSerializationTestCase;
 
 import java.io.IOException;
 
-public class GetConnectorActionResponseBWCSerializingTests extends AbstractBWCSerializationTestCase<GetConnectorAction.Response> {
-
-    private Connector connector;
+public class GetConnectorActionResponseBWCSerializingTests extends AbstractBWCWireSerializationTestCase<GetConnectorAction.Response> {
 
     @Override
     protected Writeable.Reader<GetConnectorAction.Response> instanceReader() {
@@ -27,8 +23,7 @@ public class GetConnectorActionResponseBWCSerializingTests extends AbstractBWCSe
 
     @Override
     protected GetConnectorAction.Response createTestInstance() {
-        this.connector = ConnectorTestUtils.getRandomConnector();
-        return new GetConnectorAction.Response(this.connector);
+        return new GetConnectorAction.Response(ConnectorTestUtils.getRandomConnectorSearchResult());
     }
 
     @Override
@@ -36,11 +31,6 @@ public class GetConnectorActionResponseBWCSerializingTests extends AbstractBWCSe
         return randomValueOtherThan(instance, this::createTestInstance);
     }
 
-    @Override
-    protected GetConnectorAction.Response doParseInstance(XContentParser parser) throws IOException {
-        return GetConnectorAction.Response.fromXContent(parser, connector.getConnectorId());
-    }
-
     @Override
     protected GetConnectorAction.Response mutateInstanceForVersion(GetConnectorAction.Response instance, TransportVersion version) {
         return instance;

+ 4 - 1
x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/action/ListConnectorActionResponseBWCSerializingTests.java

@@ -22,7 +22,10 @@ public class ListConnectorActionResponseBWCSerializingTests extends AbstractBWCW
 
     @Override
     protected ListConnectorAction.Response createTestInstance() {
-        return new ListConnectorAction.Response(randomList(10, ConnectorTestUtils::getRandomConnector), randomLongBetween(0, 100));
+        return new ListConnectorAction.Response(
+            randomList(10, ConnectorTestUtils::getRandomConnectorSearchResult),
+            randomLongBetween(0, 100)
+        );
     }
 
     @Override

+ 40 - 10
x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobIndexServiceTests.java

@@ -22,6 +22,7 @@ import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.test.ESSingleNodeTestCase;
 import org.elasticsearch.xcontent.ParseField;
 import org.elasticsearch.xcontent.ToXContent;
+import org.elasticsearch.xcontent.XContentType;
 import org.elasticsearch.xpack.application.connector.Connector;
 import org.elasticsearch.xpack.application.connector.ConnectorFiltering;
 import org.elasticsearch.xpack.application.connector.ConnectorIndexService;
@@ -100,7 +101,6 @@ public class ConnectorSyncJobIndexServiceTests extends ESSingleNodeTestCase {
 
         ConnectorSyncJob connectorSyncJob = awaitGetConnectorSyncJob(response.getId());
 
-        assertThat(connectorSyncJob.getId(), notNullValue());
         assertThat(connectorSyncJob.getJobType(), equalTo(requestJobType));
         assertThat(connectorSyncJob.getTriggerMethod(), equalTo(requestTriggerMethod));
         assertThat(connectorSyncJob.getStatus(), equalTo(ConnectorSyncJob.DEFAULT_INITIAL_STATUS));
@@ -283,11 +283,31 @@ public class ConnectorSyncJobIndexServiceTests extends ESSingleNodeTestCase {
         ConnectorSyncJobIndexService.ConnectorSyncJobsResult nextTwoSyncJobs = awaitListConnectorSyncJobs(2, 2, null, null);
         ConnectorSyncJobIndexService.ConnectorSyncJobsResult lastSyncJobs = awaitListConnectorSyncJobs(4, 100, null, null);
 
-        ConnectorSyncJob firstSyncJob = firstTwoSyncJobs.connectorSyncJobs().get(0);
-        ConnectorSyncJob secondSyncJob = firstTwoSyncJobs.connectorSyncJobs().get(1);
-        ConnectorSyncJob thirdSyncJob = nextTwoSyncJobs.connectorSyncJobs().get(0);
-        ConnectorSyncJob fourthSyncJob = nextTwoSyncJobs.connectorSyncJobs().get(1);
-        ConnectorSyncJob fifthSyncJob = lastSyncJobs.connectorSyncJobs().get(0);
+        ConnectorSyncJob firstSyncJob = ConnectorSyncJob.fromXContentBytes(
+            firstTwoSyncJobs.connectorSyncJobs().get(0).getSourceRef(),
+            firstTwoSyncJobs.connectorSyncJobs().get(0).getDocId(),
+            XContentType.JSON
+        );
+        ConnectorSyncJob secondSyncJob = ConnectorSyncJob.fromXContentBytes(
+            firstTwoSyncJobs.connectorSyncJobs().get(1).getSourceRef(),
+            firstTwoSyncJobs.connectorSyncJobs().get(1).getDocId(),
+            XContentType.JSON
+        );
+        ConnectorSyncJob thirdSyncJob = ConnectorSyncJob.fromXContentBytes(
+            nextTwoSyncJobs.connectorSyncJobs().get(0).getSourceRef(),
+            nextTwoSyncJobs.connectorSyncJobs().get(0).getDocId(),
+            XContentType.JSON
+        );
+        ConnectorSyncJob fourthSyncJob = ConnectorSyncJob.fromXContentBytes(
+            nextTwoSyncJobs.connectorSyncJobs().get(1).getSourceRef(),
+            nextTwoSyncJobs.connectorSyncJobs().get(1).getDocId(),
+            XContentType.JSON
+        );
+        ConnectorSyncJob fifthSyncJob = ConnectorSyncJob.fromXContentBytes(
+            lastSyncJobs.connectorSyncJobs().get(0).getSourceRef(),
+            lastSyncJobs.connectorSyncJobs().get(0).getDocId(),
+            XContentType.JSON
+        );
 
         assertThat(firstTwoSyncJobs.connectorSyncJobs().size(), equalTo(2));
         assertThat(firstTwoSyncJobs.totalResults(), equalTo(5L));
@@ -337,7 +357,7 @@ public class ConnectorSyncJobIndexServiceTests extends ESSingleNodeTestCase {
             ConnectorSyncStatus.PENDING
         );
         long numberOfResults = connectorSyncJobsResult.totalResults();
-        String idOfReturnedSyncJob = connectorSyncJobsResult.connectorSyncJobs().get(0).getId();
+        String idOfReturnedSyncJob = connectorSyncJobsResult.connectorSyncJobs().get(0).getDocId();
 
         assertThat(numberOfResults, equalTo(1L));
         assertThat(idOfReturnedSyncJob, equalTo(syncJobOneId));
@@ -363,7 +383,11 @@ public class ConnectorSyncJobIndexServiceTests extends ESSingleNodeTestCase {
         );
 
         long numberOfResults = connectorSyncJobsResult.totalResults();
-        String connectorIdOfReturnedSyncJob = connectorSyncJobsResult.connectorSyncJobs().get(0).getConnector().getConnectorId();
+        String connectorIdOfReturnedSyncJob = ConnectorSyncJob.fromXContentBytes(
+            connectorSyncJobsResult.connectorSyncJobs().get(0).getSourceRef(),
+            connectorSyncJobsResult.connectorSyncJobs().get(0).getDocId(),
+            XContentType.JSON
+        ).getConnector().getConnectorId();
 
         assertThat(numberOfResults, equalTo(1L));
         assertThat(connectorIdOfReturnedSyncJob, equalTo(connectorOneId));
@@ -699,9 +723,15 @@ public class ConnectorSyncJobIndexServiceTests extends ESSingleNodeTestCase {
         final AtomicReference<ConnectorSyncJob> resp = new AtomicReference<>(null);
         final AtomicReference<Exception> exc = new AtomicReference<>(null);
 
-        connectorSyncJobIndexService.getConnectorSyncJob(connectorSyncJobId, new ActionListener<ConnectorSyncJob>() {
+        connectorSyncJobIndexService.getConnectorSyncJob(connectorSyncJobId, new ActionListener<ConnectorSyncJobSearchResult>() {
             @Override
-            public void onResponse(ConnectorSyncJob connectorSyncJob) {
+            public void onResponse(ConnectorSyncJobSearchResult searchResult) {
+                // Serialize the sourceRef to ConnectorSyncJob class for unit tests
+                ConnectorSyncJob connectorSyncJob = ConnectorSyncJob.fromXContentBytes(
+                    searchResult.getSourceRef(),
+                    searchResult.getDocId(),
+                    XContentType.JSON
+                );
                 resp.set(connectorSyncJob);
                 latch.countDown();
             }

+ 30 - 1
x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobTestUtils.java

@@ -7,7 +7,10 @@
 
 package org.elasticsearch.xpack.application.connector.syncjob;
 
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.xcontent.XContentHelper;
 import org.elasticsearch.core.Tuple;
+import org.elasticsearch.xcontent.XContentType;
 import org.elasticsearch.xpack.application.connector.ConnectorTestUtils;
 import org.elasticsearch.xpack.application.connector.syncjob.action.CancelConnectorSyncJobAction;
 import org.elasticsearch.xpack.application.connector.syncjob.action.CheckInConnectorSyncJobAction;
@@ -19,7 +22,9 @@ import org.elasticsearch.xpack.application.connector.syncjob.action.UpdateConnec
 import org.elasticsearch.xpack.application.connector.syncjob.action.UpdateConnectorSyncJobIngestionStatsAction;
 import org.elasticsearch.xpack.application.search.SearchApplicationTestUtils;
 
+import java.io.IOException;
 import java.time.Instant;
+import java.util.Map;
 
 import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength;
 import static org.elasticsearch.test.ESTestCase.randomAlphaOfLengthBetween;
@@ -65,6 +70,30 @@ public class ConnectorSyncJobTestUtils {
             .build();
     }
 
+    private static BytesReference convertSyncJobToBytesReference(ConnectorSyncJob syncJob) {
+        try {
+            return XContentHelper.toXContent((builder, params) -> {
+                syncJob.toInnerXContent(builder, params);
+                return builder;
+            }, XContentType.JSON, null, false);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static Map<String, Object> convertSyncJobToGenericMap(ConnectorSyncJob syncJob) {
+        return XContentHelper.convertToMap(convertSyncJobToBytesReference(syncJob), true, XContentType.JSON).v2();
+    }
+
+    public static ConnectorSyncJobSearchResult getRandomSyncJobSearchResult() {
+        ConnectorSyncJob syncJob = getRandomConnectorSyncJob();
+
+        return new ConnectorSyncJobSearchResult.Builder().setId(randomAlphaOfLength(10))
+            .setResultMap(convertSyncJobToGenericMap(syncJob))
+            .setResultBytes(convertSyncJobToBytesReference(syncJob))
+            .build();
+    }
+
     public static ConnectorSyncJobTriggerMethod getRandomConnectorSyncJobTriggerMethod() {
         ConnectorSyncJobTriggerMethod[] values = ConnectorSyncJobTriggerMethod.values();
         return values[randomInt(values.length - 1)];
@@ -146,7 +175,7 @@ public class ConnectorSyncJobTestUtils {
     }
 
     public static GetConnectorSyncJobAction.Response getRandomGetConnectorSyncJobResponse() {
-        return new GetConnectorSyncJobAction.Response(getRandomConnectorSyncJob());
+        return new GetConnectorSyncJobAction.Response(getRandomSyncJobSearchResult());
     }
 
     public static ListConnectorSyncJobsAction.Request getRandomListConnectorSyncJobsActionRequest() {

+ 3 - 6
x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/syncjob/ConnectorSyncJobTests.java

@@ -87,7 +87,6 @@ public class ConnectorSyncJobTests extends ESTestCase {
                 "created_at": "2023-12-01T14:18:43.07693Z",
                 "deleted_document_count": 10,
                 "error": "some-error",
-                "id": "HIC-JYwB9RqKhB7x_hIE",
                 "indexed_document_count": 10,
                 "indexed_document_volume": 10,
                 "job_type": "full",
@@ -101,7 +100,7 @@ public class ConnectorSyncJobTests extends ESTestCase {
             }
             """);
 
-        ConnectorSyncJob syncJob = ConnectorSyncJob.fromXContentBytes(new BytesArray(content), XContentType.JSON);
+        ConnectorSyncJob syncJob = ConnectorSyncJob.fromXContentBytes(new BytesArray(content), "HIC-JYwB9RqKhB7x_hIE", XContentType.JSON);
 
         assertThat(syncJob.getCancelationRequestedAt(), equalTo(Instant.parse("2023-12-01T14:19:39.394194Z")));
         assertThat(syncJob.getCanceledAt(), equalTo(Instant.parse("2023-12-01T14:19:39.394194Z")));
@@ -170,7 +169,6 @@ public class ConnectorSyncJobTests extends ESTestCase {
                 },
                 "created_at": "2023-12-01T14:18:43.07693Z",
                 "deleted_document_count": 10,
-                "id": "HIC-JYwB9RqKhB7x_hIE",
                 "indexed_document_count": 10,
                 "indexed_document_volume": 10,
                 "job_type": "full",
@@ -182,7 +180,7 @@ public class ConnectorSyncJobTests extends ESTestCase {
             }
             """);
 
-        ConnectorSyncJob.fromXContentBytes(new BytesArray(content), XContentType.JSON);
+        ConnectorSyncJob.fromXContentBytes(new BytesArray(content), "HIC-JYwB9RqKhB7x_hIE", XContentType.JSON);
     }
 
     public void testFromXContent_WithAllNullableFieldsSetToNull_DoesNotThrow() throws IOException {
@@ -230,7 +228,6 @@ public class ConnectorSyncJobTests extends ESTestCase {
                 "created_at": "2023-12-01T14:18:43.07693Z",
                 "deleted_document_count": 10,
                 "error": null,
-                "id": "HIC-JYwB9RqKhB7x_hIE",
                 "indexed_document_count": 10,
                 "indexed_document_volume": 10,
                 "job_type": "full",
@@ -244,7 +241,7 @@ public class ConnectorSyncJobTests extends ESTestCase {
             }
             """);
 
-        ConnectorSyncJob.fromXContentBytes(new BytesArray(content), XContentType.JSON);
+        ConnectorSyncJob.fromXContentBytes(new BytesArray(content), "HIC-JYwB9RqKhB7x_hIE", XContentType.JSON);
     }
 
     public void testSyncJobConnectorFromXContent_WithAllFieldsSet() throws IOException {

+ 1 - 1
x-pack/plugin/ent-search/src/test/java/org/elasticsearch/xpack/application/connector/syncjob/action/ListConnectorSyncJobsActionResponseBWCSerializingTests.java

@@ -33,7 +33,7 @@ public class ListConnectorSyncJobsActionResponseBWCSerializingTests extends Abst
     @Override
     protected ListConnectorSyncJobsAction.Response createTestInstance() {
         return new ListConnectorSyncJobsAction.Response(
-            randomList(10, ConnectorSyncJobTestUtils::getRandomConnectorSyncJob),
+            randomList(10, ConnectorSyncJobTestUtils::getRandomSyncJobSearchResult),
             randomLongBetween(0, 100)
         );
     }