This is an automated email from the ASF dual-hosted git repository.
nfilotto pushed a commit to branch camel-3.21.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-3.21.x by this push:
new f9862684074 CAMEL-19752: camel-elasticsearch - Add a doc-only mode to
ease migration (#11286)
f9862684074 is described below
commit f9862684074b8ce751286e5790d180863f072719
Author: Nicolas Filotto <[email protected]>
AuthorDate: Sat Sep 2 10:00:38 2023 +0200
CAMEL-19752: camel-elasticsearch - Add a doc-only mode to ease migration
(#11286)
## Motivation
For some operations like update, the payload could need to be embedded in a
"doc" JSON object which makes the migration from `camel-elasticsearch-rest`
more complex.
## Modifications
* Add the new component option `enableDocumentOnlyMode` to be able to
switch globally to a mode that allows the same body content as the legacy
component `camel-elasticsearch-rest` to ease the migration
* Add the new header `enableDocumentOnlyMode` to be able to switch per
request to a mode that allows the same body content as the legacy component
`camel-elasticsearch-rest` to ease the migration
* Add more doc about the specific behavior of the update operation
* Fix all the tests that don't use requests that don't need to be embedded
in a "doc" JSON object
---
.../camel/catalog/components/elasticsearch.json | 5 +-
.../es/ElasticsearchComponentConfigurer.java | 6 +
.../es/ElasticsearchEndpointConfigurer.java | 6 +
.../es/ElasticsearchEndpointUriFactory.java | 3 +-
.../apache/camel/component/es/elasticsearch.json | 5 +-
.../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, 330 insertions(+), 34 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 e6fced6c23a..7024f042d07 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,6 +23,7 @@
},
"componentProperties": {
"connectionTimeout": { "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." },
+ "enableDocumentOnlyMode": { "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.elastic.co\/guide\ [...]
"hostAddresses": { "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": { "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 during star [...]
"maxRetryTimeout": { "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" },
@@ -46,12 +47,14 @@
"scrollKeepAliveMs": { "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": { "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": { "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": { "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": { "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": { "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": { "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": { "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": { "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" },
+ "enableDocumentOnlyMode": { "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 default, it [...]
"from": { "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": { "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": { "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" },
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 e6fced6c23a..7024f042d07 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,6 +23,7 @@
},
"componentProperties": {
"connectionTimeout": { "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." },
+ "enableDocumentOnlyMode": { "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.elastic.co\/guide\ [...]
"hostAddresses": { "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": { "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 during star [...]
"maxRetryTimeout": { "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" },
@@ -46,12 +47,14 @@
"scrollKeepAliveMs": { "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": { "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": { "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": { "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": { "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": { "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": { "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": { "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": { "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" },
+ "enableDocumentOnlyMode": { "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 default, it [...]
"from": { "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": { "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": { "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" },
diff --git
a/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc
b/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc
index 0faff49609e..14e2934ec89 100644
--- a/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc
+++ b/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc
@@ -101,8 +101,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
|===
@@ -183,7 +185,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);
----
@@ -193,7 +195,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);
@@ -222,7 +224,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 0cded24d9bc..109a122a709 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")
@@ -313,4 +315,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 dc13751e598..928c849f88e 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
@@ -175,6 +175,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 df50af5eb70..cb4ff5a6e4c 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 2cc5c5dbb52..9f3d20022d8 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.
*
@@ -822,6 +861,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,