0

I have a little trouble understanding java streams. I created a JUnit test that basically stores an element in a database, retrieves it (results are returned in a stream), and then compares both elements. The test failed, so I started to debug. Suddenly the test passed. Turns out my breakpoint gave the stream the time it needed to build?!

@Test
public void matchAllTest() {
    client.insert(object); //database schema is empty

    Stream<Object> stream = client.query("{ query matching all objects }");

    Object firstResult = stream.findFirst().get();
    assertObjectEquals(object, firstResult);
}

query works with Elasticsearch as a database and looks like this:

public Stream<Object> query(String query) {
    SearchRequestBuilder request = client.prepareSearch("index");
    request.setQuery(query);

    Stream.Builder<Object> stream = Stream.builder();

    SearchResponse response = request.get();
    SearchHits hits = response.getHits();
    hits.forEach(object -> stream.accept(object);

    return stream.build();
}

client in the test refers to a class with the query method. client in the second code snippet refers to an Elasticsearch node client, see ES Java docs.

The test fails with a NoSuchElementException ("No value present")—unless I give it time.

What exactly is happening here and how can I avoid an exception?

Felix
  • 369
  • 4
  • 15
  • 1
    Is the `query` method asynchronous? What is `client`? – Vince Apr 13 '16 at 13:31
  • `client` connects to the database (Elasticsearch) and offers methods like `query` to store and retrieve objects. It says in the Elasticsearch docs that "[a]ll operations performed are asynchronous by nature". I tried to label the `query` method as synchronous but that didn't help. – Felix Apr 13 '16 at 13:53
  • What type is `client`? I couldn't find any types in the docs that expose a plain `query` method. Mind linking me to the docs? The [preface](https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-api.html) states "*either accepts a listener, or returns a future*", so you should be able to attach a listener to the client, or supply a callback function as an argument for the method, allowing you to be notified once the action (query) has been completed – Vince Apr 13 '16 at 15:06
  • `client` and its `query` method are some sort of middleware between application and database. I added the `query` method to my question. The `SearchResponse` returned in the `query` method offers operations like `isTimedOut` and `isTerminatedEarly`, see [SearchResponse javadoc](http://javadoc.kyubu.de/elasticsearch/HEAD/org/elasticsearch/action/search/SearchResponse.html). I couldn't solve my problem with these though. – Felix Apr 13 '16 at 15:57
  • 1
    Since `Stream.Builder` is invariant, the critical part is where the builder gets filled, in other words, the `forEach` method you invoke an an instance of `SearchHits`. We don’t know anything about the `SearchHits` type, but apparently it isn’t a `Stream` implementation so the issue hasn’t anything to do with the Stream API. – Holger Apr 13 '16 at 16:59
  • I don't see any methods that allow you to specify a listener. You might wanna double-check the documentation to see if you could find a way to specify listeners, since that would be the solution to this asynchronous call issue. It seems there is `status()`, but I'm not 100% sure how this works as I've never used this API before. You could try busy-waiting on `status() == RestStatus.OK`, but this won't inform you of potential problems during the request, and I'm not even sure if `OK` represents "*this request has been fulfilled*". – Vince Apr 13 '16 at 17:11
  • Thanks for all your input. You were right the issue had nothing to do with the stream API. I was just looking in the wrong place. Michael gave the right answer below. – Felix Apr 13 '16 at 20:45

1 Answers1

1

The problem is that a document is only searchable after a refresh in elasticsearch.

For testing, you can force a refresh.

  • Thank you, that fixed it. Problem was also discussed in the question [elasticsearch java API: matchAll search query doesn't return results?](http://stackoverflow.com/questions/12692758/elasticsearch-java-api-matchall-search-query-doesnt-return-results), including working code example. – Felix Apr 13 '16 at 20:42