This is an automated email from the ASF dual-hosted git repository. nfilotto pushed a commit to branch CAMEL-19752/add-document-only-mode-4.0 in repository https://gitbox.apache.org/repos/asf/camel.git
commit d0d408e722c4fba27b84752a1fbe1097c644c77e Author: Nicolas Filotto <[email protected]> AuthorDate: Fri Sep 1 16:13:14 2023 +0200 CAMEL-19752: camel-elasticsearch - Add a doc-only mode to ease migration --- .../camel/catalog/components/elasticsearch.json | 65 +++++---- .../es/ElasticsearchComponentConfigurer.java | 6 + .../es/ElasticsearchEndpointConfigurer.java | 6 + .../es/ElasticsearchEndpointUriFactory.java | 3 +- .../apache/camel/component/es/elasticsearch.json | 65 +++++---- .../src/main/docs/elasticsearch-component.adoc | 12 +- .../camel/component/es/ElasticsearchComponent.java | 18 +++ .../component/es/ElasticsearchConfiguration.java | 17 +++ .../camel/component/es/ElasticsearchConstants.java | 3 + .../camel/component/es/ElasticsearchProducer.java | 5 + .../ElasticsearchActionRequestConverter.java | 43 +++++- .../es/integration/ElasticsearchBulkIT.java | 7 +- ...ElasticsearchGetSearchDeleteExistsUpdateIT.java | 161 ++++++++++++++++++--- .../dsl/ElasticsearchComponentBuilderFactory.java | 20 +++ .../dsl/ElasticsearchEndpointBuilderFactory.java | 53 +++++++ 15 files changed, 390 insertions(+), 94 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/elasticsearch.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/elasticsearch.json index d7c648a3244..292f137f6c0 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/elasticsearch.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/elasticsearch.json @@ -23,19 +23,20 @@ }, "componentProperties": { "connectionTimeout": { "index": 0, "kind": "property", "displayName": "Connection Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The time in ms to wait before connection will timeout." }, - "hostAddresses": { "index": 1, "kind": "property", "displayName": "Host Addresses", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Comma separated list with ip:port formatted remote transport addresses to use. The ip and port options must be left blank for hostAddresses to be considered instead." }, - "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...] - "maxRetryTimeout": { "index": 3, "kind": "property", "displayName": "Max Retry Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The time in ms before retry" }, - "socketTimeout": { "index": 4, "kind": "property", "displayName": "Socket Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The timeout in ms to wait before the socket will timeout." }, - "autowiredEnabled": { "index": 5, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] - "client": { "index": 6, "kind": "property", "displayName": "Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.elasticsearch.client.RestClient", "deprecated": false, "autowired": true, "secret": false, "description": "To use an existing configured Elasticsearch client, instead of creating a client per endpoint. This allow to customize the client with specific settings." }, - "enableSniffer": { "index": 7, "kind": "property", "displayName": "Enable Sniffer", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable automatically discover nodes from a running Elasticsearch cluster. If this option is used in conjunction with Spring Boot then it's managed by the Spring Boot configuration (see: Disable Sniffer in [...] - "sniffAfterFailureDelay": { "index": 8, "kind": "property", "displayName": "Sniff After Failure Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "description": "The delay of a sniff execution scheduled after a failure (in milliseconds)" }, - "snifferInterval": { "index": 9, "kind": "property", "displayName": "Sniffer Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "description": "The interval between consecutive ordinary sniff executions in milliseconds. Will be honoured when sniffOnFailure is disabled or when there are no failures between consecutive sniff executions" }, - "certificatePath": { "index": 10, "kind": "property", "displayName": "Certificate Path", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The path of the self-signed certificate to use to access to Elasticsearch." }, - "enableSSL": { "index": 11, "kind": "property", "displayName": "Enable SSL", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable SSL" }, - "password": { "index": 12, "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Password for authenticate" }, - "user": { "index": 13, "kind": "property", "displayName": "User", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Basic authenticate user" } + "enableDocumentOnlyMode": { "index": 1, "kind": "property", "displayName": "Enable Document Only Mode", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Indicates whether the body of the message contains only documents. By default, it is set to false to be able to do the same requests as what the Document API supports (see https:\/\/www.elasti [...] + "hostAddresses": { "index": 2, "kind": "property", "displayName": "Host Addresses", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Comma separated list with ip:port formatted remote transport addresses to use. The ip and port options must be left blank for hostAddresses to be considered instead." }, + "lazyStartProducer": { "index": 3, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...] + "maxRetryTimeout": { "index": 4, "kind": "property", "displayName": "Max Retry Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The time in ms before retry" }, + "socketTimeout": { "index": 5, "kind": "property", "displayName": "Socket Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The timeout in ms to wait before the socket will timeout." }, + "autowiredEnabled": { "index": 6, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] + "client": { "index": 7, "kind": "property", "displayName": "Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.elasticsearch.client.RestClient", "deprecated": false, "autowired": true, "secret": false, "description": "To use an existing configured Elasticsearch client, instead of creating a client per endpoint. This allow to customize the client with specific settings." }, + "enableSniffer": { "index": 8, "kind": "property", "displayName": "Enable Sniffer", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable automatically discover nodes from a running Elasticsearch cluster. If this option is used in conjunction with Spring Boot then it's managed by the Spring Boot configuration (see: Disable Sniffer in [...] + "sniffAfterFailureDelay": { "index": 9, "kind": "property", "displayName": "Sniff After Failure Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "description": "The delay of a sniff execution scheduled after a failure (in milliseconds)" }, + "snifferInterval": { "index": 10, "kind": "property", "displayName": "Sniffer Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "description": "The interval between consecutive ordinary sniff executions in milliseconds. Will be honoured when sniffOnFailure is disabled or when there are no failures between consecutive sniff executions" }, + "certificatePath": { "index": 11, "kind": "property", "displayName": "Certificate Path", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The path of the self-signed certificate to use to access to Elasticsearch." }, + "enableSSL": { "index": 12, "kind": "property", "displayName": "Enable SSL", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable SSL" }, + "password": { "index": 13, "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Password for authenticate" }, + "user": { "index": 14, "kind": "property", "displayName": "User", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Basic authenticate user" } }, "headers": { "operation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.camel.component.es.ElasticsearchOperation", "enum": [ "Index", "Update", "Bulk", "GetById", "MultiGet", "MultiSearch", "Delete", "DeleteIndex", "Search", "Exists", "Ping" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation to perform", "constantName": "org.apache.camel.component.es.El [...] @@ -46,28 +47,30 @@ "scrollKeepAliveMs": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The starting index of the response.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_SCROLL_KEEP_ALIVE_MS" }, "useScroll": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Set to true to enable scroll usage", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_SCROLL" }, "size": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the response.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_SIZE" }, - "from": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The starting index of the response.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_FROM" } + "from": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The starting index of the response.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_FROM" }, + "enableDocumentOnlyMode": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "false", "description": "Indicates whether the body of the message contains only documents.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_DOCUMENT_MODE" } }, "properties": { "clusterName": { "index": 0, "kind": "path", "displayName": "Cluster Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Name of the cluster" }, "connectionTimeout": { "index": 1, "kind": "parameter", "displayName": "Connection Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The time in ms to wait before connection will timeout." }, "disconnect": { "index": 2, "kind": "parameter", "displayName": "Disconnect", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Disconnect after it finish calling the producer" }, - "from": { "index": 3, "kind": "parameter", "displayName": "From", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Starting index of the response." }, - "hostAddresses": { "index": 4, "kind": "parameter", "displayName": "Host Addresses", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Comma separated list with ip:port formatted remote transport addresses to use." }, - "indexName": { "index": 5, "kind": "parameter", "displayName": "Index Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The name of the index to act against" }, - "maxRetryTimeout": { "index": 6, "kind": "parameter", "displayName": "Max Retry Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The time in ms before retry" }, - "operation": { "index": 7, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.es.ElasticsearchOperation", "enum": [ "Index", "Update", "Bulk", "GetById", "MultiGet", "MultiSearch", "Delete", "DeleteIndex", "Search", "Exists", "Ping" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "co [...] - "scrollKeepAliveMs": { "index": 8, "kind": "parameter", "displayName": "Scroll Keep Alive Ms", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Time in ms during which elasticsearch will keep search context alive" }, - "size": { "index": 9, "kind": "parameter", "displayName": "Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Size of the response." }, - "socketTimeout": { "index": 10, "kind": "parameter", "displayName": "Socket Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The timeout in ms to wait before the socket will timeout." }, - "useScroll": { "index": 11, "kind": "parameter", "displayName": "Use Scroll", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable scroll usage" }, - "waitForActiveShards": { "index": 12, "kind": "parameter", "displayName": "Wait For Active Shards", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Index creation waits for the write consistency number of shards to be available" }, - "lazyStartProducer": { "index": 13, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] - "documentClass": { "index": 14, "kind": "parameter", "displayName": "Document Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.Class<java.lang.Object>", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "ObjectNode", "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The class to use when deserializing the documents." }, - "enableSniffer": { "index": 15, "kind": "parameter", "displayName": "Enable Sniffer", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable automatically discover nodes from a running Elasticsearch cluster. If this [...] - "sniffAfterFailureDelay": { "index": 16, "kind": "parameter", "displayName": "Sniff After Failure Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The delay of a sniff execution scheduled after a failure (in mill [...] - "snifferInterval": { "index": 17, "kind": "parameter", "displayName": "Sniffer Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The interval between consecutive ordinary sniff executions in milliseconds. Will [...] - "certificatePath": { "index": 18, "kind": "parameter", "displayName": "Certificate Path", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The certificate that can be used to acc [...] - "enableSSL": { "index": 19, "kind": "parameter", "displayName": "Enable SSL", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable SSL" } + "enableDocumentOnlyMode": { "index": 3, "kind": "parameter", "displayName": "Enable Document Only Mode", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Indicates whether the body of the message contains only documents. By [...] + "from": { "index": 4, "kind": "parameter", "displayName": "From", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Starting index of the response." }, + "hostAddresses": { "index": 5, "kind": "parameter", "displayName": "Host Addresses", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Comma separated list with ip:port formatted remote transport addresses to use." }, + "indexName": { "index": 6, "kind": "parameter", "displayName": "Index Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The name of the index to act against" }, + "maxRetryTimeout": { "index": 7, "kind": "parameter", "displayName": "Max Retry Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The time in ms before retry" }, + "operation": { "index": 8, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.es.ElasticsearchOperation", "enum": [ "Index", "Update", "Bulk", "GetById", "MultiGet", "MultiSearch", "Delete", "DeleteIndex", "Search", "Exists", "Ping" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "co [...] + "scrollKeepAliveMs": { "index": 9, "kind": "parameter", "displayName": "Scroll Keep Alive Ms", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Time in ms during which elasticsearch will keep search context alive" }, + "size": { "index": 10, "kind": "parameter", "displayName": "Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Size of the response." }, + "socketTimeout": { "index": 11, "kind": "parameter", "displayName": "Socket Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The timeout in ms to wait before the socket will timeout." }, + "useScroll": { "index": 12, "kind": "parameter", "displayName": "Use Scroll", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable scroll usage" }, + "waitForActiveShards": { "index": 13, "kind": "parameter", "displayName": "Wait For Active Shards", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Index creation waits for the write consistency number of shards to be available" }, + "lazyStartProducer": { "index": 14, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] + "documentClass": { "index": 15, "kind": "parameter", "displayName": "Document Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.Class<java.lang.Object>", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "ObjectNode", "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The class to use when deserializing the documents." }, + "enableSniffer": { "index": 16, "kind": "parameter", "displayName": "Enable Sniffer", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable automatically discover nodes from a running Elasticsearch cluster. If this [...] + "sniffAfterFailureDelay": { "index": 17, "kind": "parameter", "displayName": "Sniff After Failure Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The delay of a sniff execution scheduled after a failure (in mill [...] + "snifferInterval": { "index": 18, "kind": "parameter", "displayName": "Sniffer Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The interval between consecutive ordinary sniff executions in milliseconds. Will [...] + "certificatePath": { "index": 19, "kind": "parameter", "displayName": "Certificate Path", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The certificate that can be used to acc [...] + "enableSSL": { "index": 20, "kind": "parameter", "displayName": "Enable SSL", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable SSL" } } } diff --git a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchComponentConfigurer.java b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchComponentConfigurer.java index 8b3a0236c01..3cfb3336d9d 100644 --- a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchComponentConfigurer.java +++ b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchComponentConfigurer.java @@ -28,6 +28,8 @@ public class ElasticsearchComponentConfigurer extends PropertyConfigurerSupport case "client": target.setClient(property(camelContext, org.elasticsearch.client.RestClient.class, value)); return true; case "connectiontimeout": case "connectionTimeout": target.setConnectionTimeout(property(camelContext, int.class, value)); return true; + case "enabledocumentonlymode": + case "enableDocumentOnlyMode": target.setEnableDocumentOnlyMode(property(camelContext, boolean.class, value)); return true; case "enablessl": case "enableSSL": target.setEnableSSL(property(camelContext, boolean.class, value)); return true; case "enablesniffer": @@ -65,6 +67,8 @@ public class ElasticsearchComponentConfigurer extends PropertyConfigurerSupport case "client": return org.elasticsearch.client.RestClient.class; case "connectiontimeout": case "connectionTimeout": return int.class; + case "enabledocumentonlymode": + case "enableDocumentOnlyMode": return boolean.class; case "enablessl": case "enableSSL": return boolean.class; case "enablesniffer": @@ -98,6 +102,8 @@ public class ElasticsearchComponentConfigurer extends PropertyConfigurerSupport case "client": return target.getClient(); case "connectiontimeout": case "connectionTimeout": return target.getConnectionTimeout(); + case "enabledocumentonlymode": + case "enableDocumentOnlyMode": return target.isEnableDocumentOnlyMode(); case "enablessl": case "enableSSL": return target.isEnableSSL(); case "enablesniffer": diff --git a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointConfigurer.java b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointConfigurer.java index 02657933b8d..0efbe912840 100644 --- a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointConfigurer.java +++ b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointConfigurer.java @@ -28,6 +28,8 @@ public class ElasticsearchEndpointConfigurer extends PropertyConfigurerSupport i case "disconnect": target.getConfiguration().setDisconnect(property(camelContext, boolean.class, value)); return true; case "documentclass": case "documentClass": target.getConfiguration().setDocumentClass(property(camelContext, java.lang.Class.class, value)); return true; + case "enabledocumentonlymode": + case "enableDocumentOnlyMode": target.getConfiguration().setEnableDocumentOnlyMode(property(camelContext, boolean.class, value)); return true; case "enablessl": case "enableSSL": target.getConfiguration().setEnableSSL(property(camelContext, boolean.class, value)); return true; case "enablesniffer": @@ -69,6 +71,8 @@ public class ElasticsearchEndpointConfigurer extends PropertyConfigurerSupport i case "disconnect": return boolean.class; case "documentclass": case "documentClass": return java.lang.Class.class; + case "enabledocumentonlymode": + case "enableDocumentOnlyMode": return boolean.class; case "enablessl": case "enableSSL": return boolean.class; case "enablesniffer": @@ -111,6 +115,8 @@ public class ElasticsearchEndpointConfigurer extends PropertyConfigurerSupport i case "disconnect": return target.getConfiguration().isDisconnect(); case "documentclass": case "documentClass": return target.getConfiguration().getDocumentClass(); + case "enabledocumentonlymode": + case "enableDocumentOnlyMode": return target.getConfiguration().isEnableDocumentOnlyMode(); case "enablessl": case "enableSSL": return target.getConfiguration().isEnableSSL(); case "enablesniffer": diff --git a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointUriFactory.java b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointUriFactory.java index 44fa48f13a9..b192be6c41d 100644 --- a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointUriFactory.java +++ b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointUriFactory.java @@ -21,12 +21,13 @@ public class ElasticsearchEndpointUriFactory extends org.apache.camel.support.co private static final Set<String> SECRET_PROPERTY_NAMES; private static final Set<String> MULTI_VALUE_PREFIXES; static { - Set<String> props = new HashSet<>(20); + Set<String> props = new HashSet<>(21); props.add("certificatePath"); props.add("clusterName"); props.add("connectionTimeout"); props.add("disconnect"); props.add("documentClass"); + props.add("enableDocumentOnlyMode"); props.add("enableSSL"); props.add("enableSniffer"); props.add("from"); diff --git a/components/camel-elasticsearch/src/generated/resources/org/apache/camel/component/es/elasticsearch.json b/components/camel-elasticsearch/src/generated/resources/org/apache/camel/component/es/elasticsearch.json index d7c648a3244..292f137f6c0 100644 --- a/components/camel-elasticsearch/src/generated/resources/org/apache/camel/component/es/elasticsearch.json +++ b/components/camel-elasticsearch/src/generated/resources/org/apache/camel/component/es/elasticsearch.json @@ -23,19 +23,20 @@ }, "componentProperties": { "connectionTimeout": { "index": 0, "kind": "property", "displayName": "Connection Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The time in ms to wait before connection will timeout." }, - "hostAddresses": { "index": 1, "kind": "property", "displayName": "Host Addresses", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Comma separated list with ip:port formatted remote transport addresses to use. The ip and port options must be left blank for hostAddresses to be considered instead." }, - "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...] - "maxRetryTimeout": { "index": 3, "kind": "property", "displayName": "Max Retry Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The time in ms before retry" }, - "socketTimeout": { "index": 4, "kind": "property", "displayName": "Socket Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The timeout in ms to wait before the socket will timeout." }, - "autowiredEnabled": { "index": 5, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] - "client": { "index": 6, "kind": "property", "displayName": "Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.elasticsearch.client.RestClient", "deprecated": false, "autowired": true, "secret": false, "description": "To use an existing configured Elasticsearch client, instead of creating a client per endpoint. This allow to customize the client with specific settings." }, - "enableSniffer": { "index": 7, "kind": "property", "displayName": "Enable Sniffer", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable automatically discover nodes from a running Elasticsearch cluster. If this option is used in conjunction with Spring Boot then it's managed by the Spring Boot configuration (see: Disable Sniffer in [...] - "sniffAfterFailureDelay": { "index": 8, "kind": "property", "displayName": "Sniff After Failure Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "description": "The delay of a sniff execution scheduled after a failure (in milliseconds)" }, - "snifferInterval": { "index": 9, "kind": "property", "displayName": "Sniffer Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "description": "The interval between consecutive ordinary sniff executions in milliseconds. Will be honoured when sniffOnFailure is disabled or when there are no failures between consecutive sniff executions" }, - "certificatePath": { "index": 10, "kind": "property", "displayName": "Certificate Path", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The path of the self-signed certificate to use to access to Elasticsearch." }, - "enableSSL": { "index": 11, "kind": "property", "displayName": "Enable SSL", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable SSL" }, - "password": { "index": 12, "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Password for authenticate" }, - "user": { "index": 13, "kind": "property", "displayName": "User", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Basic authenticate user" } + "enableDocumentOnlyMode": { "index": 1, "kind": "property", "displayName": "Enable Document Only Mode", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Indicates whether the body of the message contains only documents. By default, it is set to false to be able to do the same requests as what the Document API supports (see https:\/\/www.elasti [...] + "hostAddresses": { "index": 2, "kind": "property", "displayName": "Host Addresses", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Comma separated list with ip:port formatted remote transport addresses to use. The ip and port options must be left blank for hostAddresses to be considered instead." }, + "lazyStartProducer": { "index": 3, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...] + "maxRetryTimeout": { "index": 4, "kind": "property", "displayName": "Max Retry Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The time in ms before retry" }, + "socketTimeout": { "index": 5, "kind": "property", "displayName": "Socket Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The timeout in ms to wait before the socket will timeout." }, + "autowiredEnabled": { "index": 6, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] + "client": { "index": 7, "kind": "property", "displayName": "Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.elasticsearch.client.RestClient", "deprecated": false, "autowired": true, "secret": false, "description": "To use an existing configured Elasticsearch client, instead of creating a client per endpoint. This allow to customize the client with specific settings." }, + "enableSniffer": { "index": 8, "kind": "property", "displayName": "Enable Sniffer", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable automatically discover nodes from a running Elasticsearch cluster. If this option is used in conjunction with Spring Boot then it's managed by the Spring Boot configuration (see: Disable Sniffer in [...] + "sniffAfterFailureDelay": { "index": 9, "kind": "property", "displayName": "Sniff After Failure Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "description": "The delay of a sniff execution scheduled after a failure (in milliseconds)" }, + "snifferInterval": { "index": 10, "kind": "property", "displayName": "Sniffer Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "description": "The interval between consecutive ordinary sniff executions in milliseconds. Will be honoured when sniffOnFailure is disabled or when there are no failures between consecutive sniff executions" }, + "certificatePath": { "index": 11, "kind": "property", "displayName": "Certificate Path", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The path of the self-signed certificate to use to access to Elasticsearch." }, + "enableSSL": { "index": 12, "kind": "property", "displayName": "Enable SSL", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable SSL" }, + "password": { "index": 13, "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Password for authenticate" }, + "user": { "index": 14, "kind": "property", "displayName": "User", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Basic authenticate user" } }, "headers": { "operation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.camel.component.es.ElasticsearchOperation", "enum": [ "Index", "Update", "Bulk", "GetById", "MultiGet", "MultiSearch", "Delete", "DeleteIndex", "Search", "Exists", "Ping" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation to perform", "constantName": "org.apache.camel.component.es.El [...] @@ -46,28 +47,30 @@ "scrollKeepAliveMs": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The starting index of the response.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_SCROLL_KEEP_ALIVE_MS" }, "useScroll": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Set to true to enable scroll usage", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_SCROLL" }, "size": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the response.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_SIZE" }, - "from": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The starting index of the response.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_FROM" } + "from": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The starting index of the response.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_FROM" }, + "enableDocumentOnlyMode": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "false", "description": "Indicates whether the body of the message contains only documents.", "constantName": "org.apache.camel.component.es.ElasticsearchConstants#PARAM_DOCUMENT_MODE" } }, "properties": { "clusterName": { "index": 0, "kind": "path", "displayName": "Cluster Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Name of the cluster" }, "connectionTimeout": { "index": 1, "kind": "parameter", "displayName": "Connection Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The time in ms to wait before connection will timeout." }, "disconnect": { "index": 2, "kind": "parameter", "displayName": "Disconnect", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Disconnect after it finish calling the producer" }, - "from": { "index": 3, "kind": "parameter", "displayName": "From", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Starting index of the response." }, - "hostAddresses": { "index": 4, "kind": "parameter", "displayName": "Host Addresses", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Comma separated list with ip:port formatted remote transport addresses to use." }, - "indexName": { "index": 5, "kind": "parameter", "displayName": "Index Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The name of the index to act against" }, - "maxRetryTimeout": { "index": 6, "kind": "parameter", "displayName": "Max Retry Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The time in ms before retry" }, - "operation": { "index": 7, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.es.ElasticsearchOperation", "enum": [ "Index", "Update", "Bulk", "GetById", "MultiGet", "MultiSearch", "Delete", "DeleteIndex", "Search", "Exists", "Ping" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "co [...] - "scrollKeepAliveMs": { "index": 8, "kind": "parameter", "displayName": "Scroll Keep Alive Ms", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Time in ms during which elasticsearch will keep search context alive" }, - "size": { "index": 9, "kind": "parameter", "displayName": "Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Size of the response." }, - "socketTimeout": { "index": 10, "kind": "parameter", "displayName": "Socket Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The timeout in ms to wait before the socket will timeout." }, - "useScroll": { "index": 11, "kind": "parameter", "displayName": "Use Scroll", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable scroll usage" }, - "waitForActiveShards": { "index": 12, "kind": "parameter", "displayName": "Wait For Active Shards", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Index creation waits for the write consistency number of shards to be available" }, - "lazyStartProducer": { "index": 13, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] - "documentClass": { "index": 14, "kind": "parameter", "displayName": "Document Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.Class<java.lang.Object>", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "ObjectNode", "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The class to use when deserializing the documents." }, - "enableSniffer": { "index": 15, "kind": "parameter", "displayName": "Enable Sniffer", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable automatically discover nodes from a running Elasticsearch cluster. If this [...] - "sniffAfterFailureDelay": { "index": 16, "kind": "parameter", "displayName": "Sniff After Failure Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The delay of a sniff execution scheduled after a failure (in mill [...] - "snifferInterval": { "index": 17, "kind": "parameter", "displayName": "Sniffer Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The interval between consecutive ordinary sniff executions in milliseconds. Will [...] - "certificatePath": { "index": 18, "kind": "parameter", "displayName": "Certificate Path", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The certificate that can be used to acc [...] - "enableSSL": { "index": 19, "kind": "parameter", "displayName": "Enable SSL", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable SSL" } + "enableDocumentOnlyMode": { "index": 3, "kind": "parameter", "displayName": "Enable Document Only Mode", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Indicates whether the body of the message contains only documents. By [...] + "from": { "index": 4, "kind": "parameter", "displayName": "From", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Starting index of the response." }, + "hostAddresses": { "index": 5, "kind": "parameter", "displayName": "Host Addresses", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Comma separated list with ip:port formatted remote transport addresses to use." }, + "indexName": { "index": 6, "kind": "parameter", "displayName": "Index Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The name of the index to act against" }, + "maxRetryTimeout": { "index": 7, "kind": "parameter", "displayName": "Max Retry Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The time in ms before retry" }, + "operation": { "index": 8, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.es.ElasticsearchOperation", "enum": [ "Index", "Update", "Bulk", "GetById", "MultiGet", "MultiSearch", "Delete", "DeleteIndex", "Search", "Exists", "Ping" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "co [...] + "scrollKeepAliveMs": { "index": 9, "kind": "parameter", "displayName": "Scroll Keep Alive Ms", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Time in ms during which elasticsearch will keep search context alive" }, + "size": { "index": 10, "kind": "parameter", "displayName": "Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Size of the response." }, + "socketTimeout": { "index": 11, "kind": "parameter", "displayName": "Socket Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The timeout in ms to wait before the socket will timeout." }, + "useScroll": { "index": 12, "kind": "parameter", "displayName": "Use Scroll", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable scroll usage" }, + "waitForActiveShards": { "index": 13, "kind": "parameter", "displayName": "Wait For Active Shards", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Index creation waits for the write consistency number of shards to be available" }, + "lazyStartProducer": { "index": 14, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...] + "documentClass": { "index": 15, "kind": "parameter", "displayName": "Document Class", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.Class<java.lang.Object>", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "ObjectNode", "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The class to use when deserializing the documents." }, + "enableSniffer": { "index": 16, "kind": "parameter", "displayName": "Enable Sniffer", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable automatically discover nodes from a running Elasticsearch cluster. If this [...] + "sniffAfterFailureDelay": { "index": 17, "kind": "parameter", "displayName": "Sniff After Failure Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The delay of a sniff execution scheduled after a failure (in mill [...] + "snifferInterval": { "index": 18, "kind": "parameter", "displayName": "Sniffer Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The interval between consecutive ordinary sniff executions in milliseconds. Will [...] + "certificatePath": { "index": 19, "kind": "parameter", "displayName": "Certificate Path", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "The certificate that can be used to acc [...] + "enableSSL": { "index": 20, "kind": "parameter", "displayName": "Enable SSL", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.es.ElasticsearchConfiguration", "configurationField": "configuration", "description": "Enable SSL" } } } diff --git a/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc b/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc index b6134529535..d64af28438c 100644 --- a/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc +++ b/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc @@ -102,8 +102,10 @@ You must set the name of the target index by setting the message header with the |Update |*byte[]*, *InputStream*, *String*, *Reader*, *Map* or any document type content to update |Updates content to an index and returns the content's indexId in the body. You can set the name of the target index by setting the message header with the key "indexName". You can set the indexId by setting the message header with -the key "indexId". - +the key "indexId". Be aware of the fact that unlike the component _camel-elasticsearch-rest_, by default, the expected content of +an update request must be the same as what the https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html[Update API expects], consequently +if you want to update one part of an existing document, you need to embed the content to update into a "doc" object. To change the default behavior, it is possible +to configure it globally at the component level thanks to the option _enableDocumentOnlyMode_ or by request by setting the header _ElasticsearchConstants.PARAM_DOCUMENT_MODE_ to true. |Ping |None |Pings the Elasticsearch cluster and returns true if the ping succeeded, false otherwise |=== @@ -184,7 +186,7 @@ from("direct:search") [source,java] ---- -String query = "{\"query\":{\"match\":{\"doc.content\":\"new release of ApacheCamel\"}}}"; +String query = "{\"query\":{\"match\":{\"content\":\"new release of ApacheCamel\"}}}"; HitsMetadata<?> response = template.requestBody("direct:search", query, HitsMetadata.class); ---- @@ -194,7 +196,7 @@ Search on specific field(s) using Map. [source,java] ---- Map<String, Object> actualQuery = new HashMap<>(); -actualQuery.put("doc.content", "new release of ApacheCamel"); +actualQuery.put("content", "new release of ApacheCamel"); Map<String, Object> match = new HashMap<>(); match.put("match", actualQuery); @@ -223,7 +225,7 @@ from("direct:search") [source,java] ---- -String query = "{\"query\":{\"match\":{\"doc.content\":\"new release of ApacheCamel\"}}}"; +String query = "{\"query\":{\"match\":{\"content\":\"new release of ApacheCamel\"}}}"; try (ElasticsearchScrollRequestIterator response = template.requestBody("direct:search", query, ElasticsearchScrollRequestIterator.class)) { // do something smart with results } diff --git a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchComponent.java b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchComponent.java index f59751d9257..9137fcd8f03 100644 --- a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchComponent.java +++ b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchComponent.java @@ -45,6 +45,8 @@ public class ElasticsearchComponent extends DefaultComponent { private int maxRetryTimeout = ElasticsearchConstants.MAX_RETRY_TIMEOUT; @Metadata(defaultValue = "" + ElasticsearchConstants.DEFAULT_CONNECTION_TIMEOUT) private int connectionTimeout = ElasticsearchConstants.DEFAULT_CONNECTION_TIMEOUT; + @Metadata(defaultValue = "false") + private boolean enableDocumentOnlyMode; @Metadata(label = "security", secret = true) private String user; @Metadata(label = "security", secret = true) @@ -84,6 +86,7 @@ public class ElasticsearchComponent extends DefaultComponent { config.setSnifferInterval(this.getSnifferInterval()); config.setSniffAfterFailureDelay(this.getSniffAfterFailureDelay()); config.setClusterName(remaining); + config.setEnableDocumentOnlyMode(this.isEnableDocumentOnlyMode()); Endpoint endpoint = new ElasticsearchEndpoint(uri, this, config, client); setProperties(endpoint, parameters); @@ -202,6 +205,21 @@ public class ElasticsearchComponent extends DefaultComponent { this.certificatePath = certificatePath; } + /** + * Indicates whether the body of the message contains only documents. By default, it is set to false to be able to + * do the same requests as what the Document API supports (see + * https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for more details). To ease the + * migration of routes based on the legacy component camel-elasticsearch-rest, you should consider enabling the mode + * especially if your routes do update operations. + */ + public boolean isEnableDocumentOnlyMode() { + return enableDocumentOnlyMode; + } + + public void setEnableDocumentOnlyMode(boolean enableDocumentOnlyMode) { + this.enableDocumentOnlyMode = enableDocumentOnlyMode; + } + /** * The time in ms before retry */ diff --git a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConfiguration.java b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConfiguration.java index 1cb3ce9ed2c..79cc8ae56fd 100644 --- a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConfiguration.java +++ b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConfiguration.java @@ -53,6 +53,8 @@ public class ElasticsearchConfiguration { private int maxRetryTimeout = ElasticsearchConstants.MAX_RETRY_TIMEOUT; @UriParam(defaultValue = "" + ElasticsearchConstants.DEFAULT_CONNECTION_TIMEOUT) private int connectionTimeout = ElasticsearchConstants.DEFAULT_CONNECTION_TIMEOUT; + @UriParam(defaultValue = "false") + private boolean enableDocumentOnlyMode; @UriParam private boolean disconnect; @UriParam(label = "security") @@ -314,4 +316,19 @@ public class ElasticsearchConfiguration { public void setDocumentClass(Class<?> documentClass) { this.documentClass = documentClass; } + + /** + * Indicates whether the body of the message contains only documents. By default, it is set to false to be able to + * do the same requests as what the Document API supports (see + * https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for more details). To ease the + * migration of routes based on the legacy component camel-elasticsearch-rest, you should consider enabling the mode + * especially if your routes do update operations. + */ + public boolean isEnableDocumentOnlyMode() { + return enableDocumentOnlyMode; + } + + public void setEnableDocumentOnlyMode(boolean enableDocumentOnlyMode) { + this.enableDocumentOnlyMode = enableDocumentOnlyMode; + } } diff --git a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConstants.java b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConstants.java index 40c743ae089..c937321e977 100644 --- a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConstants.java +++ b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConstants.java @@ -41,6 +41,9 @@ public interface ElasticsearchConstants { String PARAM_SIZE = "size"; @Metadata(description = "The starting index of the response.", javaType = "Integer") String PARAM_FROM = "from"; + @Metadata(description = "Indicates whether the body of the message contains only documents.", javaType = "Boolean", + defaultValue = "false") + String PARAM_DOCUMENT_MODE = "enableDocumentOnlyMode"; String PROPERTY_SCROLL_ES_QUERY_COUNT = "CamelElasticsearchScrollQueryCount"; diff --git a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java index 53670ca938d..64ee8bb3157 100644 --- a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java +++ b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java @@ -174,6 +174,11 @@ class ElasticsearchProducer extends DefaultAsyncProducer { message.setHeader(ElasticsearchConstants.PARAM_FROM, configuration.getFrom()); } + Boolean enableDocumentOnlyMode = message.getHeader(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.class); + if (enableDocumentOnlyMode == null) { + message.setHeader(ElasticsearchConstants.PARAM_DOCUMENT_MODE, configuration.isEnableDocumentOnlyMode()); + } + boolean configWaitForActiveShards = false; Integer waitForActiveShards = message.getHeader(ElasticsearchConstants.PARAM_WAIT_FOR_ACTIVE_SHARDS, Integer.class); if (waitForActiveShards == null) { diff --git a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java index 19835023e28..4ae90a194df 100644 --- a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java +++ b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java @@ -121,17 +121,20 @@ public final class ElasticsearchActionRequestConverter { return builder.id(exchange.getIn().getHeader(ElasticsearchConstants.PARAM_INDEX_ID, String.class)); } UpdateRequest.Builder<?, Object> builder = new UpdateRequest.Builder<>(); + Boolean enableDocumentOnlyMode + = exchange.getIn().getHeader(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.FALSE, Boolean.class); + Mode mode = enableDocumentOnlyMode == Boolean.TRUE ? Mode.DOCUMENT_ONLY : Mode.DEFAULT; if (document instanceof byte[]) { - builder.withJson(new ByteArrayInputStream((byte[]) document)); + mode.addDocToUpdateRequestBuilder(builder, new ByteArrayInputStream((byte[]) document)); } else if (document instanceof InputStream) { - builder.withJson((InputStream) document); + mode.addDocToUpdateRequestBuilder(builder, (InputStream) document); } else if (document instanceof String) { - builder.withJson(new StringReader((String) document)); + mode.addDocToUpdateRequestBuilder(builder, new StringReader((String) document)); } else if (document instanceof Reader) { - builder.withJson((Reader) document); + mode.addDocToUpdateRequestBuilder(builder, (Reader) document); } else if (document instanceof Map) { ObjectMapper objectMapper = new ObjectMapper(); - builder.withJson(new StringReader(objectMapper.writeValueAsString(document))); + mode.addDocToUpdateRequestBuilder(builder, new StringReader(objectMapper.writeValueAsString(document))); } else { builder.doc(document); } @@ -293,4 +296,34 @@ public final class ElasticsearchActionRequestConverter { } return null; } + + enum Mode { + DEFAULT { + @Override + protected void addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, InputStream in) { + builder.withJson(in); + } + + @Override + protected void addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, Reader in) { + builder.withJson(in); + } + + }, + DOCUMENT_ONLY { + @Override + protected void addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, InputStream in) { + builder.doc(JsonData.from(in)); + } + + @Override + protected void addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, Reader in) { + builder.doc(JsonData.from(in)); + } + }; + + protected abstract void addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, InputStream in); + + protected abstract void addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, Reader in); + } } diff --git a/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchBulkIT.java b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchBulkIT.java index bd5ab8f5bac..a5bc39e2cbe 100644 --- a/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchBulkIT.java +++ b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchBulkIT.java @@ -35,6 +35,7 @@ import co.elastic.clients.elasticsearch.core.bulk.DeleteOperation; import co.elastic.clients.elasticsearch.core.bulk.IndexOperation; import co.elastic.clients.elasticsearch.core.bulk.UpdateAction; import co.elastic.clients.elasticsearch.core.bulk.UpdateOperation; +import co.elastic.clients.json.JsonData; import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.camel.builder.RouteBuilder; import org.junit.jupiter.api.Test; @@ -220,10 +221,10 @@ class ElasticsearchBulkIT extends ElasticsearchTestSupport { .index("twitter").id(indexId) .action( new UpdateAction.Builder<>() - .withJson( + .doc(JsonData.from( new StringReader( - String.format("{ \"doc\": {\"%skey2\": \"%svalue2\"}}", - createPrefix(), createPrefix()))) + String.format("{\"%skey2\": \"%svalue2\"}", + createPrefix(), createPrefix())))) .build()); @SuppressWarnings("unchecked") List<BulkResponseItem> response = template.requestBody("direct:bulk", List.of(builder), List.class); diff --git a/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchGetSearchDeleteExistsUpdateIT.java b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchGetSearchDeleteExistsUpdateIT.java index a6673bf931b..c79fd106865 100644 --- a/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchGetSearchDeleteExistsUpdateIT.java +++ b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchGetSearchDeleteExistsUpdateIT.java @@ -277,12 +277,11 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor Map<String, Object> headers = new HashMap<>(); headers.put(ElasticsearchConstants.PARAM_OPERATION, ElasticsearchOperation.Bulk); headers.put(ElasticsearchConstants.PARAM_INDEX_NAME, "twitter"); - template.requestBodyAndHeaders("direct:start", List.of(Map.of("doc", map1), Map.of("doc", map2)), headers, - String.class); + template.requestBodyAndHeaders("direct:start", List.of(map1, map2), headers, String.class); // No match Map<String, Object> actualQuery = new HashMap<>(); - actualQuery.put("doc.testSearchWithMapQuery1", "bar"); + actualQuery.put("testSearchWithMapQuery1", "bar"); Map<String, Object> match = new HashMap<>(); match.put("match", actualQuery); Map<String, Object> query = new HashMap<>(); @@ -293,7 +292,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertEquals(0, response.total().value(), "response hits should be == 0"); // Match - actualQuery.put("doc.testSearchWithMapQuery1", "foo"); + actualQuery.put("testSearchWithMapQuery1", "foo"); // the result may see stale data so use Awaitility Awaitility.await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { HitsMetadata<?> resp = template.requestBody("direct:search", query, HitsMetadata.class); @@ -303,8 +302,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertEquals(1, resp.hits().size(), "response hits should be == 1"); Object result = resp.hits().get(0).source(); assertInstanceOf(ObjectNode.class, result); - assertTrue(((ObjectNode) result).has("doc")); - JsonNode node = ((ObjectNode) result).get("doc"); + JsonNode node = (ObjectNode) result; assertTrue(node.has("testSearchWithMapQuery1")); assertEquals("foo", node.get("testSearchWithMapQuery1").asText()); }); @@ -318,12 +316,11 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor Map<String, Object> headers = new HashMap<>(); headers.put(ElasticsearchConstants.PARAM_OPERATION, ElasticsearchOperation.Bulk); headers.put(ElasticsearchConstants.PARAM_INDEX_NAME, "twitter"); - template.requestBodyAndHeaders("direct:start", List.of(Map.of("doc", map1), Map.of("doc", map2)), headers, - String.class); + template.requestBodyAndHeaders("direct:start", List.of(map1, map2), headers, String.class); // No match String query = "{\n" - + " \"query\" : { \"match\" : { \"doc.testSearchWithStringQuery1\" : \"bar\" }}\n" + + " \"query\" : { \"match\" : { \"testSearchWithStringQuery1\" : \"bar\" }}\n" + "}\n"; HitsMetadata<?> response = template.requestBody("direct:search", query, HitsMetadata.class); @@ -333,7 +330,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor // Match String q = "{\n" - + " \"query\" : { \"match\" : { \"doc.testSearchWithStringQuery1\" : \"foo\" }}\n" + + " \"query\" : { \"match\" : { \"testSearchWithStringQuery1\" : \"foo\" }}\n" + "}\n"; // the result may see stale data so use Awaitility Awaitility.await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { @@ -344,8 +341,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertEquals(1, resp.hits().size(), "response hits should be == 1"); Object result = resp.hits().get(0).source(); assertInstanceOf(ObjectNode.class, result); - assertTrue(((ObjectNode) result).has("doc")); - JsonNode node = ((ObjectNode) result).get("doc"); + JsonNode node = (ObjectNode) result; assertTrue(node.has("testSearchWithStringQuery1")); assertEquals("foo", node.get("testSearchWithStringQuery1").asText()); }); @@ -359,13 +355,13 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor Map<String, Object> headers = new HashMap<>(); headers.put(ElasticsearchConstants.PARAM_OPERATION, ElasticsearchOperation.Bulk); headers.put(ElasticsearchConstants.PARAM_INDEX_NAME, "twitter"); - template.requestBodyAndHeaders("direct:start", List.of(Map.of("doc", map1), Map.of("doc", map2)), headers, + template.requestBodyAndHeaders("direct:start", List.of(map1, map2), headers, String.class); // No match SearchRequest.Builder builder = new SearchRequest.Builder() .query(new Query.Builder() - .match(new MatchQuery.Builder().field("doc.testSearchWithBuilder1").query("bar").build()).build()); + .match(new MatchQuery.Builder().field("testSearchWithBuilder1").query("bar").build()).build()); HitsMetadata<?> response = template.requestBody("direct:search", builder, HitsMetadata.class); assertNotNull(response, "response should not be null"); assertNotNull(response.total()); @@ -376,7 +372,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor Awaitility.await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { SearchRequest.Builder b = new SearchRequest.Builder() .query(new Query.Builder() - .match(new MatchQuery.Builder().field("doc.testSearchWithBuilder1").query("foo").build()).build()); + .match(new MatchQuery.Builder().field("testSearchWithBuilder1").query("foo").build()).build()); HitsMetadata<?> resp = template.requestBody("direct:search", b, HitsMetadata.class); assertNotNull(resp, "response should not be null"); @@ -385,8 +381,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertEquals(1, resp.hits().size(), "response hits should be == 1"); Object result = resp.hits().get(0).source(); assertInstanceOf(ObjectNode.class, result); - assertTrue(((ObjectNode) result).has("doc")); - JsonNode node = ((ObjectNode) result).get("doc"); + JsonNode node = (ObjectNode) result; assertTrue(node.has("testSearchWithBuilder1")); assertEquals("foo", node.get("testSearchWithBuilder1").asText()); }); @@ -415,7 +410,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor // No match SearchRequest.Builder builder = new SearchRequest.Builder() - .query(new Query.Builder().match(new MatchQuery.Builder().field("doc.id").query("bar").build()).build()); + .query(new Query.Builder().match(new MatchQuery.Builder().field("id").query("bar").build()).build()); HitsMetadata<?> response = template.requestBodyAndHeader( "direct:search", builder, ElasticsearchConstants.PARAM_DOCUMENT_CLASS, Product.class, HitsMetadata.class); assertNotNull(response, "response should not be null"); @@ -534,6 +529,29 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertEquals(createPrefix() + "value2", ((ObjectNode) response.source()).get(createPrefix() + "key2").asText()); } + @Test + void testUpdateWithMapInDocumentOnlyMode() { + Map<String, String> map = createIndexedData(); + String indexId = template.requestBody("direct:index", map, String.class); + assertNotNull(indexId, "indexId should be set"); + + Map<String, String> newMap = new HashMap<>(); + newMap.put(createPrefix() + "key2", createPrefix() + "value2"); + Map<String, Object> headers = new HashMap<>(); + headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId); + headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE); + indexId = template.requestBodyAndHeaders("direct:update", newMap, headers, String.class); + assertNotNull(indexId, "indexId should be set"); + + //now, verify GET succeeded + GetResponse<?> response = template.requestBody("direct:get", indexId, GetResponse.class); + assertNotNull(response, "response should not be null"); + assertNotNull(response.source(), "response source should not be null"); + assertInstanceOf(ObjectNode.class, response.source(), "response source should be a ObjectNode"); + assertTrue(((ObjectNode) response.source()).has(createPrefix() + "key2")); + assertEquals(createPrefix() + "value2", ((ObjectNode) response.source()).get(createPrefix() + "key2").asText()); + } + @Test void testGetWithHeaders() { //first, Index a value @@ -627,6 +645,26 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertEquals("123", indexId, "indexId should be equals to the provided id"); } + @Test + void testUpdateWithIDInHeaderInDocumentOnlyMode() { + Map<String, String> map = createIndexedData(); + Map<String, Object> headers = new HashMap<>(); + headers.put(ElasticsearchConstants.PARAM_OPERATION, ElasticsearchOperation.Index); + headers.put(ElasticsearchConstants.PARAM_INDEX_NAME, "twitter"); + headers.put(ElasticsearchConstants.PARAM_INDEX_ID, "123"); + + String indexId = template.requestBodyAndHeaders("direct:start", map, headers, String.class); + assertNotNull(indexId, "indexId should be set"); + assertEquals("123", indexId, "indexId should be equals to the provided id"); + + headers.put(ElasticsearchConstants.PARAM_OPERATION, ElasticsearchOperation.Update); + headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE); + + indexId = template.requestBodyAndHeaders("direct:start", map, headers, String.class); + assertNotNull(indexId, "indexId should be set"); + assertEquals("123", indexId, "indexId should be equals to the provided id"); + } + @Test void testGetRequestBody() { String prefix = createPrefix(); @@ -703,6 +741,27 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertThat(node.get(key).asText(), equalTo("testUpdateWithString-updated")); } + @Test + void testUpdateWithStringInDocumentOnlyMode() { + Map<String, String> map = createIndexedData(); + String indexId = template.requestBody("direct:index", map, String.class); + assertNotNull(indexId, "indexId should be set"); + String key = map.keySet().iterator().next(); + Object body = String.format("{\"%s\" : \"testUpdateWithString-updated\"}", key); + + Map<String, Object> headers = new HashMap<>(); + headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId); + headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE); + indexId = template.requestBodyAndHeaders("direct:update", body, headers, String.class); + assertNotNull(indexId, "indexId should be set"); + + GetResponse<?> response = template.requestBody("direct:get", indexId, GetResponse.class); + assertThat(response.source(), notNullValue()); + ObjectNode node = (ObjectNode) response.source(); + assertThat(node.has(key), equalTo(true)); + assertThat(node.get(key).asText(), equalTo("testUpdateWithString-updated")); + } + @Test void testUpdateWithReader() { Map<String, String> map = createIndexedData(); @@ -723,6 +782,27 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertThat(node.get(key).asText(), equalTo("testUpdateWithReader-updated")); } + @Test + void testUpdateWithReaderInDocumentOnlyMode() { + Map<String, String> map = createIndexedData(); + String indexId = template.requestBody("direct:index", map, String.class); + assertNotNull(indexId, "indexId should be set"); + String key = map.keySet().iterator().next(); + Object body = new StringReader(String.format("{\"%s\" : \"testUpdateWithReader-updated\"}", key)); + + Map<String, Object> headers = new HashMap<>(); + headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId); + headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE); + indexId = template.requestBodyAndHeaders("direct:update", body, headers, String.class); + assertNotNull(indexId, "indexId should be set"); + + GetResponse<?> response = template.requestBody("direct:get", indexId, GetResponse.class); + assertThat(response.source(), notNullValue()); + ObjectNode node = (ObjectNode) response.source(); + assertThat(node.has(key), equalTo(true)); + assertThat(node.get(key).asText(), equalTo("testUpdateWithReader-updated")); + } + @Test void testUpdateWithBytes() { Map<String, String> map = createIndexedData(); @@ -744,6 +824,28 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertThat(node.get(key).asText(), equalTo("testUpdateWithBytes-updated")); } + @Test + void testUpdateWithBytesInDocumentOnlyMode() { + Map<String, String> map = createIndexedData(); + String indexId = template.requestBody("direct:index", map, String.class); + assertNotNull(indexId, "indexId should be set"); + String key = map.keySet().iterator().next(); + Object body + = String.format("{\"%s\" : \"testUpdateWithBytes-updated\"}", key).getBytes(StandardCharsets.UTF_8); + + Map<String, Object> headers = new HashMap<>(); + headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId); + headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE); + indexId = template.requestBodyAndHeaders("direct:update", body, headers, String.class); + assertNotNull(indexId, "indexId should be set"); + + GetResponse<?> response = template.requestBody("direct:get", indexId, GetResponse.class); + assertThat(response.source(), notNullValue()); + ObjectNode node = (ObjectNode) response.source(); + assertThat(node.has(key), equalTo(true)); + assertThat(node.get(key).asText(), equalTo("testUpdateWithBytes-updated")); + } + @Test void testUpdateWithInputStream() { Map<String, String> map = createIndexedData(); @@ -766,6 +868,29 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends ElasticsearchTestSuppor assertThat(node.get(key).asText(), equalTo("testUpdateWithInputStream-updated")); } + @Test + void testUpdateWithInputStreamInDocumentOnlyMode() { + Map<String, String> map = createIndexedData(); + String indexId = template.requestBody("direct:index", map, String.class); + assertNotNull(indexId, "indexId should be set"); + String key = map.keySet().iterator().next(); + Object body = new ByteArrayInputStream( + String.format("{\"%s\" : \"testUpdateWithInputStream-updated\"}", key) + .getBytes(StandardCharsets.UTF_8)); + + Map<String, Object> headers = new HashMap<>(); + headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId); + headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE); + indexId = template.requestBodyAndHeaders("direct:update", body, headers, String.class); + assertNotNull(indexId, "indexId should be set"); + + GetResponse<?> response = template.requestBody("direct:get", indexId, GetResponse.class); + assertThat(response.source(), notNullValue()); + ObjectNode node = (ObjectNode) response.source(); + assertThat(node.has(key), equalTo(true)); + assertThat(node.get(key).asText(), equalTo("testUpdateWithInputStream-updated")); + } + @Test void testUpdateWithDocumentType() { Product product = new Product(); diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ElasticsearchComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ElasticsearchComponentBuilderFactory.java index 8e37853f6c3..f5625fe6120 100644 --- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ElasticsearchComponentBuilderFactory.java +++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ElasticsearchComponentBuilderFactory.java @@ -66,6 +66,25 @@ public interface ElasticsearchComponentBuilderFactory { doSetProperty("connectionTimeout", connectionTimeout); return this; } + /** + * Indicates whether the body of the message contains only documents. By + * default, it is set to false to be able to do the same requests as + * what the Document API supports (see + * https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for more details). To ease the migration of routes based on the legacy component camel-elasticsearch-rest, you should consider enabling the mode especially if your routes do update operations. + * + * The option is a: <code>boolean</code> type. + * + * Default: false + * Group: producer + * + * @param enableDocumentOnlyMode the value to set + * @return the dsl builder + */ + default ElasticsearchComponentBuilder enableDocumentOnlyMode( + boolean enableDocumentOnlyMode) { + doSetProperty("enableDocumentOnlyMode", enableDocumentOnlyMode); + return this; + } /** * Comma separated list with ip:port formatted remote transport * addresses to use. The ip and port options must be left blank for @@ -308,6 +327,7 @@ public interface ElasticsearchComponentBuilderFactory { Object value) { switch (name) { case "connectionTimeout": ((ElasticsearchComponent) component).setConnectionTimeout((int) value); return true; + case "enableDocumentOnlyMode": ((ElasticsearchComponent) component).setEnableDocumentOnlyMode((boolean) value); return true; case "hostAddresses": ((ElasticsearchComponent) component).setHostAddresses((java.lang.String) value); return true; case "lazyStartProducer": ((ElasticsearchComponent) component).setLazyStartProducer((boolean) value); return true; case "maxRetryTimeout": ((ElasticsearchComponent) component).setMaxRetryTimeout((int) value); return true; diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ElasticsearchEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ElasticsearchEndpointBuilderFactory.java index 72bc1897aa2..051957ba090 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ElasticsearchEndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ElasticsearchEndpointBuilderFactory.java @@ -106,6 +106,45 @@ public interface ElasticsearchEndpointBuilderFactory { doSetProperty("disconnect", disconnect); return this; } + /** + * Indicates whether the body of the message contains only documents. By + * default, it is set to false to be able to do the same requests as + * what the Document API supports (see + * https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for more details). To ease the migration of routes based on the legacy component camel-elasticsearch-rest, you should consider enabling the mode especially if your routes do update operations. + * + * The option is a: <code>boolean</code> type. + * + * Default: false + * Group: producer + * + * @param enableDocumentOnlyMode the value to set + * @return the dsl builder + */ + default ElasticsearchEndpointBuilder enableDocumentOnlyMode( + boolean enableDocumentOnlyMode) { + doSetProperty("enableDocumentOnlyMode", enableDocumentOnlyMode); + return this; + } + /** + * Indicates whether the body of the message contains only documents. By + * default, it is set to false to be able to do the same requests as + * what the Document API supports (see + * https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for more details). To ease the migration of routes based on the legacy component camel-elasticsearch-rest, you should consider enabling the mode especially if your routes do update operations. + * + * The option will be converted to a <code>boolean</code> + * type. + * + * Default: false + * Group: producer + * + * @param enableDocumentOnlyMode the value to set + * @return the dsl builder + */ + default ElasticsearchEndpointBuilder enableDocumentOnlyMode( + String enableDocumentOnlyMode) { + doSetProperty("enableDocumentOnlyMode", enableDocumentOnlyMode); + return this; + } /** * Starting index of the response. * @@ -825,6 +864,20 @@ public interface ElasticsearchEndpointBuilderFactory { public String from() { return "from"; } + + /** + * Indicates whether the body of the message contains only documents. + * + * The option is a: {@code Boolean} type. + * + * Default: false + * Group: producer + * + * @return the name of the header {@code enableDocumentOnlyMode}. + */ + public String enableDocumentOnlyMode() { + return "enableDocumentOnlyMode"; + } } static ElasticsearchEndpointBuilder endpointBuilder( String componentName,
