4

I am trying several examples from Jest to use as a POC for ElasticSearch integration.

Right now, I am trying just a basic GET. I created a POJO called Document. In there are some basic setters and getters are some fields. I populate it and then use GSON to generate the JSON text.

From this generated JSON, I go into ElasticSearch Sense and do the following:

PUT /reports/documents/3
{
    // JSON code
}

This generates just fine. I then try using Get to pull the values out from Java, like so:

JestClientFactory factory = new JestClientFactory();

factory.setHttpClientConfig(new HttpClientConfig
                            .Builder("http://localhost:9200")
                            .multiThreaded(true)
                            .build());

client = factory.getObject();

Get get = new Get.Builder("reports", "3").type("documents").build();

try {
    JestResult result = client.execute(get);
    String json = result.getJsonString();
    System.out.println(json);

    Document doc = null; 
    doc = result.getSourceAsObject(Document.class);
    System.out.println("is doc null? " + doc == null);
}catch (Exception e) {
    System.err.println("Error getting document");
    e.printStackTrace();
}

The String json returns what I would expect (showing _index, _type, _id and of course _source). However, doc always comes out as NULL. I am not sure why that is happening.

Just to see if this was just a Get problem, I proceeded to try to Search.I did the following code snippet:

try {
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.matchQuery("reportNumber", "101221895CRT-004"));

    Search search = new Search.Builder(searchSourceBuilder.toString())
                                        // multiple index or types can be added.
                                        .addIndex("reports")
                                        .addType("documents")
                                        .build();

    SearchResult result = client.execute(search);

    //List<Document> results = result.getSourceAsObjectList(Document.class);

    List<SearchResult.Hit<Document, Void>> hits = result.getHits(Document.class);

    for (SearchResult.Hit hit : hits) {
        Document source = (Document) hit.source;
        Void ex = (Void) hit.explanation;

        System.out.println();
    }

    System.out.println("Result size: " + hits.size());
}catch (Exception e) {
    System.err.println("Error searching");
    e.printStackTrace();
}

When looking at result, the JSON of the object is shown. However, the List<Document> results comes out as NULL. When using hits, the size of hits is correct, but the "source" and "ex" are both NULL.

Any ideas on what I am doing wrong with this?

UPDATE
After reading Cihat's comment, I went ahead and added in logging. It turns out I am getting an error when trying to convert a date (hence why it's always coming back as NULL).

I get the following error message:

Unhandled exception occurred while converting source to the object .com.someCompanyName.data.Document
com.google.gson.JsonSyntaxException: java.text.ParseException: Unparseable date: "Nov 6, 2014 8:29:00 AM"

I have tried all different formats:

  • 11/06/2014 8:29:00 AM (and without time and making year just 14)
  • 06-NOV-2014 8:29:00 AM (and without time and making year just 14)
  • 2014-11-06 8:29:00 AM (same thing with time and year changes)
  • 2014-NOV-06 8:29:00 AM (same thing with time and year changes)
  • 06/11/2014 8:29:00 AM (same thing)

All of those failed. I am sure I tried some other formats, so not sure what format the date should be in. I even tried the exact date from DateFormat JavaDocs and it still failed. Every time I do a search, it says to define the Dateformat in the GsonBuilder, but in Jest I do not have access to that.

Machavity
  • 30,841
  • 27
  • 92
  • 100
Ascalonian
  • 14,409
  • 18
  • 71
  • 103
  • 1
    What's your JSON structure look like? Where's the definition for `Document` and `STDocument`? Did you have a look at logs (maybe enable debug level logging on jest packages)? – Cihan Keser Apr 21 '15 at 14:41
  • I wrote a quick test case that uses Jest to index a document and then use `getSourceAsObject` to access it. That is working fine. This is probably a problem with GSON and your `Document` class. – Christian Trimble Apr 21 '15 at 20:07
  • @CihatKeser - Thank you for the suggestion on the logging. I added it and updated the question accordingly. – Ascalonian Apr 21 '15 at 20:54
  • 1
    You might want to checkout out this [test case](https://github.com/searchbox-io/Jest/blob/master/jest/src/test/java/io/searchbox/core/BulkIntegrationTest.java#L35). – Christian Trimble Apr 22 '15 at 00:45
  • @C.Trimble - That worked perfectly, thank you! Please remove your answer below and put that code snippet into the answer with the source link (you may get down voted for just providing the link) and I will accept your answer :-) – Ascalonian Apr 22 '15 at 02:57
  • 1
    The default date-time format Jest (and *hopefully* ES) uses is the ISO 8601 combined date+time format (i.e.: `yyyy-MM-dd'T'HH:mm:ssZ`); if you need any other format then you should set it on the gson instance as C.Trimble pointed out. Also for what it's worth: in the upcoming version these kind of deserialization exceptions will not be swallowed and get lost in logs as it did in here :) – Cihan Keser Apr 22 '15 at 10:09
  • @CihatKeser - I tried that as well (I knew I forgot a time format) haha. Thank you for the heads up regarding the upcoming version! – Ascalonian Apr 22 '15 at 11:35
  • "I tried that as well" meaning you are still getting the same error? – Cihan Keser Apr 22 '15 at 13:30
  • yes, I still got the error – Ascalonian Apr 22 '15 at 13:55
  • So the date field in your JSON (that you have indexed on ES) is something like "2015-04-19T12:59:23Z", right? – Cihan Keser Apr 22 '15 at 15:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/75948/discussion-between-cihat-keser-and-ascalonian). – Cihan Keser Apr 22 '15 at 15:56
  • I'm having the same issue. All of my timestamps are longs. How can I tell gson/jest to accept this? – Josh C. Sep 10 '19 at 16:29

1 Answers1

2

This test case demonstrates indexing a document with Jest and then getting the same document back out. Not a complete answer, but hopefully it is useful to see something that is known to work.

import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.JestResult;
import io.searchbox.client.config.HttpClientConfig;
import io.searchbox.core.Get;
import io.searchbox.core.Index;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.MatcherAssert.*;
import org.junit.Test;

public class JestRoundtripIT {

  public static final String INDEX = "reports";
  public static final String TYPE = "documents";
  public static final String ID = "3";

  @Test
  public void documentRoundTrip() throws Exception {
    JestClientFactory factory = new JestClientFactory();

    factory.setHttpClientConfig(new HttpClientConfig
                                .Builder("http://localhost:9200")
                                .multiThreaded(true)
                                .build());

    JestClient client = factory.getObject();

    Document original = new Document()
      .withAuthor("Shay Banon")
      .withContent("You know, for search...");

    JestResult indexResult = client.execute(
      new Index.Builder(original)
        .index(INDEX)
        .type(TYPE)
        .id(ID)
        .build());
    assertThat(indexResult.isSucceeded(), equalTo(true));

    JestResult getResult = client.execute(
      new Get.Builder(INDEX, ID)
      .type(TYPE)
      .build());
    assertThat(getResult.isSucceeded(), equalTo(true));

    Document fromEs = getResult.getSourceAsObject(Document.class);

    assertThat(fromEs, notNullValue());
    assertThat(fromEs.getAuthor(), equalTo(original.getAuthor()));
    assertThat(fromEs.getContent(), equalTo(original.getContent()));
  }

  public static class Document {
    protected String author;
    protected String content;
    public Document withAuthor( String author ) {
      this.author = author;
      return this;
    }

    public Document withContent( String content ) {
      this.content = content;
      return this;
    }

    public String getAuthor() {
      return author;
    }

    public void setAuthor( String author ) {
      this.author = author;
    }

    public String getContent() {
      return content;
    }

    public void setContent( String content ) {
      this.content = content;
    }
  }
}
Christian Trimble
  • 2,126
  • 16
  • 27