diff --git a/.github/workflows/ci-actions.yml b/.github/workflows/ci-actions.yml
index 18bcd9b96d7d5..e6e919c85fc88 100644
--- a/.github/workflows/ci-actions.yml
+++ b/.github/workflows/ci-actions.yml
@@ -451,14 +451,20 @@ jobs:
hibernate-orm-rest-data-panache
- category: Data5
postgres: "true"
- timeout: 60
+ timeout: 65
test-modules: >
jpa-postgresql
- hibernate-search-elasticsearch
narayana-stm
narayana-jta
reactive-pg-client
hibernate-reactive-postgresql
+ - category: Data6
+ postgres: "true"
+ timeout: 40
+ test-modules: >
+ elasticsearch-rest-client
+ elasticsearch-rest-high-level-client
+ hibernate-search-elasticsearch
- category: Amazon
amazonServices: "true"
timeout: 45
diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 80b0ff2d47d73..b22defaebe009 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -460,6 +460,16 @@
quarkus-datasource-deployment${project.version}
+
+ io.quarkus
+ quarkus-elasticsearch-rest-client-common
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-elasticsearch-rest-client-common-deployment
+ ${project.version}
+ io.quarkusquarkus-elasticsearch-rest-client
@@ -470,6 +480,16 @@
quarkus-elasticsearch-rest-client-deployment${project.version}
+
+ io.quarkus
+ quarkus-elasticsearch-rest-high-level-client
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-elasticsearch-rest-high-level-client-deployment
+ ${project.version}
+ io.quarkusquarkus-security
@@ -3408,6 +3428,18 @@
elasticsearch-rest-client${elasticsearch-rest-client.version}
+
+ org.elasticsearch.client
+ elasticsearch-rest-high-level-client
+ ${elasticsearch-rest-client.version}
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+
+
+ org.elasticsearch.clientelasticsearch-rest-client-sniffer
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/Feature.java b/core/deployment/src/main/java/io/quarkus/deployment/Feature.java
index 8aaf6daf1a6a5..56bab5e6a90d5 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/Feature.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/Feature.java
@@ -4,7 +4,7 @@
/**
* Represents a feature provided by a core extension.
- *
+ *
* @see FeatureBuildItem
*/
public enum Feature {
@@ -23,7 +23,9 @@ public enum Feature {
CDI,
CONFIG_YAML,
CONSUL_CONFIG,
+ ELASTICSEARCH_REST_CLIENT_COMMON,
ELASTICSEARCH_REST_CLIENT,
+ ELASTICSEARCH_REST_HIGH_LEVEL_CLIENT,
FLYWAY,
GRPC_CLIENT,
GRPC_SERVER,
diff --git a/docs/pom.xml b/docs/pom.xml
index 2c3c259013cc1..64c7c91d1e3ce 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -117,6 +117,7 @@
${protoc.version}${os-maven-plugin.version}${protobuf-maven-plugin.version}
+ ${elasticsearch-server.version}${quarkus-home-url}
diff --git a/docs/src/main/asciidoc/elasticsearch.adoc b/docs/src/main/asciidoc/elasticsearch.adoc
new file mode 100644
index 0000000000000..f9a8e2e06ea9b
--- /dev/null
+++ b/docs/src/main/asciidoc/elasticsearch.adoc
@@ -0,0 +1,417 @@
+////
+This guide is maintained in the main Quarkus repository
+and pull requests should be submitted there:
+https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
+////
+= Quarkus - Connecting to an Elasticsearch cluster
+include::./attributes.adoc[]
+:extension-status: preview
+
+Elasticsearch is a well known full text search engine and NoSQL datastore.
+
+In this guide, we will see how you can get your REST services to use an Elasticsearch cluster.
+
+Quarkus provides two ways of accessing Elasticsearch: via the lower level `RestClient` or via the `RestHighLevelClient` we will call them
+the low level and the high level clients.
+
+include::./status-include.adoc[]
+
+== Prerequisites
+
+To complete this guide, you need:
+
+* less than 15 minutes
+* an IDE
+* JDK 1.8+ installed with `JAVA_HOME` configured appropriately
+* Apache Maven {maven-version}
+* Elasticsearch installed or Docker installed
+
+== Architecture
+
+The application built in this guide is quite simple: the user can add elements in a list using a form and the list is updated.
+
+All the information between the browser and the server is formatted as JSON.
+
+The elements are stored in Elasticsearch.
+
+== Solution
+
+We recommend that you follow the instructions in the next sections and create the application step by step.
+However, you can go right to the completed example.
+
+Clone the Git repository: `git clone {quickstarts-clone-url}`, or download an {quickstarts-archive-url}[archive].
+
+The solution for the low level client is located in the `elasticsearch-rest-client-quickstart` {quickstarts-tree-url}/elasticsearch-rest-client-quickstart[directory].
+
+The solution for the high level client is located in the `elasticsearch-rest-high-level-client-quickstart` {quickstarts-tree-url}/elasticsearch-rest-high-level-client-quickstart[directory].
+
+== Creating the Maven project
+
+First, we need a new project. Create a new project with the following command:
+
+[source,shell,subs=attributes+]
+----
+mvn io.quarkus:quarkus-maven-plugin:{quarkus-version}:create \
+ -DprojectGroupId=org.acme \
+ -DprojectArtifactId=elasticsearch-quickstart \
+ -DclassName="org.acme.elasticsearch.FruitResource" \
+ -Dpath="/fruits" \
+ -Dextensions="resteasy-jackson,elasticsearch-rest-client"
+cd elasticsearch-quickstart
+----
+
+This command generates a Maven structure importing the RESTEasy/JAX-RS, Jackson, and the Elasticsearch low level client extensions.
+After this, the `quarkus-elasticsearch-rest-client` extension has been added to your `pom.xml`.
+
+If you want to use the high level client instead, replace the `elasticsearch-rest-client` extension by the `elasticsearch-rest-high-level-client` extension.
+
+[NOTE]
+====
+We use the `resteasy-jackson` extension here and not the JSON-B variant because we will use the Vert.x `JsonObject` helper
+to serialize/deserialize our objects to/from Elasticsearch and it uses Jackson under the hood.
+====
+
+If you don’t want to generate a new project, add the following dependencies to your pom.xml.
+
+For the Elasticsearch low level client, add:
+
+[source,xml]
+----
+
+ io.quarkus
+ quarkus-elasticsearch-rest-client
+
+----
+
+For the Elasticsearch high level client, add:
+
+[source,xml]
+----
+
+ io.quarkus
+ quarkus-elasticsearch-rest-high-level-client
+
+----
+
+== Creating your first JSON REST service
+
+In this example, we will create an application to manage a list of fruits.
+
+First, let's create the `Fruit` bean as follows:
+
+[source,java]
+----
+package org.acme.elasticsearch;
+
+public class Fruit {
+ public String id;
+ public String name;
+ public String color;
+}
+----
+
+Nothing fancy. One important thing to note is that having a default constructor is required by the JSON serialization layer.
+
+Now create a `org.acme.elasticsearch.FruitService` that will be the business layer of our application and store/load the fruits from the Elasticsearch instance.
+Here we use the low level client, if you want to use the high level client instead follow the instructions in the link:#using-the-high-level-rest-client[Using the High Level REST Client] paragraph instead.
+
+[source,java]
+----
+package org.acme.elasticsearch;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.apache.http.util.EntityUtils;
+import org.elasticsearch.client.Request;
+import org.elasticsearch.client.Response;
+import org.elasticsearch.client.RestClient;
+
+import io.vertx.core.json.JsonArray;
+import io.vertx.core.json.JsonObject;
+
+@ApplicationScoped
+public class FruitService {
+ @Inject
+ RestClient restClient; //<1>
+
+ public void index(Fruit fruit) throws IOException {
+ Request request = new Request(
+ "PUT",
+ "/fruits/_doc/" + fruit.id); //<2>
+ request.setJsonEntity(JsonObject.mapFrom(fruit).toString()); //<3>
+ restClient.performRequest(request); //<4>
+ }
+
+ public Fruit get(String id) throws IOException {
+ Request request = new Request(
+ "GET",
+ "/fruits/_doc/" + id);
+ Response response = restClient.performRequest(request);
+ String responseBody = EntityUtils.toString(response.getEntity());
+ JsonObject json = new JsonObject(responseBody); //<5>
+ return json.getJsonObject("_source").mapTo(Fruit.class);
+ }
+
+ public List searchByColor(String color) throws IOException {
+ return search("color", color);
+ }
+
+ public List searchByName(String name) throws IOException {
+ return search("name", name);
+ }
+
+ private List search(String term, String match) throws IOException {
+ Request request = new Request(
+ "GET",
+ "/fruits/_search");
+ //construct a JSON query like {"query": {"match": {"": " results = new ArrayList<>(hits.size());
+ for (int i = 0; i < hits.size(); i++) {
+ JsonObject hit = hits.getJsonObject(i);
+ Fruit fruit = hit.getJsonObject("_source").mapTo(Fruit.class);
+ results.add(fruit);
+ }
+ return results;
+ }
+}
+----
+
+In this example you can note the following:
+
+1. We inject an Elasticsearch low level `RestClient` into our service.
+2. We create an Elasticsearch request.
+3. We use Vert.x `JsonObject` to serialize the object before sending it to Elasticsearch, you can use whatever you want to serialize to JSON.
+4. We send the request (indexing request here) to Elasticsearch.
+5. In order to deserialize the object from Elasticsearch, we again use Vert.x `JsonObject`.
+
+Now, edit the `org.acme.elasticsearch.FruitResource` class as follows:
+
+[source,java]
+----
+@Path("/fruits")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class FruitResource {
+ @Inject
+ FruitService fruitService;
+
+ @POST
+ public Response index(Fruit fruit) throws IOException {
+ if (fruit.id == null) {
+ fruit.id = UUID.randomUUID().toString();
+ }
+ fruitService.index(fruit);
+ return Response.created(URI.create("/fruits/" + fruit.id)).build();
+ }
+
+ @GET
+ @Path("/{id}")
+ public Fruit get(@PathParam("id") String id) throws IOException {
+ return fruitService.get(id);
+ }
+
+ @GET
+ @Path("/search")
+ public List search(@QueryParam("name") String name, @QueryParam("color") String color) throws IOException {
+ if (name != null) {
+ return fruitService.searchByName(name);
+ } else if (color != null) {
+ return fruitService.searchByColor(color);
+ } else {
+ throw new BadRequestException("Should provide name or color query parameter");
+ }
+ }
+
+}
+----
+
+The implementation is pretty straightforward and you just need to define your endpoints using the JAX-RS annotations and use the `FruitService` to list/add new fruits.
+
+== Configuring Elasticsearch
+The main property to configure is the URL to connect to the Elasticsearch cluster.
+
+A sample configuration should look like this:
+
+[source,properties]
+----
+# configure the Elasticsearch client for a cluster of two nodes
+quarkus.elasticsearch.hosts = elasticsearch1:9200,elasticsearch2:9200
+----
+
+In this example, we are using a single instance running on localhost:
+
+[source,properties]
+----
+# configure the Elasticsearch client for a single instance on localhost
+quarkus.elasticsearch.hosts = localhost:9200
+----
+
+If you need a more advanced configuration, you can find the comprehensive list of supported configuration properties at the end of this guide.
+
+
+== Running an Elasticsearch cluster
+
+As by default, the Elasticsearch client is configured to access a local Elasticsearch cluster on port 9200 (the default Elasticsearch port),
+if you have a local running instance on this port, there is nothing more to do before being able to test it!
+
+If you want to use Docker to run an Elasticsearch instance, you can use the following command to launch one:
+
+[source,shell,subs=attributes+]
+----
+docker run --name elasticsearch -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms512m -Xmx512m"\
+ --rm -p 9200:9200 docker.elastic.co/elasticsearch/elasticsearch-oss:{elasticsearch-version}
+----
+
+== Creating a frontend
+
+Now let's add a simple web page to interact with our `FruitResource`.
+Quarkus automatically serves static resources located under the `META-INF/resources` directory.
+In the `src/main/resources/META-INF/resources` directory, add a `fruits.html` file with the content from this {quickstarts-blob-url}/elasticsearch-low-level-client-quickstart/src/main/resources/META-INF/resources/fruits.html[fruits.html] file in it.
+
+You can now interact with your REST service:
+
+* start Quarkus with `./mvnw quarkus:dev`
+* open a browser to `http://localhost:8080/fruits.html`
+* add new fruits to the list via the 'Add fruit' form
+* search for fruits by name or color via the 'Search Fruit' form
+
+== Using the High Level REST Client
+
+Quarkus provides support for the Elasticsearch High Level REST Client but keep in mind that it comes with some caveats:
+
+- It drags a lot of dependencies - especially Lucene -, which doesn't fit well with Quarkus philosophy. The Elasticsearch team is aware of this issue and it might improve sometime in the future.
+- It is tied to a certain version of the Elasticsearch server: you cannot use a High Level REST Client version 7 to access a server version 6.
+
+Here is a version of the `FruitService` using the high level client instead of the low level one:
+
+[source,java]
+----
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.elasticsearch.action.get.GetRequest;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+
+import io.vertx.core.json.JsonObject;
+
+@ApplicationScoped
+public class FruitService {
+ @Inject
+ RestHighLevelClient restHighLevelClient; // <1>
+
+ public void index(Fruit fruit) throws IOException {
+ IndexRequest request = new IndexRequest("fruits"); // <2>
+ request.id(fruit.id);
+ request.source(JsonObject.mapFrom(fruit).toString(), XContentType.JSON); // <3>
+ restHighLevelClient.index(request, RequestOptions.DEFAULT); // <4>
+ }
+
+ public Fruit get(String id) throws IOException {
+ GetRequest getRequest = new GetRequest("fruits", id);
+ GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
+ if (getResponse.isExists()) {
+ String sourceAsString = getResponse.getSourceAsString();
+ JsonObject json = new JsonObject(sourceAsString); // <5>
+ return json.mapTo(Fruit.class);
+ }
+ return null;
+ }
+
+ public List searchByColor(String color) throws IOException {
+ return search("color", color);
+ }
+
+ public List searchByName(String name) throws IOException {
+ return search("name", name);
+ }
+
+ private List search(String term, String match) throws IOException {
+ SearchRequest searchRequest = new SearchRequest("fruits");
+ SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+ searchSourceBuilder.query(QueryBuilders.matchQuery(term, match));
+ searchRequest.source(searchSourceBuilder);
+
+ SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+ SearchHits hits = searchResponse.getHits();
+ List results = new ArrayList<>(hits.getHits().length);
+ for (SearchHit hit : hits.getHits()) {
+ String sourceAsString = hit.getSourceAsString();
+ JsonObject json = new JsonObject(sourceAsString);
+ results.add(json.mapTo(Fruit.class));
+ }
+ return results;
+ }
+}
+----
+
+In this example you can note the following:
+
+1. We inject an Elasticsearch `RestHighLevelClient` inside the service.
+2. We create an Elasticsearch index request.
+3. We use Vert.x `JsonObject` to serialize the object before sending it to Elasticsearch, you can use whatever you want to serialize to JSON.
+4. We send the request to Elasticsearch.
+5. In order to deserialize the object from Elasticsearch, we again use Vert.x `JsonObject`.
+
+== Hibernate Search Elasticsearch
+
+Quarkus supports Hibernate Search with Elasticsearch via the `hibernate-search-elasticsearch` extension.
+
+Hibernate Search Elasticsearch allows to synchronize your JPA entities to an Elasticsearch cluster and offers a way to query your Elasticsearch cluster using the Hibernate Search API.
+
+If you're interested in it, you can read the link:hibernate-search-elasticsearch[Hibernate Search with Elasticsearch guide].
+
+== Cluster Health Check
+
+If you are using the `quarkus-smallrye-health` extension, both the extension will automatically add a readiness health check
+to validate the health of the cluster.
+
+So when you access the `/health/ready` endpoint of your application you will have information about the cluster status.
+It uses the cluster health endpoint, the check will be down if the status of the cluster is **red**, or the cluster is not available.
+
+This behavior can be disabled by setting the `quarkus.elasticsearch.health.enabled` property to `false` in your `application.properties`.
+
+== Building a native executable
+
+You can use both clients in a native executable.
+
+You can build a native executable with the usual command `./mvnw package -Pnative`.
+
+Running it is as simple as executing `./target/elasticsearch-low-level-client-quickstart-1.0-SNAPSHOT-runner`.
+
+You can then point your browser to `http://localhost:8080/fruits.html` and use your application.
+
+== Conclusion
+
+Accessing an Elasticsearch cluster from a low level or a high level client is easy with Quarkus as it provides easy configuration, CDI integration and native support for it.
+
+== Configuration Reference
+
+include::{generated-dir}/config/quarkus-elasticsearch-low-level-client.adoc[opts=optional, leveloffset=+1]
diff --git a/docs/src/main/asciidoc/hibernate-search-elasticsearch.adoc b/docs/src/main/asciidoc/hibernate-search-elasticsearch.adoc
index 970263147de92..117b4854b954f 100644
--- a/docs/src/main/asciidoc/hibernate-search-elasticsearch.adoc
+++ b/docs/src/main/asciidoc/hibernate-search-elasticsearch.adoc
@@ -618,9 +618,9 @@ We need a PostgreSQL instance and an Elasticsearch cluster.
Let's use Docker to start one of each:
-[source, shell]
+[source, shell,subs=attributes+]
----
-docker run -it --rm=true --name elasticsearch_quarkus_test -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.7.0
+docker run -it --rm=true --name elasticsearch_quarkus_test -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch-oss:{elasticsearch-version}
----
[source, shell]
diff --git a/extensions/elasticsearch-rest-client-common/deployment/pom.xml b/extensions/elasticsearch-rest-client-common/deployment/pom.xml
new file mode 100644
index 0000000000000..3a4a0a046bbcd
--- /dev/null
+++ b/extensions/elasticsearch-rest-client-common/deployment/pom.xml
@@ -0,0 +1,43 @@
+
+
+
+ quarkus-elasticsearch-rest-client-common-parent
+ io.quarkus
+ 999-SNAPSHOT
+ ../
+
+ 4.0.0
+
+ quarkus-elasticsearch-rest-client-common-deployment
+ Quarkus - Elasticsearch REST client - Deployment
+
+
+
+ io.quarkus
+ quarkus-core-deployment
+
+
+ io.quarkus
+ quarkus-elasticsearch-rest-client-common
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
diff --git a/extensions/elasticsearch-rest-client/deployment/src/main/java/io/quarkus/elasticsearch/restclient/deployment/ElasticsearchRestClientProcessor.java b/extensions/elasticsearch-rest-client-common/deployment/src/main/java/io/quarkus/elasticsearch/restclient/common/deployment/ElasticsearchRestClientProcessor.java
similarity index 81%
rename from extensions/elasticsearch-rest-client/deployment/src/main/java/io/quarkus/elasticsearch/restclient/deployment/ElasticsearchRestClientProcessor.java
rename to extensions/elasticsearch-rest-client-common/deployment/src/main/java/io/quarkus/elasticsearch/restclient/common/deployment/ElasticsearchRestClientProcessor.java
index a867768b6b965..e59d5977a97cb 100644
--- a/extensions/elasticsearch-rest-client/deployment/src/main/java/io/quarkus/elasticsearch/restclient/deployment/ElasticsearchRestClientProcessor.java
+++ b/extensions/elasticsearch-rest-client-common/deployment/src/main/java/io/quarkus/elasticsearch/restclient/common/deployment/ElasticsearchRestClientProcessor.java
@@ -1,4 +1,4 @@
-package io.quarkus.elasticsearch.restclient.deployment;
+package io.quarkus.elasticsearch.restclient.common.deployment;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
@@ -10,6 +10,6 @@ class ElasticsearchRestClientProcessor {
@BuildStep
public void build(BuildProducer extensionSslNativeSupport) {
// Indicates that this extension would like the SSL support to be enabled
- extensionSslNativeSupport.produce(new ExtensionSslNativeSupportBuildItem(Feature.ELASTICSEARCH_REST_CLIENT.getName()));
+ extensionSslNativeSupport.produce(new ExtensionSslNativeSupportBuildItem(Feature.ELASTICSEARCH_REST_CLIENT_COMMON));
}
}
diff --git a/extensions/elasticsearch-rest-client-common/pom.xml b/extensions/elasticsearch-rest-client-common/pom.xml
new file mode 100644
index 0000000000000..0f20c640641ab
--- /dev/null
+++ b/extensions/elasticsearch-rest-client-common/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ quarkus-build-parent
+ io.quarkus
+ 999-SNAPSHOT
+ ../../build-parent/pom.xml
+
+ 4.0.0
+
+ quarkus-elasticsearch-rest-client-common-parent
+ Quarkus - Elasticsearch client common
+ pom
+
+ deployment
+ runtime
+
+
diff --git a/extensions/elasticsearch-rest-client-common/runtime/pom.xml b/extensions/elasticsearch-rest-client-common/runtime/pom.xml
new file mode 100644
index 0000000000000..49bee4f77e45f
--- /dev/null
+++ b/extensions/elasticsearch-rest-client-common/runtime/pom.xml
@@ -0,0 +1,71 @@
+
+
+
+ quarkus-elasticsearch-rest-client-common-parent
+ io.quarkus
+ 999-SNAPSHOT
+ ../
+
+ 4.0.0
+
+ quarkus-elasticsearch-rest-client-common
+ Quarkus - Elasticsearch REST client common - Runtime
+ Elasticsearch REST client common
+
+
+ io.quarkus
+ quarkus-core
+
+
+ org.elasticsearch.client
+ elasticsearch-rest-client
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.jboss.logging
+ commons-logging-jboss-logging
+
+
+ org.elasticsearch.client
+ elasticsearch-rest-client-sniffer
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.graalvm.nativeimage
+ svm
+
+
+
+
+
+
+ io.quarkus
+ quarkus-bootstrap-maven-plugin
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
diff --git a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/runtime/graal/Substitute_RestClient.java b/extensions/elasticsearch-rest-client-common/runtime/src/main/java/io/quarkus/elasticsearch/restclient/common/runtime/graal/Substitute_RestClient.java
similarity index 98%
rename from extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/runtime/graal/Substitute_RestClient.java
rename to extensions/elasticsearch-rest-client-common/runtime/src/main/java/io/quarkus/elasticsearch/restclient/common/runtime/graal/Substitute_RestClient.java
index 1d730e80f53e6..8807153ae936e 100644
--- a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/runtime/graal/Substitute_RestClient.java
+++ b/extensions/elasticsearch-rest-client-common/runtime/src/main/java/io/quarkus/elasticsearch/restclient/common/runtime/graal/Substitute_RestClient.java
@@ -1,4 +1,4 @@
-package io.quarkus.elasticsearch.restclient.runtime.graal;
+package io.quarkus.elasticsearch.restclient.common.runtime.graal;
import java.util.ArrayList;
import java.util.Collection;
diff --git a/extensions/elasticsearch-rest-client/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/elasticsearch-rest-client-common/runtime/src/main/resources/META-INF/quarkus-extension.yaml
similarity index 71%
rename from extensions/elasticsearch-rest-client/runtime/src/main/resources/META-INF/quarkus-extension.yaml
rename to extensions/elasticsearch-rest-client-common/runtime/src/main/resources/META-INF/quarkus-extension.yaml
index 3a584f07e4f60..aab0fe0dbc7ce 100644
--- a/extensions/elasticsearch-rest-client/runtime/src/main/resources/META-INF/quarkus-extension.yaml
+++ b/extensions/elasticsearch-rest-client-common/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -1,5 +1,5 @@
---
-name: "Elasticsearch REST Client"
+name: "Elasticsearch REST Client Common"
metadata:
keywords:
- "search"
diff --git a/extensions/elasticsearch-rest-client/deployment/pom.xml b/extensions/elasticsearch-rest-client/deployment/pom.xml
index 08a15f8b5f088..379ab306974f6 100644
--- a/extensions/elasticsearch-rest-client/deployment/pom.xml
+++ b/extensions/elasticsearch-rest-client/deployment/pom.xml
@@ -2,13 +2,13 @@
+ 4.0.0
- quarkus-elasticsearch-rest-client-parentio.quarkus
+ quarkus-elasticsearch-rest-client-parent999-SNAPSHOT
- ../
+ ../pom.xml
- 4.0.0quarkus-elasticsearch-rest-client-deploymentQuarkus - Elasticsearch REST client - Deployment
@@ -18,15 +18,28 @@
io.quarkusquarkus-core-deployment
+
+ io.quarkus
+ quarkus-elasticsearch-rest-client-common-deployment
+ io.quarkusquarkus-elasticsearch-rest-client
+
+ io.quarkus
+ quarkus-arc-deployment
+
+
+ io.quarkus
+ quarkus-smallrye-health-spi
+
+ org.apache.maven.pluginsmaven-compiler-plugin
@@ -40,4 +53,5 @@
+
diff --git a/extensions/elasticsearch-rest-client/deployment/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/deployment/ElasticsearchBuildTimeConfig.java b/extensions/elasticsearch-rest-client/deployment/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/deployment/ElasticsearchBuildTimeConfig.java
new file mode 100644
index 0000000000000..d12b79edc995f
--- /dev/null
+++ b/extensions/elasticsearch-rest-client/deployment/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/deployment/ElasticsearchBuildTimeConfig.java
@@ -0,0 +1,14 @@
+package io.quarkus.elasticsearch.restclient.lowlevel.deployment;
+
+import io.quarkus.runtime.annotations.ConfigItem;
+import io.quarkus.runtime.annotations.ConfigPhase;
+import io.quarkus.runtime.annotations.ConfigRoot;
+
+@ConfigRoot(name = "elasticsearch", phase = ConfigPhase.BUILD_TIME)
+public class ElasticsearchBuildTimeConfig {
+ /**
+ * Whether or not an health check is published in case the smallrye-health extension is present.
+ */
+ @ConfigItem(name = "health.enabled", defaultValue = "true")
+ public boolean healthEnabled;
+}
diff --git a/extensions/elasticsearch-rest-client/deployment/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/deployment/ElasticsearchLowLevelClientProcessor.java b/extensions/elasticsearch-rest-client/deployment/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/deployment/ElasticsearchLowLevelClientProcessor.java
new file mode 100644
index 0000000000000..5aa3aafbf3e38
--- /dev/null
+++ b/extensions/elasticsearch-rest-client/deployment/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/deployment/ElasticsearchLowLevelClientProcessor.java
@@ -0,0 +1,28 @@
+package io.quarkus.elasticsearch.restclient.lowlevel.deployment;
+
+import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
+import io.quarkus.deployment.Feature;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.elasticsearch.restclient.lowlevel.runtime.ElasticsearchRestClientProducer;
+import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem;
+
+class ElasticsearchLowLevelClientProcessor {
+
+ @BuildStep
+ FeatureBuildItem feature() {
+ return new FeatureBuildItem(Feature.ELASTICSEARCH_REST_CLIENT);
+ }
+
+ @BuildStep()
+ AdditionalBeanBuildItem build() {
+ return AdditionalBeanBuildItem.unremovableOf(ElasticsearchRestClientProducer.class);
+ }
+
+ @BuildStep
+ HealthBuildItem addHealthCheck(ElasticsearchBuildTimeConfig buildTimeConfig) {
+ return new HealthBuildItem("io.quarkus.elasticsearch.restclient.lowlevel.runtime.health.ElasticsearchHealthCheck",
+ buildTimeConfig.healthEnabled, "elasticsearch");
+ }
+
+}
diff --git a/extensions/elasticsearch-rest-client/pom.xml b/extensions/elasticsearch-rest-client/pom.xml
index cd0ea6ac1dbc4..41ed2e11676c0 100644
--- a/extensions/elasticsearch-rest-client/pom.xml
+++ b/extensions/elasticsearch-rest-client/pom.xml
@@ -8,11 +8,13 @@
999-SNAPSHOT../../build-parent/pom.xml
+
4.0.0quarkus-elasticsearch-rest-client-parent
- Quarkus - Elasticsearch client
+ Quarkus - Elasticsearch REST client - Parentpom
+
deploymentruntime
diff --git a/extensions/elasticsearch-rest-client/runtime/pom.xml b/extensions/elasticsearch-rest-client/runtime/pom.xml
index a3e347961dc51..e998f4a228d69 100644
--- a/extensions/elasticsearch-rest-client/runtime/pom.xml
+++ b/extensions/elasticsearch-rest-client/runtime/pom.xml
@@ -2,49 +2,35 @@
+ 4.0.0
- quarkus-elasticsearch-rest-client-parentio.quarkus
+ quarkus-elasticsearch-rest-client-parent999-SNAPSHOT
- ../
+ ../pom.xml
- 4.0.0quarkus-elasticsearch-rest-clientQuarkus - Elasticsearch REST client - Runtime
- Elasticsearch REST client
+ Connect to an Elasticsearch cluster using the REST low level client
+
io.quarkusquarkus-core
- org.elasticsearch.client
- elasticsearch-rest-client
-
-
- commons-logging
- commons-logging
-
-
-
-
- org.jboss.logging
- commons-logging-jboss-logging
+ io.quarkus
+ quarkus-elasticsearch-rest-client-common
- org.elasticsearch.client
- elasticsearch-rest-client-sniffer
-
-
- commons-logging
- commons-logging
-
-
+ io.quarkus
+ quarkus-arc
- org.graalvm.nativeimage
- svm
+ io.quarkus
+ quarkus-smallrye-health
+ true
@@ -55,6 +41,7 @@
quarkus-bootstrap-maven-plugin
+ org.apache.maven.pluginsmaven-compiler-plugin
diff --git a/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java
new file mode 100644
index 0000000000000..3edd508c89b65
--- /dev/null
+++ b/extensions/elasticsearch-rest-client/runtime/src/main/java/io/quarkus/elasticsearch/restclient/lowlevel/runtime/ElasticsearchConfig.java
@@ -0,0 +1,99 @@
+package io.quarkus.elasticsearch.restclient.lowlevel.runtime;
+
+import java.net.InetSocketAddress;
+import java.time.Duration;
+import java.util.List;
+import java.util.Optional;
+
+import io.quarkus.runtime.annotations.ConfigGroup;
+import io.quarkus.runtime.annotations.ConfigItem;
+import io.quarkus.runtime.annotations.ConfigPhase;
+import io.quarkus.runtime.annotations.ConfigRoot;
+
+@ConfigRoot(phase = ConfigPhase.RUN_TIME)
+public class ElasticsearchConfig {
+
+ /**
+ * The list of hosts of the Elasticsearch servers.
+ */
+ @ConfigItem(defaultValue = "localhost:9200")
+ public List hosts;
+
+ /**
+ * The protocol to use when contacting Elasticsearch servers.
+ * Set to "https" to enable SSL/TLS.
+ */
+ @ConfigItem(defaultValue = "http")
+ public String protocol;
+
+ /**
+ * The username for basic HTTP authentication.
+ */
+ @ConfigItem
+ public Optional username;
+
+ /**
+ * The password for basic HTTP authentication.
+ */
+ @ConfigItem
+ public Optional password;
+
+ /**
+ * The connection timeout.
+ */
+ @ConfigItem(defaultValue = "1S")
+ public Duration connectionTimeout;
+
+ /**
+ * The socket timeout.
+ */
+ @ConfigItem(defaultValue = "30S")
+ public Duration socketTimeout;
+
+ /**
+ * The maximum number of connections to all the Elasticsearch servers.
+ */
+ @ConfigItem(defaultValue = "20")
+ public int maxConnections;
+
+ /**
+ * The maximum number of connections per Elasticsearch server.
+ */
+ @ConfigItem(defaultValue = "10")
+ public int maxConnectionsPerRoute;
+
+ /**
+ * The number of IO thread.
+ * By default, this is the number of locally detected processors.
+ *
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-client/src/main/resources/application.properties b/integration-tests/elasticsearch-rest-client/src/main/resources/application.properties
new file mode 100644
index 0000000000000..8395e78244c4d
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-client/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+quarkus.elasticsearch.hosts=localhost:9200
+quarkus.elasticsearch.socket-timeout=10S
+quarkus.elasticsearch.discovery.enabled=true
+quarkus.elasticsearch.discovery.refresh-interval=1M
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-client/src/test/java/io/quarkus/it/elasticsearch/FruitResourceTest.java b/integration-tests/elasticsearch-rest-client/src/test/java/io/quarkus/it/elasticsearch/FruitResourceTest.java
new file mode 100644
index 0000000000000..6ebed60a37fa9
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-client/src/test/java/io/quarkus/it/elasticsearch/FruitResourceTest.java
@@ -0,0 +1,69 @@
+package io.quarkus.it.elasticsearch;
+
+import static io.restassured.RestAssured.get;
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.is;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.common.mapper.TypeRef;
+
+@QuarkusTest
+public class FruitResourceTest {
+ private static final TypeRef> LIST_OF_FRUIT_TYPE_REF = new TypeRef>() {
+ };
+
+ @Test
+ public void testEndpoint() throws InterruptedException {
+ // create a Fruit
+ Fruit fruit = new Fruit();
+ fruit.id = "1";
+ fruit.name = "Apple";
+ fruit.color = "Green";
+ given()
+ .contentType("application/json")
+ .body(fruit)
+ .when().post("/fruits")
+ .then()
+ .statusCode(201);
+
+ // get the Fruit
+ Fruit result = get("/fruits/1").as(Fruit.class);
+ Assertions.assertNotNull(result);
+ Assertions.assertEquals("1", result.id);
+ Assertions.assertEquals("Apple", result.name);
+ Assertions.assertEquals("Green", result.color);
+
+ // wait a few ms for the indexing to happened
+ Thread.sleep(1000);
+
+ // search the Fruit
+ List results = get("/fruits/search?color=Green").as(LIST_OF_FRUIT_TYPE_REF);
+ Assertions.assertNotNull(results);
+ Assertions.assertFalse(results.isEmpty());
+ Assertions.assertEquals("1", results.get(0).id);
+ Assertions.assertEquals("Apple", results.get(0).name);
+ Assertions.assertEquals("Green", results.get(0).color);
+ results = get("/fruits/search?name=Apple").as(LIST_OF_FRUIT_TYPE_REF);
+ Assertions.assertNotNull(results);
+ Assertions.assertFalse(results.isEmpty());
+ Assertions.assertEquals("1", results.get(0).id);
+ Assertions.assertEquals("Apple", results.get(0).name);
+ Assertions.assertEquals("Green", results.get(0).color);
+ }
+
+ @Test
+ public void testHealth() {
+ RestAssured.when().get("/health/ready").then()
+ .body("status", is("UP"),
+ "checks.status", containsInAnyOrder("UP"),
+ "checks.name", containsInAnyOrder("Elasticsearch cluster health check"));
+ }
+
+}
diff --git a/integration-tests/elasticsearch-rest-client/src/test/java/io/quarkus/it/elasticsearch/NativeFruitResourceIT.java b/integration-tests/elasticsearch-rest-client/src/test/java/io/quarkus/it/elasticsearch/NativeFruitResourceIT.java
new file mode 100644
index 0000000000000..6d1a5382c051f
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-client/src/test/java/io/quarkus/it/elasticsearch/NativeFruitResourceIT.java
@@ -0,0 +1,9 @@
+package io.quarkus.it.elasticsearch;
+
+import io.quarkus.test.junit.NativeImageTest;
+
+@NativeImageTest
+public class NativeFruitResourceIT extends FruitResourceTest {
+
+ // Execute the same tests but in native mode.
+}
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-client/src/test/resources/elasticsearch-maven-plugin/configuration/elasticsearch.yml b/integration-tests/elasticsearch-rest-client/src/test/resources/elasticsearch-maven-plugin/configuration/elasticsearch.yml
new file mode 100644
index 0000000000000..e15abadf05b9d
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-client/src/test/resources/elasticsearch-maven-plugin/configuration/elasticsearch.yml
@@ -0,0 +1,92 @@
+# ======================== Elasticsearch Configuration =========================
+#
+# NOTE: Elasticsearch comes with reasonable defaults for most settings.
+# Before you set out to tweak and tune the configuration, make sure you
+# understand what are you trying to accomplish and the consequences.
+#
+# The primary way of configuring a node is via this file. This template lists
+# the most important settings you may want to configure for a production cluster.
+#
+# Please consult the documentation for further information on configuration options:
+# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
+#
+# ---------------------------------- Cluster -----------------------------------
+#
+# Use a descriptive name for your cluster:
+#
+#cluster.name: my-application
+#
+# ------------------------------------ Node ------------------------------------
+#
+# Use a descriptive name for the node:
+#
+#node.name: node-1
+#
+# Add custom attributes to the node:
+#
+#node.attr.rack: r1
+#
+# ----------------------------------- Paths ------------------------------------
+#
+# Path to directory where to store the data (separate multiple locations by comma):
+#
+#path.data: /path/to/data
+#
+# Path to log files:
+#
+#path.logs: /path/to/logs
+#
+# ----------------------------------- Memory -----------------------------------
+#
+# Lock the memory on startup:
+#
+bootstrap.memory_lock: true
+#
+# Make sure that the heap size is set to about half the memory available
+# on the system and that the owner of the process is allowed to use this
+# limit.
+#
+# Elasticsearch performs poorly when the system is swapping the memory.
+#
+# ---------------------------------- Network -----------------------------------
+#
+# Set the bind address to a specific IP (IPv4 or IPv6):
+#
+network.host: _local_
+#
+# Set a custom port for HTTP:
+#
+http.port: 9200
+#
+# For more information, consult the network module documentation.
+#
+# --------------------------------- Discovery ----------------------------------
+#
+# Pass an initial list of hosts to perform discovery when this node is started:
+# The default list of hosts is ["127.0.0.1", "[::1]"]
+#
+#discovery.seed_hosts: ["host1", "host2"]
+#
+# Bootstrap the cluster using an initial set of master-eligible nodes:
+#
+#cluster.initial_master_nodes: ["node-1", "node-2"]
+#
+# For more information, consult the discovery and cluster formation module documentation.
+#
+# ---------------------------------- Gateway -----------------------------------
+#
+# Block initial recovery after a full cluster restart until N nodes are started:
+#
+#gateway.recover_after_nodes: 3
+#
+# For more information, consult the gateway module documentation.
+#
+# ---------------------------------- Various -----------------------------------
+#
+# Require explicit names when deleting indices:
+#
+#action.destructive_requires_name: true
+#
+# Disable starting multiple nodes on a single system:
+#
+node.max_local_storage_nodes: 1
diff --git a/integration-tests/elasticsearch-rest-client/src/test/resources/elasticsearch-maven-plugin/configuration/jvm.options b/integration-tests/elasticsearch-rest-client/src/test/resources/elasticsearch-maven-plugin/configuration/jvm.options
new file mode 100644
index 0000000000000..91f3f0ee7dd56
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-client/src/test/resources/elasticsearch-maven-plugin/configuration/jvm.options
@@ -0,0 +1,125 @@
+## JVM configuration
+
+################################################################
+## IMPORTANT: JVM heap size
+################################################################
+##
+## You should always set the min and max JVM heap
+## size to the same value. For example, to set
+## the heap to 4 GB, set:
+##
+## -Xms4g
+## -Xmx4g
+##
+## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
+## for more information
+##
+################################################################
+
+# Xms represents the initial size of total heap space
+# Xmx represents the maximum size of total heap space
+
+# For Hibernate Search, we don't need as much as the default 2g
+# Let's keep it low, so that we'll be able to run tests
+# on memory-constrained CI slaves
+-Xms256m
+-Xmx256m
+
+################################################################
+## Expert settings
+################################################################
+##
+## All settings below this section are considered
+## expert settings. Don't tamper with them unless
+## you understand what you are doing
+##
+################################################################
+
+## GC configuration
+-XX:+UseConcMarkSweepGC
+-XX:CMSInitiatingOccupancyFraction=75
+-XX:+UseCMSInitiatingOccupancyOnly
+
+## G1GC Configuration
+# NOTE: G1GC is only supported on JDK version 10 or later.
+# To use G1GC uncomment the lines below.
+# 10-:-XX:-UseConcMarkSweepGC
+# 10-:-XX:-UseCMSInitiatingOccupancyOnly
+# 10-:-XX:+UseG1GC
+# 10-:-XX:InitiatingHeapOccupancyPercent=75
+
+## DNS cache policy
+# cache ttl in seconds for positive DNS lookups noting that this overrides the
+# JDK security property networkaddress.cache.ttl; set to -1 to cache forever
+-Des.networkaddress.cache.ttl=60
+# cache ttl in seconds for negative DNS lookups noting that this overrides the
+# JDK security property networkaddress.cache.negative ttl; set to -1 to cache
+# forever
+-Des.networkaddress.cache.negative.ttl=10
+
+## optimizations
+
+# pre-touch memory pages used by the JVM during initialization
+-XX:+AlwaysPreTouch
+
+## basic
+
+# explicitly set the stack size
+-Xss1m
+
+# set to headless, just in case
+-Djava.awt.headless=true
+
+# ensure UTF-8 encoding by default (e.g. filenames)
+-Dfile.encoding=UTF-8
+
+# use our provided JNA always versus the system one
+-Djna.nosys=true
+
+# turn off a JDK optimization that throws away stack traces for common
+# exceptions because stack traces are important for debugging
+-XX:-OmitStackTraceInFastThrow
+
+# flags to configure Netty
+-Dio.netty.noUnsafe=true
+-Dio.netty.noKeySetOptimization=true
+-Dio.netty.recycler.maxCapacityPerThread=0
+
+# log4j 2
+-Dlog4j.shutdownHookEnabled=false
+-Dlog4j2.disable.jmx=true
+
+-Djava.io.tmpdir=${ES_TMPDIR}
+
+## heap dumps
+
+# generate a heap dump when an allocation from the Java heap fails
+# heap dumps are created in the working directory of the JVM
+-XX:+HeapDumpOnOutOfMemoryError
+
+# specify an alternative path for heap dumps; ensure the directory exists and
+# has sufficient space
+-XX:HeapDumpPath=data
+
+# specify an alternative path for JVM fatal error logs
+-XX:ErrorFile=logs/hs_err_pid%p.log
+
+## JDK 8 GC logging
+
+8:-XX:+PrintGCDetails
+8:-XX:+PrintGCDateStamps
+8:-XX:+PrintTenuringDistribution
+8:-XX:+PrintGCApplicationStoppedTime
+8:-Xloggc:logs/gc.log
+8:-XX:+UseGCLogFileRotation
+8:-XX:NumberOfGCLogFiles=32
+8:-XX:GCLogFileSize=64m
+
+# JDK 9+ GC logging
+9-:-Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m
+# due to internationalization enhancements in JDK 9 Elasticsearch need to set the provider to COMPAT otherwise
+# time/date parsing will break in an incompatible way for some date patterns and locals
+9-:-Djava.locale.providers=COMPAT
+
+# temporary workaround for C2 bug with JDK 10 on hardware with AVX-512
+10-:-XX:UseAVX=2
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-client/src/test/resources/elasticsearch-maven-plugin/configuration/log4j2.properties b/integration-tests/elasticsearch-rest-client/src/test/resources/elasticsearch-maven-plugin/configuration/log4j2.properties
new file mode 100644
index 0000000000000..e4789c251b25a
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-client/src/test/resources/elasticsearch-maven-plugin/configuration/log4j2.properties
@@ -0,0 +1,36 @@
+status = error
+appenders = console
+loggers = action, metadata, cluster, settings, deprecation, slow_search, slow_indexing
+
+# log action execution errors for easier debugging
+logger.action.name = org.elasticsearch.action
+logger.action.level = info
+
+# do not log metadata too much as we generate a log of noise
+logger.metadata.name = org.elasticsearch.cluster.metadata
+logger.metadata.level = warn
+
+logger.cluster.name = org.elasticsearch.cluster.routing.allocation
+logger.cluster.level = warn
+
+logger.settings.name = org.elasticsearch.common.settings
+logger.settings.level = warn
+
+logger.deprecation.name = org.elasticsearch.deprecation
+logger.deprecation.level = warn
+
+# Warn us about using inefficient Search operations
+logger.slow_search.name = index.search.slowlog
+logger.slow_search.level = trace
+
+# Warn us about using inefficient indexing actions
+logger.slow_indexing.name = index.indexing.slowlog
+logger.slow_indexing.level = trace
+
+appender.console.type = Console
+appender.console.name = console
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d{ABSOLUTE} (%t) %5p %c{1}:%L - %m%n
+
+rootLogger.level = info
+rootLogger.appenderRef.console.ref = console
diff --git a/integration-tests/elasticsearch-rest-high-level-client/.gitignore b/integration-tests/elasticsearch-rest-high-level-client/.gitignore
new file mode 100644
index 0000000000000..087a18358fe57
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/.gitignore
@@ -0,0 +1,35 @@
+# Eclipse
+.project
+.classpath
+.settings/
+bin/
+
+# IntelliJ
+.idea
+*.ipr
+*.iml
+*.iws
+
+# NetBeans
+nb-configuration.xml
+
+# Visual Studio Code
+.vscode
+
+# OSX
+.DS_Store
+
+# Vim
+*.swp
+*.swo
+
+# patch
+*.orig
+*.rej
+
+# Maven
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+release.properties
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-high-level-client/README.md b/integration-tests/elasticsearch-rest-high-level-client/README.md
new file mode 100644
index 0000000000000..43570d93bdc2f
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/README.md
@@ -0,0 +1,30 @@
+# quarkus-integration-test-elasticsearch-rest-high-level-client project
+
+This project uses Quarkus, the Supersonic Subatomic Java Framework.
+
+If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ .
+
+## Running the application in dev mode
+
+You can run your application in dev mode that enables live coding using:
+```
+./mvnw quarkus:dev
+```
+
+## Packaging and running the application
+
+The application can be packaged using `./mvnw package`.
+It produces the `quarkus-integration-test-elasticsearch-rest-high-level-client-1.0-SNAPSHOT-runner.jar` file in the `/target` directory.
+Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/lib` directory.
+
+The application is now runnable using `java -jar target/quarkus-integration-test-elasticsearch-rest-high-level-client-1.0-SNAPSHOT-runner.jar`.
+
+## Creating a native executable
+
+You can create a native executable using: `./mvnw package -Pnative`.
+
+Or, if you don't have GraalVM installed, you can run the native executable build in a container using: `./mvnw package -Pnative -Dquarkus.native.container-build=true`.
+
+You can then execute your native executable with: `./target/quarkus-integration-test-elasticsearch-rest-high-level-client-1.0-SNAPSHOT-runner`
+
+If you want to learn more about building native executables, please consult https://quarkus.io/guides/building-native-image-guide.
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-high-level-client/pom.xml b/integration-tests/elasticsearch-rest-high-level-client/pom.xml
new file mode 100644
index 0000000000000..20f4b06c6f9ba
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/pom.xml
@@ -0,0 +1,157 @@
+
+
+
+ quarkus-integration-tests-parent
+ io.quarkus
+ 999-SNAPSHOT
+ ../
+
+
+ 4.0.0
+
+ quarkus-integration-test-elasticsearch-rest-high-level-client
+ Quarkus - Integration Tests - Elasticsearch REST high level client
+
+
+
+
+ io.quarkus
+ quarkus-resteasy-jackson
+
+
+ io.quarkus
+ quarkus-elasticsearch-rest-high-level-client
+
+
+ io.quarkus
+ quarkus-smallrye-health
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+ ${project.version}
+
+
+
+ build
+
+
+
+
+
+ maven-surefire-plugin
+
+ true
+
+
+
+ maven-failsafe-plugin
+
+ true
+
+
+
+
+
+
+
+ test-elasticsearch
+
+
+ test-elasticsearch
+
+
+
+
+
+ maven-surefire-plugin
+
+ false
+
+
+
+ maven-failsafe-plugin
+
+ false
+
+
+
+ com.github.alexcojocaru
+ elasticsearch-maven-plugin
+
+ 90
+ ${project.build.directory}/test-classes/elasticsearch-maven-plugin/configuration/
+ true
+
+
+
+
+ start-elasticsearch
+ process-test-classes
+
+ runforked
+
+
+
+ stop-elasticsearch
+ post-integration-test
+
+ stop
+
+
+
+
+
+
+
+
+ native
+
+
+ native
+
+
+
+
+
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+
+
+
+
+
+
+
+
+ native
+
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-high-level-client/src/main/java/io/quarkus/it/elasticsearch/highlevel/Fruit.java b/integration-tests/elasticsearch-rest-high-level-client/src/main/java/io/quarkus/it/elasticsearch/highlevel/Fruit.java
new file mode 100644
index 0000000000000..07c6e2d45ae96
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/src/main/java/io/quarkus/it/elasticsearch/highlevel/Fruit.java
@@ -0,0 +1,7 @@
+package io.quarkus.it.elasticsearch.highlevel;
+
+public class Fruit {
+ public String id;
+ public String name;
+ public String color;
+}
diff --git a/integration-tests/elasticsearch-rest-high-level-client/src/main/java/io/quarkus/it/elasticsearch/highlevel/FruitResource.java b/integration-tests/elasticsearch-rest-high-level-client/src/main/java/io/quarkus/it/elasticsearch/highlevel/FruitResource.java
new file mode 100644
index 0000000000000..47e8663da7a69
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/src/main/java/io/quarkus/it/elasticsearch/highlevel/FruitResource.java
@@ -0,0 +1,54 @@
+package io.quarkus.it.elasticsearch.highlevel;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("/fruits")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class FruitResource {
+ @Inject
+ FruitService fruitService;
+
+ @POST
+ public Response index(Fruit fruit) throws IOException {
+ if (fruit.id == null) {
+ fruit.id = UUID.randomUUID().toString();
+ }
+ fruitService.index(fruit);
+ return Response.created(URI.create("/fruits/" + fruit.id)).build();
+ }
+
+ @GET
+ @Path("/{id}")
+ public Fruit get(@PathParam("id") String id) throws IOException {
+ return fruitService.get(id);
+ }
+
+ @GET
+ @Path("/search")
+ public List search(@QueryParam("name") String name, @QueryParam("color") String color) throws IOException {
+ if (name != null) {
+ return fruitService.searchByName(name);
+ } else if (color != null) {
+ return fruitService.searchByColor(color);
+ } else {
+ throw new BadRequestException("Should provide name or color query parameter");
+ }
+ }
+
+}
diff --git a/integration-tests/elasticsearch-rest-high-level-client/src/main/java/io/quarkus/it/elasticsearch/highlevel/FruitService.java b/integration-tests/elasticsearch-rest-high-level-client/src/main/java/io/quarkus/it/elasticsearch/highlevel/FruitService.java
new file mode 100644
index 0000000000000..bb1c7c2566fcb
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/src/main/java/io/quarkus/it/elasticsearch/highlevel/FruitService.java
@@ -0,0 +1,72 @@
+package io.quarkus.it.elasticsearch.highlevel;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.elasticsearch.action.get.GetRequest;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+
+import io.vertx.core.json.JsonObject;
+
+@ApplicationScoped
+public class FruitService {
+ @Inject
+ RestHighLevelClient restHighLevelClient;
+
+ public void index(Fruit fruit) throws IOException {
+ IndexRequest request = new IndexRequest("fruits");
+ request.id(fruit.id);
+ request.source(JsonObject.mapFrom(fruit).toString(), XContentType.JSON);
+ restHighLevelClient.index(request, RequestOptions.DEFAULT);
+ }
+
+ public Fruit get(String id) throws IOException {
+ GetRequest getRequest = new GetRequest("fruits", id);
+ GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
+ if (getResponse.isExists()) {
+ String sourceAsString = getResponse.getSourceAsString();
+ JsonObject json = new JsonObject(sourceAsString);
+ return json.mapTo(Fruit.class);
+ }
+ return null;
+ }
+
+ public List searchByColor(String color) throws IOException {
+ return search("color", color);
+ }
+
+ public List searchByName(String name) throws IOException {
+ return search("name", name);
+ }
+
+ private List search(String term, String match) throws IOException {
+ SearchRequest searchRequest = new SearchRequest("fruits");
+ SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+ searchSourceBuilder.query(QueryBuilders.matchQuery(term, match));
+ searchRequest.source(searchSourceBuilder);
+
+ SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+ SearchHits hits = searchResponse.getHits();
+ List results = new ArrayList<>(hits.getHits().length);
+ for (SearchHit hit : hits.getHits()) {
+ String sourceAsString = hit.getSourceAsString();
+ JsonObject json = new JsonObject(sourceAsString);
+ results.add(json.mapTo(Fruit.class));
+ }
+ return results;
+ }
+}
diff --git a/integration-tests/elasticsearch-rest-high-level-client/src/main/resources/META-INF/resources/fruits.html b/integration-tests/elasticsearch-rest-high-level-client/src/main/resources/META-INF/resources/fruits.html
new file mode 100644
index 0000000000000..a2144d6a57be8
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/src/main/resources/META-INF/resources/fruits.html
@@ -0,0 +1,120 @@
+
+
+
+
+ Fruit REST service
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-high-level-client/src/test/java/io/quarkus/it/elasticsearch/FruitResourceTest.java b/integration-tests/elasticsearch-rest-high-level-client/src/test/java/io/quarkus/it/elasticsearch/FruitResourceTest.java
new file mode 100644
index 0000000000000..f6a077535d747
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/src/test/java/io/quarkus/it/elasticsearch/FruitResourceTest.java
@@ -0,0 +1,70 @@
+package io.quarkus.it.elasticsearch;
+
+import static io.restassured.RestAssured.get;
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.is;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.it.elasticsearch.highlevel.Fruit;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.common.mapper.TypeRef;
+
+@QuarkusTest
+public class FruitResourceTest {
+ private static final TypeRef> LIST_OF_FRUIT_TYPE_REF = new TypeRef>() {
+ };
+
+ @Test
+ public void testEndpoint() throws InterruptedException {
+ // create a Fruit
+ Fruit fruit = new Fruit();
+ fruit.id = "1";
+ fruit.name = "Apple";
+ fruit.color = "Green";
+ given()
+ .contentType("application/json")
+ .body(fruit)
+ .when().post("/fruits")
+ .then()
+ .statusCode(201);
+
+ // get the Fruit
+ Fruit result = get("/fruits/1").as(Fruit.class);
+ Assertions.assertNotNull(result);
+ Assertions.assertEquals("1", result.id);
+ Assertions.assertEquals("Apple", result.name);
+ Assertions.assertEquals("Green", result.color);
+
+ // wait a few ms for the indexing to happened
+ Thread.sleep(1000);
+
+ // search the Fruit
+ List results = get("/fruits/search?color=Green").as(LIST_OF_FRUIT_TYPE_REF);
+ Assertions.assertNotNull(results);
+ Assertions.assertFalse(results.isEmpty());
+ Assertions.assertEquals("1", results.get(0).id);
+ Assertions.assertEquals("Apple", results.get(0).name);
+ Assertions.assertEquals("Green", results.get(0).color);
+ results = get("/fruits/search?name=Apple").as(LIST_OF_FRUIT_TYPE_REF);
+ Assertions.assertNotNull(results);
+ Assertions.assertFalse(results.isEmpty());
+ Assertions.assertEquals("1", results.get(0).id);
+ Assertions.assertEquals("Apple", results.get(0).name);
+ Assertions.assertEquals("Green", results.get(0).color);
+ }
+
+ @Test
+ public void testHealth() {
+ RestAssured.when().get("/health/ready").then()
+ .body("status", is("UP"),
+ "checks.status", containsInAnyOrder("UP"),
+ "checks.name", containsInAnyOrder("Elasticsearch cluster health check"));
+ }
+
+}
diff --git a/integration-tests/elasticsearch-rest-high-level-client/src/test/java/io/quarkus/it/elasticsearch/NativeFruitResourceIT.java b/integration-tests/elasticsearch-rest-high-level-client/src/test/java/io/quarkus/it/elasticsearch/NativeFruitResourceIT.java
new file mode 100644
index 0000000000000..6d1a5382c051f
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/src/test/java/io/quarkus/it/elasticsearch/NativeFruitResourceIT.java
@@ -0,0 +1,9 @@
+package io.quarkus.it.elasticsearch;
+
+import io.quarkus.test.junit.NativeImageTest;
+
+@NativeImageTest
+public class NativeFruitResourceIT extends FruitResourceTest {
+
+ // Execute the same tests but in native mode.
+}
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-high-level-client/src/test/resources/elasticsearch-maven-plugin/configuration/elasticsearch.yml b/integration-tests/elasticsearch-rest-high-level-client/src/test/resources/elasticsearch-maven-plugin/configuration/elasticsearch.yml
new file mode 100644
index 0000000000000..e15abadf05b9d
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/src/test/resources/elasticsearch-maven-plugin/configuration/elasticsearch.yml
@@ -0,0 +1,92 @@
+# ======================== Elasticsearch Configuration =========================
+#
+# NOTE: Elasticsearch comes with reasonable defaults for most settings.
+# Before you set out to tweak and tune the configuration, make sure you
+# understand what are you trying to accomplish and the consequences.
+#
+# The primary way of configuring a node is via this file. This template lists
+# the most important settings you may want to configure for a production cluster.
+#
+# Please consult the documentation for further information on configuration options:
+# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
+#
+# ---------------------------------- Cluster -----------------------------------
+#
+# Use a descriptive name for your cluster:
+#
+#cluster.name: my-application
+#
+# ------------------------------------ Node ------------------------------------
+#
+# Use a descriptive name for the node:
+#
+#node.name: node-1
+#
+# Add custom attributes to the node:
+#
+#node.attr.rack: r1
+#
+# ----------------------------------- Paths ------------------------------------
+#
+# Path to directory where to store the data (separate multiple locations by comma):
+#
+#path.data: /path/to/data
+#
+# Path to log files:
+#
+#path.logs: /path/to/logs
+#
+# ----------------------------------- Memory -----------------------------------
+#
+# Lock the memory on startup:
+#
+bootstrap.memory_lock: true
+#
+# Make sure that the heap size is set to about half the memory available
+# on the system and that the owner of the process is allowed to use this
+# limit.
+#
+# Elasticsearch performs poorly when the system is swapping the memory.
+#
+# ---------------------------------- Network -----------------------------------
+#
+# Set the bind address to a specific IP (IPv4 or IPv6):
+#
+network.host: _local_
+#
+# Set a custom port for HTTP:
+#
+http.port: 9200
+#
+# For more information, consult the network module documentation.
+#
+# --------------------------------- Discovery ----------------------------------
+#
+# Pass an initial list of hosts to perform discovery when this node is started:
+# The default list of hosts is ["127.0.0.1", "[::1]"]
+#
+#discovery.seed_hosts: ["host1", "host2"]
+#
+# Bootstrap the cluster using an initial set of master-eligible nodes:
+#
+#cluster.initial_master_nodes: ["node-1", "node-2"]
+#
+# For more information, consult the discovery and cluster formation module documentation.
+#
+# ---------------------------------- Gateway -----------------------------------
+#
+# Block initial recovery after a full cluster restart until N nodes are started:
+#
+#gateway.recover_after_nodes: 3
+#
+# For more information, consult the gateway module documentation.
+#
+# ---------------------------------- Various -----------------------------------
+#
+# Require explicit names when deleting indices:
+#
+#action.destructive_requires_name: true
+#
+# Disable starting multiple nodes on a single system:
+#
+node.max_local_storage_nodes: 1
diff --git a/integration-tests/elasticsearch-rest-high-level-client/src/test/resources/elasticsearch-maven-plugin/configuration/jvm.options b/integration-tests/elasticsearch-rest-high-level-client/src/test/resources/elasticsearch-maven-plugin/configuration/jvm.options
new file mode 100644
index 0000000000000..91f3f0ee7dd56
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/src/test/resources/elasticsearch-maven-plugin/configuration/jvm.options
@@ -0,0 +1,125 @@
+## JVM configuration
+
+################################################################
+## IMPORTANT: JVM heap size
+################################################################
+##
+## You should always set the min and max JVM heap
+## size to the same value. For example, to set
+## the heap to 4 GB, set:
+##
+## -Xms4g
+## -Xmx4g
+##
+## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
+## for more information
+##
+################################################################
+
+# Xms represents the initial size of total heap space
+# Xmx represents the maximum size of total heap space
+
+# For Hibernate Search, we don't need as much as the default 2g
+# Let's keep it low, so that we'll be able to run tests
+# on memory-constrained CI slaves
+-Xms256m
+-Xmx256m
+
+################################################################
+## Expert settings
+################################################################
+##
+## All settings below this section are considered
+## expert settings. Don't tamper with them unless
+## you understand what you are doing
+##
+################################################################
+
+## GC configuration
+-XX:+UseConcMarkSweepGC
+-XX:CMSInitiatingOccupancyFraction=75
+-XX:+UseCMSInitiatingOccupancyOnly
+
+## G1GC Configuration
+# NOTE: G1GC is only supported on JDK version 10 or later.
+# To use G1GC uncomment the lines below.
+# 10-:-XX:-UseConcMarkSweepGC
+# 10-:-XX:-UseCMSInitiatingOccupancyOnly
+# 10-:-XX:+UseG1GC
+# 10-:-XX:InitiatingHeapOccupancyPercent=75
+
+## DNS cache policy
+# cache ttl in seconds for positive DNS lookups noting that this overrides the
+# JDK security property networkaddress.cache.ttl; set to -1 to cache forever
+-Des.networkaddress.cache.ttl=60
+# cache ttl in seconds for negative DNS lookups noting that this overrides the
+# JDK security property networkaddress.cache.negative ttl; set to -1 to cache
+# forever
+-Des.networkaddress.cache.negative.ttl=10
+
+## optimizations
+
+# pre-touch memory pages used by the JVM during initialization
+-XX:+AlwaysPreTouch
+
+## basic
+
+# explicitly set the stack size
+-Xss1m
+
+# set to headless, just in case
+-Djava.awt.headless=true
+
+# ensure UTF-8 encoding by default (e.g. filenames)
+-Dfile.encoding=UTF-8
+
+# use our provided JNA always versus the system one
+-Djna.nosys=true
+
+# turn off a JDK optimization that throws away stack traces for common
+# exceptions because stack traces are important for debugging
+-XX:-OmitStackTraceInFastThrow
+
+# flags to configure Netty
+-Dio.netty.noUnsafe=true
+-Dio.netty.noKeySetOptimization=true
+-Dio.netty.recycler.maxCapacityPerThread=0
+
+# log4j 2
+-Dlog4j.shutdownHookEnabled=false
+-Dlog4j2.disable.jmx=true
+
+-Djava.io.tmpdir=${ES_TMPDIR}
+
+## heap dumps
+
+# generate a heap dump when an allocation from the Java heap fails
+# heap dumps are created in the working directory of the JVM
+-XX:+HeapDumpOnOutOfMemoryError
+
+# specify an alternative path for heap dumps; ensure the directory exists and
+# has sufficient space
+-XX:HeapDumpPath=data
+
+# specify an alternative path for JVM fatal error logs
+-XX:ErrorFile=logs/hs_err_pid%p.log
+
+## JDK 8 GC logging
+
+8:-XX:+PrintGCDetails
+8:-XX:+PrintGCDateStamps
+8:-XX:+PrintTenuringDistribution
+8:-XX:+PrintGCApplicationStoppedTime
+8:-Xloggc:logs/gc.log
+8:-XX:+UseGCLogFileRotation
+8:-XX:NumberOfGCLogFiles=32
+8:-XX:GCLogFileSize=64m
+
+# JDK 9+ GC logging
+9-:-Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m
+# due to internationalization enhancements in JDK 9 Elasticsearch need to set the provider to COMPAT otherwise
+# time/date parsing will break in an incompatible way for some date patterns and locals
+9-:-Djava.locale.providers=COMPAT
+
+# temporary workaround for C2 bug with JDK 10 on hardware with AVX-512
+10-:-XX:UseAVX=2
\ No newline at end of file
diff --git a/integration-tests/elasticsearch-rest-high-level-client/src/test/resources/elasticsearch-maven-plugin/configuration/log4j2.properties b/integration-tests/elasticsearch-rest-high-level-client/src/test/resources/elasticsearch-maven-plugin/configuration/log4j2.properties
new file mode 100644
index 0000000000000..e4789c251b25a
--- /dev/null
+++ b/integration-tests/elasticsearch-rest-high-level-client/src/test/resources/elasticsearch-maven-plugin/configuration/log4j2.properties
@@ -0,0 +1,36 @@
+status = error
+appenders = console
+loggers = action, metadata, cluster, settings, deprecation, slow_search, slow_indexing
+
+# log action execution errors for easier debugging
+logger.action.name = org.elasticsearch.action
+logger.action.level = info
+
+# do not log metadata too much as we generate a log of noise
+logger.metadata.name = org.elasticsearch.cluster.metadata
+logger.metadata.level = warn
+
+logger.cluster.name = org.elasticsearch.cluster.routing.allocation
+logger.cluster.level = warn
+
+logger.settings.name = org.elasticsearch.common.settings
+logger.settings.level = warn
+
+logger.deprecation.name = org.elasticsearch.deprecation
+logger.deprecation.level = warn
+
+# Warn us about using inefficient Search operations
+logger.slow_search.name = index.search.slowlog
+logger.slow_search.level = trace
+
+# Warn us about using inefficient indexing actions
+logger.slow_indexing.name = index.indexing.slowlog
+logger.slow_indexing.level = trace
+
+appender.console.type = Console
+appender.console.name = console
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d{ABSOLUTE} (%t) %5p %c{1}:%L - %m%n
+
+rootLogger.level = info
+rootLogger.appenderRef.console.ref = console
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 1536f724933fa..c6146c8e36e42 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -127,6 +127,8 @@
webjars-locatordevmodeide-launcher
+ elasticsearch-rest-client
+ elasticsearch-rest-high-level-clientgrpc-plain-text