{"id":64718,"date":"2017-03-29T13:00:14","date_gmt":"2017-03-29T10:00:14","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=64718"},"modified":"2023-12-11T10:17:23","modified_gmt":"2023-12-11T08:17:23","slug":"elasticsearch-java-developers-elasticsearch-java","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html","title":{"rendered":"Elasticsearch for Java Developers: Elasticsearch from Java"},"content":{"rendered":"<p><em>This article is part of our Academy Course titled <a href=\"https:\/\/www.javacodegeeks.com\/2017\/04\/elasticsearch-tutorial-java-developers.html\">Elasticsearch Tutorial for Java Developers<\/a>.<\/p>\n<p>In this course, we provide a series of tutorials so that you can develop your own Elasticsearch based applications. We cover a wide range of topics, from installation and operations, to Java API Integration and reporting. With our straightforward tutorials, you will be able to get your own projects up and running in minimum time. Check it out <a href=\"https:\/\/www.javacodegeeks.com\/2017\/04\/elasticsearch-tutorial-java-developers.html\">here<\/a>!<\/em><\/p>\n<h2><a name=\"introduction\"><\/a>1. Introduction<\/h2>\n<p>In the <a href=\"https:\/\/www.javacodegeeks.com\/2017\/02\/elasticsearch-java-developers-elasticsearch-command-line.html\">previous part of the tutorial<\/a> we mastered the skills of establishing meaningful conversations with <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> by leveraging its numerous <a href=\"https:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">RESTful APIs<\/a>, using the command line tools only. It is very handful knowledge, however when you are developing Java \/ JVM applications, you would need better options than command line. Luckily, <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> has more than one offering in this area.<\/p>\n<div class=\"toc\">\n<h3>Table Of Contents<\/h3>\n<dl>\n<dt><a href=\"#introduction\">1. Introduction<\/a><\/dt>\n<dt><a href=\"#client\">2. Using Java Client API<\/a><\/dt>\n<dt><a href=\"#rest\">3. Using Java Rest Client<\/a><\/dt>\n<dt><a href=\"#testing\">4. Using Testing Kit<\/a><\/dt>\n<dt><a href=\"#conclusions\">5. Conclusions<\/a><\/dt>\n<dt><a href=\"#next\">6. What\u2019s next<\/a><\/dt>\n<\/dl>\n<\/div>\n<p>Along this part of the tutorial we are going learn how to talk to <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> by means of native Java APIs. Our approach to that would be to code and to work on a couple of Java applications, using <a href=\"https:\/\/maven.apache.org\/\">Apache Maven<\/a> for build management, terrific <a href=\"https:\/\/projects.spring.io\/spring-framework\/\">Spring Framework<\/a> for dependency wiring and <a href=\"https:\/\/en.wikipedia.org\/wiki\/Inversion_of_control\">inversion of control<\/a>, and awesome <a href=\"http:\/\/junit.org\/junit4\/\">JUnit<\/a> \/ <a href=\"http:\/\/joel-costigliola.github.io\/assertj\/\">AssertJ<\/a> as test scaffolding.<\/p>\n<h2><a name=\"client\"><\/a>2. Using Java Client API<\/h2>\n<p>Since the early versions, <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> distributes a dedicated <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/index.html\">Java client API<\/a> with each release, also known as transport client. It talks <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> native transport protocol and as such, imposes the constraint that the version of the client library should at least match the major version of <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> distribution you are using (ideally, the client should have exactly the same version).<\/p>\n<p>As we are \u00adusing <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> version <code>5.2.0<\/code>, it would make sense to add the respective client version dependency to our <code>pom.xml<\/code> file.<\/p>\n<pre class=\"brush:xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.elasticsearch.client&lt;\/groupId&gt;\n    &lt;artifactId&gt;transport&lt;\/artifactId&gt;\n    &lt;version&gt;5.2.0&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>Since we have chosen <a href=\"https:\/\/projects.spring.io\/spring-framework\/\">Spring Framework<\/a> to power our application, literally the only thing we need is a transport client configuration.<\/p>\n<pre class=\"brush:java\">@Configuration\npublic class ElasticsearchClientConfiguration {\n    @Bean(destroyMethod = \"close\")\n    TransportClient transportClient() throws UnknownHostException  {\n        return new PreBuiltTransportClient(\n            Settings.builder()-\n                .put(ClusterName.CLUSTER_NAME_SETTING.getKey(), \"es-catalog\")\n                .build()\n            )\n            .addTransportAddress(new InetSocketTransportAddress(\n                InetAddress.getByName(\"localhost\"), 9300));\n    }\n}\n<\/pre>\n<p>The <code>PreBuiltTransportClient<\/code> follows the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Builder_pattern\">builder pattern<\/a> (as most of the classes as we are going to see soon) to construct <code>TransportClient<\/code> instance, and once it is there, we could use the injection techniques supported by <a href=\"https:\/\/projects.spring.io\/spring-framework\/\">Spring Framework<\/a> to access it:<\/p>\n<pre class=\"brush:java\">@Autowired private TransportClient client;\n<\/pre>\n<p>The <code>CLUSTER_NAME_SETTING<\/code> is worth of our attention: it should match exactly the name of the <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> cluster we are connecting to, which in our case is <code>es-catalog<\/code>.<\/p>\n<p>Great, we have our transport client initialized, so what can we do with it? Essentially, the transport client exposes a whole bunch of methods (following the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Fluent_interface\">fluent interface<\/a> style) to open the access to all <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> APIs from the Java code. To get one step ahead, it should be noted that transport client has explicit separation between regular APIs and admin APIs. The latter is available by invoking <code>admin()<\/code> method on the transport client instance.<\/p>\n<p>Before rolling the sleeves and getting our hands dirty, it is necessary to mention that <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> Java APIs are designed to be fully asynchronous and as such, are centered around two key abstractions:\u00a0 <code>ActionFuture&lt;?&gt;<\/code> and <code>ListenableActionFuture&lt;?&gt;<\/code>. In fact, <code>ActionFuture&lt;?&gt;<\/code> is just a plain old Java <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/util\/concurrent\/Future.html\">Future&lt;?&gt;<\/a>\u00a0with a couple of handful methods added, stay tuned on that. From the other side, <code>ListenableActionFuture&lt;?&gt;<\/code> is more powerful abstraction with the ability to take the callbacks and notify the caller about the result of the execution.<\/p>\n<p>Picking one style over the other is totally dictated by the needs of your applications, as both of them do have own pros and cons. Without further ado, let us go ahead and make sure our <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> cluster is healthy and is ready to rock.<\/p>\n<pre class=\"brush:java\">final ClusterHealthResponse response = client\n    .admin()\n    .cluster()\n    .health(\n        Requests\n            .clusterHealthRequest()\n            .waitForGreenStatus()\n            .timeout(TimeValue.timeValueSeconds(5))\n    )\n    .actionGet();\n\nassertThat(response.isTimedOut())\n    .withFailMessage(\"The cluster is unhealthy: %s\", response.getStatus())\n    .isFalse();\n\n<\/pre>\n<p>The example is pretty simple and straightforward. What we do is inquiring <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> cluster about its status while explicitly asking to wait at most <code>5 seconds<\/code> for the status to become <code>green<\/code> (if it is not the case yet). Under the hood, <code>client.admin().cluster().health(...)<\/code> returns <code>ActionFuture&lt;?&gt;<\/code> so we have to call one of the <code>actionGet<\/code> methods to get the response.<\/p>\n<p>Here is another, slightly different way to use <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> Java API, this time employing the <code>prepareXxx<\/code> methods family.<\/p>\n<pre class=\"brush:java\">final ClusterHealthResponse response = client\n    .admin()\n    .cluster()\n    .prepareHealth()\n    .setWaitForGreenStatus()\n    .setTimeout(TimeValue.timeValueSeconds(5))\n    .execute()\n    .actionGet();\n\nassertThat(response.isTimedOut())\n    .withFailMessage(\"The cluster is unhealthy: %s\", response.getStatus())\n    .isFalse();\n<\/pre>\n<p>Although both code snippets lead to absolutely identical results, the latter one is calling <code>client.admin().cluster().prepareHealth().execute()<\/code> method at the end of the chain, which returns <code>ListenableActionFuture&lt;?&gt;<\/code>. It does not make a lot of difference in this example but please keep it in mind as we are going to see more interesting use cases where such a detail becomes really a game changer.<\/p>\n<p>And finally, last but not least, the asynchronous nature of any API (and <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> Java API is not an exception) assumes that invocation of the operation will take some time and it becomes the responsibility of the caller to decide how to deal with that. What we have used so far is just calling <code>actionGet<\/code> on the instance of <code>ActionFuture&lt;?&gt;<\/code>, which effectively transforms the asynchronous execution into a blocking (or, to say it the other way, synchronous) call. Moreover, we did not specify the expectations in terms of how long we would agree to wait for the execution to be completed before giving up. We could do better than that and in the rest of this section we are going to address both of these points.<\/p>\n<p>Once we have our <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> cluster status all <code>green<\/code>, it is time to create some indices, much like we have done in the previous part of the tutorial but this time using Java APIs only. It would be good idea to ensure that <code>catalog<\/code> index does not exist yet before creating one.<\/p>\n<pre class=\"brush:java\">final IndicesExistsResponse response = client\n    .admin()\n    .indices()\n    .prepareExists(\"catalog\")\n    .get(TimeValue.timeValueMillis(100));\n\t\t\nif (!response.isExists()) {\n    ...\n}\n<\/pre>\n<p>Please notice that in the snippet above we provided the explicit timeout for the operation to complete, <code>get(TimeValue.timeValueMillis(100))<\/code>, which is essentially the shortcut to <code>execute().actionGet(TimeValue.timeValueMillis(100))<\/code>.<\/p>\n<p>For the <code>catalog<\/code> index settings and mapping types we are going to use exactly the same <a href=\"http:\/\/www.json.org\/\">JSON<\/a> file, <code>catalog-index.json<\/code>, which we had been using in the previous part of the tutorial. We are going to place it into <code>src\/test\/resources<\/code> folder, following <a href=\"https:\/\/maven.apache.org\/\">Apache Maven<\/a> conventions.<\/p>\n<pre class=\"brush:java\">@Value(\"classpath:catalog-index.json\") \nprivate Resource index;\n<\/pre>\n<p>Fortunately <a href=\"https:\/\/projects.spring.io\/spring-framework\/\">Spring Framework<\/a> simplifies a lot the injection of the classpath resources so not much we need to do here to gain the access to <code>catalog-index.json<\/code> content and feed it directly to <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> Java API.<\/p>\n<pre class=\"brush:java\">try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) {\n    Streams.copy(index.getInputStream(), out);\n\t\t\t\n    final CreateIndexResponse response = client\n        .admin()\n        .indices()\n        .prepareCreate(\"catalog\")\n        .setSource(out.toByteArray())\n        .setTimeout(TimeValue.timeValueSeconds(1))\n        .get(TimeValue.timeValueSeconds(2));\n\t\n    assertThat(response.isAcknowledged())\n        .withFailMessage(\"The index creation has not been acknowledged\")\n        .isTrue();\t\t\n}\n<\/pre>\n<p>This code block illustrates yet another way to approach the <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> Java APIs by utilizing the <code>setSource<\/code> method call. In a nutshell, we just supply the request payload ourselves in a form of opaque blob (or string) and it is going to be sent to <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> node(s) as is. However, we could have used a pure Java data structures instead, for example:<\/p>\n<pre class=\"brush:java\">final CreateIndexResponse response = client\n    .admin()\n    .indices()\n    .prepareCreate(\"catalog\")\n    .setSettings(...)\n    .setMapping(\"books\", ...)\n    .setMapping(\"authors\", ...)\n    .setTimeout(TimeValue.timeValueSeconds(1))\n    .get(TimeValue.timeValueSeconds(2));\n<\/pre>\n<p>Good, with that we are going to conclude the transport client admin APIs and switch over to document and search APIs, as those would be the ones you would use most of the time.\u00a0As we remember, <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a>\u00a0 speaks <a href=\"http:\/\/www.json.org\/\">JSON<\/a> so we have to somehow convert books and authors to <a href=\"http:\/\/www.json.org\/\">JSON<\/a> representation using Java. In fact, <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> Java API helps with that by supporting the generic abstraction over the content named <code>XContent<\/code>, for example:<\/p>\n<pre class=\"brush:java\">final XContentBuilder source = JsonXContent\n    .contentBuilder()\n    .startObject()\n    .field(\"title\", \"Elasticsearch: The Definitive Guide. ...\")\n    .startArray(\"categories\")\n        .startObject().field(\"name\", \"analytics\").endObject()\n        .startObject().field(\"name\", \"search\").endObject()\n        .startObject().field(\"name\", \"database store\").endObject()\n    .endArray()\n    .field(\"publisher\", \"O'Reilly\")\n    .field(\"description\", \"Whether you need full-text search or ...\")\n    .field(\"published_date\", new LocalDate(2015, 02, 07).toDate())\n    .field(\"isbn\", \"978-1449358549\")\n    .field(\"rating\", 4)\n    .endObject();\n<\/pre>\n<p>Having the document representation, we could send it over to <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> for indexing. To keep the promises, this time we would like to go truly asynchronous way and do not wait for the response, providing the notification callback in a shape of <code>ActionListener&lt;IndexResponse&gt;<\/code> instead.<\/p>\n<pre class=\"brush:java\">client\n    .prepareIndex(\"catalog\", \"books\")\n    .setId(\"978-1449358549\")\n    .setContentType(XContentType.JSON)\n    .setSource(source)\n    .setOpType(OpType.INDEX)\n    .setRefreshPolicy(RefreshPolicy.WAIT_UNTIL)\n    .setTimeout(TimeValue.timeValueMillis(100))\n    .execute(new ActionListener() {\n        @Override\n\t  public void onResponse(IndexResponse response) {\n\t      LOG.info(\"The document has been indexed with the result: {}\", \n\t\t    response.getResult());\n        }\n\t\t\t\t\n        @Override\n        public void onFailure(Exception ex) {\n            LOG.error(\"The document has been not been indexed\", ex);\n        }\n    });\n<\/pre>\n<p>Nice, so we have our first document in the <code>books<\/code> collection! What about <code>authors<\/code> though? Well, just as reminder, the book in question has more than one author so it is a perfect occasion to use document bulk indexing.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:java\">final XContentBuilder clintonGormley = JsonXContent\n    .contentBuilder()\n    .startObject()\n    .field(\"first_name\", \"Clinton\")\n    .field(\"last_name\", \"Gormley\")\n    .endObject();\n\t\t\nfinal XContentBuilder zacharyTong = JsonXContent\n    .contentBuilder()\n    .startObject()\n    .field(\"first_name\", \"Zachary\")\n    .field(\"last_name\", \"Tong\")\n    .endObject();\n<\/pre>\n<p>The <code>XContent<\/code> part is clear enough and frankly, you may never use such an option, preferring to model real classes and use one of the terrific Java libraries for automatic to \/ from <a href=\"http:\/\/www.json.org\/\">JSON<\/a> conversions. But the following snippet is really interesting.<\/p>\n<pre class=\"brush:java\">final BulkResponse response = client\n    .prepareBulk()\n    .add(\n        Requests\n            .indexRequest(\"catalog\")\n            .type(\"authors\")\n            .id(\"1\")\n            .source(clintonGormley)\n            .parent(\"978-1449358549\")\n            .opType(OpType.INDEX)\n    )\n    .add(\n        Requests\n            .indexRequest(\"catalog\")\n            .type(\"authors\")\n            .id(\"2\")\n            .source(zacharyTong)\n            .parent(\"978-1449358549\")\n            .opType(OpType.INDEX)\n    )\n    .setRefreshPolicy(RefreshPolicy.WAIT_UNTIL)\n    .setTimeout(TimeValue.timeValueMillis(500))\n    .get(TimeValue.timeValueSeconds(1));\n\t\t\nassertThat(response.hasFailures())\n    .withFailMessage(\"Bulk operation reported some failures: %s\", \n        response.buildFailureMessage())\n    .isFalse();\n<\/pre>\n<p>We are sending two index requests for <code>authors<\/code> collection in one single batch. You might be wondering what this <code>parent(\"978-1449358549\")<\/code> means and to answer this question we have to recall that <code>books<\/code> and <code>authors<\/code> are modeled using parent \/ child relationships. So the <code>parent<\/code> key in this case is the reference (by the <code>_id<\/code> property) to the respective parent document in <code>books<\/code> collection.<\/p>\n<p>Well done, so we know how to work with indices and how to index the documents using <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> transport client Java APIs. It is search time now!<\/p>\n<pre class=\"brush:java\">final SearchResponse response = client\n    .prepareSearch(\"catalog\")\n    .setTypes(\"books\")\n    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)\n    .setQuery(QueryBuilders.matchAllQuery())\n    .setFrom(0)\n    .setSize(10)\n    .setTimeout(TimeValue.timeValueMillis(100))\n    .get(TimeValue.timeValueMillis(200));\n\nassertThat(response.getHits().hits())\n    .withFailMessage(\"Expecting at least one book to be returned\")\n    .isNotEmpty();\n<\/pre>\n<p>The simplest search criterion one can come up with is to match all documents and this is what we have done in the snippet above (please notice that we explicitly limited the number of results returned to <code>10<\/code> documents).<\/p>\n<p>To our luck, <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> Java API has full-fledged implementation of <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/query-dsl.html\">Query DSL<\/a> in a form of <code>QueryBuilders<\/code> and <code>QueryBuilder<\/code> classes so writing (and maintaining) the complex queries is exceptionally easy. As an exercise, we are going to build the same compound query which we came up with in the previous part of the tutorial:<\/p>\n<pre class=\"brush:java\">final QueryBuilder query = QueryBuilders\n    .boolQuery()\n        .must(\n            QueryBuilders\n                .rangeQuery(\"rating\")\n                .gte(4)\n        )\n        .must(\n            QueryBuilders\n                .nestedQuery(\n                    \"categories\", \n                    QueryBuilders.matchQuery(\"categories.name\", \"analytics\"),\n                    ScoreMode.Total\n                )\n            )\n        .must(\n            QueryBuilders\n                .hasChildQuery(\n                    \"authors\", \n                    QueryBuilders.termQuery(\"last_name\", \"Gormley\"),\n                    ScoreMode.Total\n                )\n    );\n<\/pre>\n<p>The code looks pretty, concise and human-readable. If you are keen on using <a href=\"https:\/\/docs.oracle.com\/javase\/1.5.0\/docs\/guide\/language\/static-import.html\">static imports<\/a> feature of the Java programming language, the query is going to look even more compact.<\/p>\n<pre class=\"brush:java\">final SearchResponse response = client\n    .prepareSearch(\"catalog\")\n    .setTypes(\"books\")\n    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)\n    .setQuery(query)\n    .setFrom(0)\n    .setSize(10)\n    .setFetchSource(\n        new String[] { \"title\", \"publisher\" }, \/* includes *\/ \n        new String[0] \/* excludes *\/\n    )\n    .setTimeout(TimeValue.timeValueMillis(100))\n    .get(TimeValue.timeValueMillis(200));\n\nassertThat(response.getHits().hits())\n    .withFailMessage(\"Expecting at least one book to be returned\")\n    .extracting(\"sourceAsString\", String.class)\n    .hasOnlyOneElementSatisfying(source -&gt; {\n        assertThat(source).contains(\"Elasticsearch: The Definitive Guide.\");\n    });<\/pre>\n<p>To keep both versions of the query identical, we also hinted the search request through <code>setFetchSource<\/code> method that we are interested only in returning title and publisher properties of the document source.<\/p>\n<p>The curious readers might be wondering how to use aggregations along with the search requests. This is excellent topic to cover so let us talk about that for a moment. Along with <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/query-dsl.html\">Query DSL<\/a>, <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> Java API also supplies <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/java-aggs.html\">aggregations DSL<\/a>, revolving around <code>AggregationBuilders<\/code> and <code>AggregationBuilder<\/code> classes. For example, this is how we could build the bucketed aggregation by <code>publisher<\/code> property.<\/p>\n<pre class=\"brush:java\">final AggregationBuilder aggregation = AggregationBuilders\n    .terms(\"publishers\")\n    .field(\"publisher\")\n    .size(10);\n<\/pre>\n<p>Having the aggregations defined, we could inject them into search request using <code>addAggregation<\/code> method call as is shown in the code snippet below:<\/p>\n<pre class=\"brush:java\">final SearchResponse response = client\n    .prepareSearch(\"catalog\")\n    .setTypes(\"books\")\n    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)\n    .setQuery(QueryBuilders.matchAllQuery())\n    .addAggregation(aggregation)\n    .setFrom(0)\n    .setSize(10)\n    .setTimeout(TimeValue.timeValueMillis(100))\n    .get(TimeValue.timeValueMillis(200));\n\nfinal StringTerms publishers = response.getAggregations().get(\"publishers\");\nassertThat(publishers.getBuckets())\n    .extracting(\"keyAsString\", String.class)\n    .contains(\"O'Reilly\");\n<\/pre>\n<p>The results of the aggregations are available in the response and could be retrieved by referencing the aggregation name, for example <code>publishers<\/code> in our case. However be cautious and carefully use the proper aggregation types in order to not get surprises in a form of <a href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/java\/lang\/ClassCastException.html\">ClassCastException<\/a>. Because our publishers aggregation has been defined to group terms into buckets, we are safe by casting the one from the response to <code>StringTerms <\/code>class instance.<\/p>\n<h2><a name=\"rest\"><\/a>3. Using Java Rest Client<\/h2>\n<p>One of the drawbacks related to the usage of the <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/index.html\">Java client API<\/a> is the requirement to be binary compatible with the version of <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> (either standalone or cluster) you are running.<\/p>\n<p>Fortunately, since the first release of <code>5.0.0<\/code> branch, <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> brings another option on the table: <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a>. It uses <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">HTTP<\/a> protocol to talk to <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a>\u00a0 by invoking its <a href=\"https:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">RESTful API<\/a> endpoints and is oblivious to the version of <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> (literally, it is compatible with all <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> versions).<\/p>\n<p>It should be noted though that <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> is pretty low level and is not as convenient to use as <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/index.html\">Java client API<\/a>, far from that in fact. However, there are quite a few reasons why one may prefer to use <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> over <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/index.html\">Java client API<\/a> to communicate with <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> so it is worth its own discussion. To start off, let us include the respective dependency into our <a href=\"https:\/\/maven.apache.org\/\">Apache Maven<\/a> <code>pom.xml<\/code> file.<\/p>\n<pre class=\"brush:xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.elasticsearch.client&lt;\/groupId&gt;\n    &lt;artifactId&gt;rest&lt;\/artifactId&gt;\n    &lt;version&gt;5.2.0&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>From the configuration perspective we only need to construct the instance of <code>RestClient<\/code> by calling <code>RestClient.builder<\/code> method.<\/p>\n<pre class=\"brush:java\">@Configuration\npublic class ElasticsearchClientConfiguration {\n    @Bean(destroyMethod = \"close\")\n    RestClient transportClient() {\n        return RestClient\n            .builder(new HttpHost(\"localhost\", 9200))\n            .setRequestConfigCallback(new RequestConfigCallback() {\n                  @Override\n                  public Builder customizeRequestConfig(Builder builder) {\n                      return builder\n                          .setConnectTimeout(1000)\n                          .setSocketTimeout(5000);\n                  }\n            })\n            .build();\n    }\n}\n<\/pre>\n<p>We are jumping a bit ahead here but please pay particular attention to configuration of the proper timeouts because <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> does not provide a way (at least, at the moment) to specify those on per-request level basis. With that, we can inject the <code>RestClient<\/code> instance anywhere, using the same wiring techniques <a href=\"https:\/\/projects.spring.io\/spring-framework\/\">Spring Framework<\/a> is kindly providing to us:<\/p>\n<pre class=\"brush:java\">@Autowired private RestClient client;\n<\/pre>\n<p>To make a fair comparison between <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/index.html\">Java client API<\/a> and <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a>, we are going to dissect a couple of examples we have looked at in the previous section, setting out the stage by checking the <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> cluster health.<\/p>\n<pre class=\"brush:java\">@Test\npublic void esClusterIsHealthy() throws Exception {\n    final Response response = client\n        .performRequest(HttpGet.METHOD_NAME, \"_cluster\/health\", emptyMap());\n\n    final Object json = defaultConfiguration()\n        .jsonProvider()\n        .parse(EntityUtils.toString(response.getEntity()));\n\t\t\n    assertThat(json, hasJsonPath(\"$.status\", equalTo(\"green\")));\n}\n<\/pre>\n<p>Indeed, the difference is obvious. As you may guess, <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> is actually a thin wrapper around the more generic, well-known and respected <a href=\"https:\/\/hc.apache.org\/\">Apache Http Client<\/a> library. The response is returned as a string or byte array and it becomes the responsibility of the caller to transform it to <a href=\"http:\/\/www.json.org\/\">JSON<\/a> and extract the necessary pieces of data. To deal with that in test assertions, we have on-boarded the wonderful <a href=\"https:\/\/github.com\/jayway\/JsonPath\">JsonPath<\/a> library, but you are free to make a choice here.<\/p>\n<p>A family of <code>performRequest<\/code> methods is the typical way for synchronous (or blocking) communication using <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> API. Alternatively, there is a family of <code>performRequestAsync<\/code> methods which are supposed to be used in fully asynchronous flows. In the next example we are going to use one of those in order to index the document into <code>books<\/code> collection.<\/p>\n<p>The simplest way to represent <a href=\"http:\/\/www.json.org\/\">JSON<\/a>-like structure in Java language is using plain old <code>Map&lt;String, Object&gt;<\/code> as it is demonstrated in the code fragment below.<\/p>\n<pre class=\"brush:java\">final Map&lt;String, Object&gt; source = new LinkedHashMap&lt;&gt;();\nsource.put(\"title\", \"Elasticsearch: The Definitive Guide. ...\");\nsource.put(\"categories\", \n    new Map[] {\n        singletonMap(\"name\", \"analytics\"),\n        singletonMap(\"name\", \"search\"),\n        singletonMap(\"name\", \"database store\")\n    }\n);\nsource.put(\"publisher\", \"O'Reilly\");\nsource.put(\"description\", \"Whether you need full-text search or ...\");\nsource.put(\"published_date\", \"2015-02-07\");\nsource.put(\"isbn\", \"978-1449358549\");\nsource.put(\"rating\", 4);\n<\/pre>\n<p>Now we need to convert this Java structure into valid <a href=\"http:\/\/www.json.org\/\">JSON<\/a> string. There are dozens of way to do so but we are going to leverage the <a href=\"https:\/\/netplex.github.io\/json-smart\/\">json-smart<\/a> library, for the reason that it is already available as a transitive dependency of <a href=\"https:\/\/github.com\/jayway\/JsonPath\">JsonPath<\/a> library.<\/p>\n<pre class=\"brush:java\">final HttpEntity payload = new NStringEntity(JSONObject.toJSONString(source), \n    ContentType.APPLICATION_JSON);\n<\/pre>\n<p>Having the payload ready, nothing prevents us from invoking <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/docs-index_.html\">Indexing API<\/a> of the <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> to add a book into <code>books<\/code> collection.<\/p>\n<pre class=\"brush:java\">client.performRequestAsync(\n    HttpPut.METHOD_NAME, \n    \"catalog\/books\/978-1449358549\",\n    emptyMap(),\n    payload,\n    new ResponseListener() {\n        @Override\n        public void onSuccess(Response response) {\n            LOG.info(\"The document has been indexed successfully\");\n        }\n\t\t\t\t\n        @Override\n        public void onFailure(Exception ex) {\n            LOG.error(\"The document has been not been indexed\", ex);\n        }\n    });\n<\/pre>\n<p>This time we decided to not wait for the response but supply a callback (instance of <code>ResponseListener<\/code>) instead, keeping the flow truly asynchronous. To finish up, it would be great to understand what it takes to perform more or less realistic search request and parse the results.<\/p>\n<p>As you may expect, the <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> does not provide any fluent APIs around <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/query-dsl.html\">Query DSL<\/a> so we have to fallback to <code>Map&lt;String, Object&gt;<\/code> one more time in order to construct the search criteria.<\/p>\n<pre class=\"brush:java\">final Map&lt;String, Object&gt; authors = new LinkedHashMap&lt;&gt;();\nauthors.put(\"type\", \"authors\");\nauthors.put(\"query\", \n    singletonMap(\"term\",\n        singletonMap(\"last_name\", \"Gormley\")\n    )\n);\n\t\t\nfinal Map&lt;String, Object&gt; categories = new LinkedHashMap&lt;&gt;();\ncategories.put(\"path\", \"categories\");\ncategories.put(\"query\",\n    singletonMap(\"match\", \n        singletonMap(\"categories.name\", \"search\")\n    )\n);\n\t\t\nfinal Map&lt;String, Object&gt; query = new LinkedHashMap&lt;&gt;();\nquery.put(\"size\", 10);\nquery.put(\"_source\", new String[] { \"title\", \"publisher\" });\nquery.put(\"query\", \n    singletonMap(\"bool\",\n        singletonMap(\"must\", new Map[] {\n            singletonMap(\"range\",\n                singletonMap(\"rating\", \n                    singletonMap(\"gte\", 4)\n                )\n            ),\n            singletonMap(\"has_child\", authors),\n            singletonMap(\"nested\", categories)\n        })\n    )\n);\n<\/pre>\n<p>The price to pay by tackling the problem openly is a lot of cumbersome and error-prone code to write. In this regard, the consistency and conciseness of <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/index.html\">Java client API<\/a> really makes a huge difference. You may argue that in reality one may rely on much simpler and safer techniques, like <a href=\"https:\/\/en.wikipedia.org\/wiki\/Data_transfer_object\">data transfer object<\/a>, <a href=\"https:\/\/martinfowler.com\/bliki\/ValueObject.html\">value objects<\/a>, or even to have <a href=\"http:\/\/www.json.org\/\">JSON<\/a> search query templates with placeholders, but the point is a little help is offered by <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> at the moment.<\/p>\n<pre class=\"brush:java\">final HttpEntity payload = new NStringEntity(JSONObject.toJSONString(query), \n    ContentType.APPLICATION_JSON);\n\nfinal Response response = client\n    .performRequest(HttpPost.METHOD_NAME, \"catalog\/books\/_search\", \n        emptyMap(), payload);\n\nfinal Object json = defaultConfiguration()\n    .jsonProvider()\n    .parse(EntityUtils.toString(response.getEntity()));\n\nassertThat(json, hasJsonPath(\"$.hits.hits[0]._source.title\", \n    containsString(\"Elasticsearch: The Definitive Guide.\")));\n<\/pre>\n<p>Not much to add here, just consult the <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/search-request-body.html\">Search API<\/a> documentation on the format and extract the details of your interest from the response, like we do by asserting on the <code>title property<\/code> of the document <code>_source<\/code>.<\/p>\n<p>With that, we are wrapping up our discussion about <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a>. Frankly speaking, you may find it unclear if there are any benefits of using it versus choosing one of the generic <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">HTTP<\/a> clients Java ecosystem is rich of. Indeed, this is a valid concern but please keep in mind that <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> is brand new addition to <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> family and, hopefully, we are going to see a lot of exciting features pumped into it very soon.<br \/>\n[ulp id=&#8217;lFK4fMZhpULqeQUl&#8217;]<br \/>\n&nbsp;<\/p>\n<h2><a name=\"testing\"><\/a>4. Using Testing Kit<\/h2>\n<p>As our applications become more complex and distributed, the proper testing becomes as important as never before. For years <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> provides the <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/testing-framework.html\">superior test harness<\/a> in order to simplify the testing of the applications which heavily rely on its search and analytics features. More specifically, there are two types of tests which you may need in your projects:<\/p>\n<ul>\n<li><strong>Unit tests<\/strong>: those are testing the individual units (like classes f.e.) in isolation and generally do not require to have running <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> nodes or clusters. These kinds of tests are backed by <code>ESTestCase<\/code> and <code>ESTokenStreamTestCase<\/code>.<\/li>\n<li><strong>Integration tests<\/strong>: those are testing the complete flows and usually require at least one running <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> node (or cluster, to stress out more realistic scenarios). These kinds of tests are backed by <code>ESIntegTestCase<\/code>, <code>ESSingleNodeTestCase<\/code> and <code>ESBackCompatTestCase<\/code>.<\/li>\n<\/ul>\n<p>Let us roll the sleeves one more time and learn how to use the test scaffolding provided by <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> to develop our own test suites. \u00a0We are going to start off by declaring our dependencies, still using <a href=\"https:\/\/maven.apache.org\/\">Apache Maven<\/a> for that.<\/p>\n<pre class=\"brush:xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.apache.lucene&lt;\/groupId&gt;\n    &lt;artifactId&gt;lucene-test-framework&lt;\/artifactId&gt;\n    &lt;version&gt;6.4.0&lt;\/version&gt;\n    &lt;scope&gt;test&lt;\/scope&gt;\n&lt;\/dependency&gt;\n\n&lt;dependency&gt;\n    &lt;groupId&gt;org.elasticsearch.test&lt;\/groupId&gt;\n    &lt;artifactId&gt;framework&lt;\/artifactId&gt;\n    &lt;version&gt;5.2.0&lt;\/version&gt;\n    &lt;scope&gt;test&lt;\/scope&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>Although this is not strictly necessary, we are also adding the explicit dependency to <a href=\"http:\/\/junit.org\/junit4\/\">JUnit<\/a>, bumping its version to <code>4.12<\/code>.<\/p>\n<pre class=\"brush:xml\">&lt;dependency&gt;\n    &lt;groupId&gt;junit&lt;\/groupId&gt;\n    &lt;artifactId&gt;junit&lt;\/artifactId&gt;\n    &lt;version&gt;4.12&lt;\/version&gt;\n    &lt;scope&gt;test&lt;\/scope&gt;\n    &lt;exclusions&gt;\n        &lt;exclusion&gt;\n            &lt;groupId&gt;org.hamcrest&lt;\/groupId&gt;\n            &lt;artifactId&gt;hamcrest-core&lt;\/artifactId&gt;\n        &lt;\/exclusion&gt;\n    &lt;\/exclusions&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>We have to sound a note of caution here: the <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> test framework is exceptionally sensitive to dependencies, making sure your application does not fall into the problem so well known to every Java developer as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Java_Classloader#JAR_hell\">jar hell<\/a>. One of the pre-checks <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> test framework does is ensuring there are no duplicate classes in classpath. It is quite often that you may use other excellent testing libraries along the way but if your <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> test cases suddenly are starting to fail the initialization phase, it is very likely due to <a href=\"https:\/\/en.wikipedia.org\/wiki\/Java_Classloader#JAR_hell\">jar hell<\/a> issues detected and some exclusions have to be applied.<\/p>\n<p>And one more thing, very likely you may need to turn off security manager during the test runs by setting <code>tests.security.manager<\/code> property to <code>false<\/code>. This could be done either by passing <code>-Dtests.security.manager=false<\/code> argument to JVM directly or using <a href=\"https:\/\/maven.apache.org\/\">Apache Maven<\/a> plugin configuration.<\/p>\n<pre class=\"brush:xml\">&lt;plugin&gt;\n    &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\n    &lt;artifactId&gt;maven-surefire-plugin&lt;\/artifactId&gt;\n    &lt;version&gt;2.19.1&lt;\/version&gt;\n    &lt;configuration&gt;\n        &lt;argLine&gt;-Dtests.security.manager=false&lt;\/argLine&gt;\n    &lt;\/configuration&gt;\n&lt;\/plugin&gt;\n<\/pre>\n<p>Wonderful, all prerequisites are explained and we are all set to start developing our first test cases. The <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/unit-tests.html\">unit tests<\/a> in context applicable to <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> are very useful to test your own <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/analysis-analyzers.html\">analyzers<\/a>, <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/analysis-tokenizers.html\">tokenizers<\/a>, <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/analysis-tokenfilters.html\">token filters<\/a> and <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/analysis-charfilters.html\">character filters<\/a>. We have not done much in this regards, but the <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/integration-tests.html\">integration tests<\/a> are a very different story. Let us see what it takes to spin up <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> cluster with <code>3<\/code> nodes.<\/p>\n<pre class=\"brush:java\">@ClusterScope(numDataNodes = 3)\npublic class ElasticsearchClusterTest extends ESIntegTestCase {\n}\n<\/pre>\n<p>And \u2026 literally, that is it. Surely, although the cluster is up, it has no indices or whatnot preconfigured. \u00a0Let us add some test background to create a <code>catalog<\/code> index and its mapping types, using the same <code>catalog-index.json<\/code> file.<\/p>\n<pre class=\"brush:java\">@Before\npublic void setUpCatalog() throws IOException {\n    try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) {\n        Streams.copy(getClass().getResourceAsStream(\"\/catalog-index.json\"), \n            out);\n\t\t\t\n        final CreateIndexResponse response = admin()\n\t\t.indices()\n            .prepareCreate(\"catalog\")\n            .setSource(out.toByteArray())\n            .get();\n\t\t\t\n        assertAcked(response);\n        ensureGreen(\"catalog\");\n    }\n}\n<\/pre>\n<p>If you recognize this code already it is because we are using the same transport client we have learned about before! <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> test scaffolding provides it for you behind <code>client()<\/code> or <code>admin()<\/code> methods, along with <code>getRestClient()<\/code> in case you need <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> instance. It would be good to clear up the cluster after each test run, luckily we can use <code>cluster()<\/code> method to get access to couple of very useful operations, for example:<\/p>\n<pre class=\"brush:java\">@After\npublic void tearDownCatalog() throws IOException, InterruptedException {\n    cluster().wipeIndices(\"catalog\");\n}\n<\/pre>\n<p>Overall, <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> test harness aims for two goals: simplify the most common tasks (we have already seen <code>client()<\/code>, <code>admin()<\/code>, <code>cluster()<\/code> in action) and easily do the verification, assertions or expectations (for example, <code>ensureGreen(...)<\/code>, <code>assertAcked(...)<\/code>). The official documentation has dedicated sections which go over <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/integration-tests.html#helper-methods\">helper methods<\/a> and <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/assertions.html\">assertions<\/a> so please take a look.<\/p>\n<p>To begin with, the empty index should have no documents in it so our first test case is going to assert this fact explicitly.<\/p>\n<pre class=\"brush:java\">@Test\npublic void testEmptyCatalogHasNoBooks() {\n    final SearchResponse response = client()\n        .prepareSearch(\"catalog\")\n        .setTypes(\"books\")\n        .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)\n        .setQuery(QueryBuilders.matchAllQuery())\n        .setFetchSource(false)\n        .get();\n\n    assertNoSearchHits(response);\t\n}\n<\/pre>\n<p>Easy one, but what about creating real documents? <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> test framework has a wide range of helpful methods to generate random values for mostly any type. We can leverage that to create a book, add it into the book <code>catalog<\/code> index and issue the queries against it.<\/p>\n<pre class=\"brush:java\">@Test\npublic void testInsertAndSearchForBook() throws IOException {\n    final XContentBuilder source = JsonXContent\n        .contentBuilder()\n\t  .startObject()\n        .field(\"title\", randomAsciiOfLength(100))\n        .startArray(\"categories\")\n            .startObject().field(\"name\", \"analytics\").endObject()\n            .startObject().field(\"name\", \"search\").endObject()\n            .startObject().field(\"name\", \"database store\").endObject()\n        .endArray()\n        .field(\"publisher\", randomAsciiOfLength(20))\n        .field(\"description\", randomAsciiOfLength(200))\n        .field(\"published_date\", new LocalDate(2015, 02, 07).toDate())\n        .field(\"isbn\", \"978-1449358549\")\n        .field(\"rating\", randomInt(5))\n        .endObject();\n\t\t\n    index(\"catalog\", \"books\", \"978-1449358549\", source);\n    refresh(\"catalog\");\n\t\t\n    final QueryBuilder query = QueryBuilders\n        .nestedQuery(\n            \"categories\", \n            QueryBuilders.matchQuery(\"categories.name\", \"analytics\"),\n            ScoreMode.Total\n        );\n    \t\n    final SearchResponse response = client()\n        .prepareSearch(\"catalog\")\n        .setTypes(\"books\")\n        .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)\n        .setQuery(query)\n        .setFetchSource(false)\n        .get();\n\n    assertSearchHits(response, \"978-1449358549\");\t\t\n}\n<\/pre>\n<p>As you can see, most of the book properties are generated randomly except the <code>categories<\/code> so we could reliably search by them.<\/p>\n<p>The <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> testing support opens a lot of interesting opportunities not only to test the successful outcomes but also to simulate realistic cluster behavior and erroneous conditions (the helper methods provided by <code>internalCluster()<\/code> are exceptionally useful here). For such a complex distributed system as <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a>, the value of such tests is priceless so please leverage the available options to ensure that the code deployed into production is robust and resilient to failures.\u00a0 As a quick example, we could shutdown random data node while running the search requests and assert that they are still being processed.<\/p>\n<pre class=\"brush:java\">@Test\npublic void testClusterNodeIsDown() throws IOException {\n    internalCluster().stopRandomDataNode();\n        \n    final SearchResponse response = client()\n        .prepareSearch(\"catalog\")\n        .setTypes(\"books\")\n        .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)\n        .setQuery(QueryBuilders.matchAllQuery())\n        .setFetchSource(false)\n        .get();\n\n    assertNoSearchHits(response);\n}\n<\/pre>\n<p>We just scratched the surface of what is possible with <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> test harness. Hopefully you are practicing test-driven development in your organization and the examples we have looked at could serve you well as a starting point.<\/p>\n<h2><a name=\"conclusions\"><\/a>5. Conclusions<\/h2>\n<p>In this part of the tutorial we have learned about two types of the Java client APIs which <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> offers out of the box: <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/index.html\">transport client<\/a> and <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">REST client<\/a>. You may find it difficult to make a choice of what Java client APIs favor to use, but by and large, it highly depends on an application. In most cases <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/index.html\">transport client<\/a> is the best option however if your project uses just a couple of <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> APIs (or very limited subset of its features), <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">REST client<\/a> could be a better alternative. Also, we should not forget that <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-rest\/current\/index.html\">Java REST client<\/a> is pretty new and will improve in future releases for sure, so keep an eye on it.<\/p>\n<p>While we have been dissecting <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/client\/java-api\/current\/index.html\">transport client<\/a>, the point has been made about its fully asynchronous nature. Although it is good thing by all means, we have seen that it is based on callbacks (more precisely, listeners) which may quickly lead to the problem known as <a href=\"http:\/\/stackoverflow.com\/questions\/29341582\/how-to-avoid-callback-hell-in-java\">callback hell<\/a>. It is highly advisable to fight this issue early on (luckily, there are quite a few libraries and alternatives available like <a href=\"https:\/\/github.com\/ReactiveX\/RxJava\">RxJava 2<\/a> and <a href=\"http:\/\/projectreactor.io\/\">Project Reactor<\/a>, with <a href=\"https:\/\/community.oracle.com\/docs\/DOC-1006738\">Java 9<\/a> catching up as well).<\/p>\n<p>And last but not least, we have glanced over <a href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/testing-framework.html\">test harness<\/a> of <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> and had a chance to appreciate the great helps it provides to Java \/ JVM developers.<\/p>\n<h2><a name=\"next\"><\/a>6. What\u2019s next<\/h2>\n<p><a href=\"https:\/\/www.javacodegeeks.com\/2017\/04\/elasticsearch-java-developers-elasticsearch-ecosystem.html\">In the upcoming part<\/a>, the last one of the tutorial, we are going to talk about ecosystem of the terrific projects centered around <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a>. Hopefully, you will be amazed one more time by <a href=\"https:\/\/www.elastic.co\/products\/elasticsearch\">Elasticsearch<\/a> capabilities and features, opening for yourself new horizons of its applicability.<\/p>\n<p>The complete source code for all projects is available for download: <a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/elasticsearch-client-rest.zip\">elasticsearch-client-rest<\/a>, <a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/elasticsearch-testing.zip\">elasticsearch-testing<\/a>, <a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/elasticsearch-client-java.zip\">elasticsearch-client-java<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article is part of our Academy Course titled Elasticsearch Tutorial for Java Developers. In this course, we provide a series of tutorials so that you can develop your own Elasticsearch based applications. We cover a wide range of topics, from installation and operations, to Java API Integration and reporting. With our straightforward tutorials, you &hellip;<\/p>\n","protected":false},"author":141,"featured_media":65382,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[732],"class_list":["post-64718","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-java","tag-elasticsearch"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Elasticsearch for Java Developers: Elasticsearch from Java - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"This article is part of our Academy Course titled Elasticsearch Tutorial for Java Developers. In this course, we provide a series of tutorials so that you\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Elasticsearch for Java Developers: Elasticsearch from Java - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"This article is part of our Academy Course titled Elasticsearch Tutorial for Java Developers. In this course, we provide a series of tutorials so that you\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2017-03-29T10:00:14+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-11T08:17:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/04\/elastic-logo.png\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Andrey Redko\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrey Redko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html\"},\"author\":{\"name\":\"Andrey Redko\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\"},\"headline\":\"Elasticsearch for Java Developers: Elasticsearch from Java\",\"datePublished\":\"2017-03-29T10:00:14+00:00\",\"dateModified\":\"2023-12-11T08:17:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html\"},\"wordCount\":3460,\"commentCount\":8,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2017\\\/04\\\/elastic-logo.png\",\"keywords\":[\"Elasticsearch\"],\"articleSection\":[\"Core Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html\",\"name\":\"Elasticsearch for Java Developers: Elasticsearch from Java - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2017\\\/04\\\/elastic-logo.png\",\"datePublished\":\"2017-03-29T10:00:14+00:00\",\"dateModified\":\"2023-12-11T08:17:23+00:00\",\"description\":\"This article is part of our Academy Course titled Elasticsearch Tutorial for Java Developers. In this course, we provide a series of tutorials so that you\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2017\\\/04\\\/elastic-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2017\\\/04\\\/elastic-logo.png\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/elasticsearch-java-developers-elasticsearch-java.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Core Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/core-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Elasticsearch for Java Developers: Elasticsearch from Java\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\",\"name\":\"Andrey Redko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"caption\":\"Andrey Redko\"},\"description\":\"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\\\/EE, C#\\\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).\",\"sameAs\":[\"http:\\\/\\\/aredko.blogspot.com\\\/\",\"http:\\\/\\\/ca.linkedin.com\\\/in\\\/aredko\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/andrey-redko\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Elasticsearch for Java Developers: Elasticsearch from Java - Java Code Geeks","description":"This article is part of our Academy Course titled Elasticsearch Tutorial for Java Developers. In this course, we provide a series of tutorials so that you","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html","og_locale":"en_US","og_type":"article","og_title":"Elasticsearch for Java Developers: Elasticsearch from Java - Java Code Geeks","og_description":"This article is part of our Academy Course titled Elasticsearch Tutorial for Java Developers. In this course, we provide a series of tutorials so that you","og_url":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2017-03-29T10:00:14+00:00","article_modified_time":"2023-12-11T08:17:23+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/04\/elastic-logo.png","type":"image\/png"}],"author":"Andrey Redko","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Andrey Redko","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html"},"author":{"name":"Andrey Redko","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413"},"headline":"Elasticsearch for Java Developers: Elasticsearch from Java","datePublished":"2017-03-29T10:00:14+00:00","dateModified":"2023-12-11T08:17:23+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html"},"wordCount":3460,"commentCount":8,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/04\/elastic-logo.png","keywords":["Elasticsearch"],"articleSection":["Core Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html","url":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html","name":"Elasticsearch for Java Developers: Elasticsearch from Java - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/04\/elastic-logo.png","datePublished":"2017-03-29T10:00:14+00:00","dateModified":"2023-12-11T08:17:23+00:00","description":"This article is part of our Academy Course titled Elasticsearch Tutorial for Java Developers. In this course, we provide a series of tutorials so that you","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/04\/elastic-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/04\/elastic-logo.png","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/elasticsearch-java-developers-elasticsearch-java.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Core Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/core-java"},{"@type":"ListItem","position":4,"name":"Elasticsearch for Java Developers: Elasticsearch from Java"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413","name":"Andrey Redko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","caption":"Andrey Redko"},"description":"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\/EE, C#\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).","sameAs":["http:\/\/aredko.blogspot.com\/","http:\/\/ca.linkedin.com\/in\/aredko"],"url":"https:\/\/www.javacodegeeks.com\/author\/andrey-redko"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/64718","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/141"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=64718"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/64718\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/65382"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=64718"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=64718"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=64718"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}