Skip to content

Example from the readme doc fails with Jackson, works with Yasson #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sothawo opened this issue Jun 4, 2021 · 4 comments
Closed

Comments

@sothawo
Copy link
Contributor

sothawo commented Jun 4, 2021

I have set up a minimal Java application to test the client (https://github.com/sothawo/elastic-java-test) It's basically the code from the readme showing how to use the Elastisearch Client.

I have Elasticsearch 7.12.1 running in docker on port 9002 and am using an intercepting proxy on port 8080 to check what's going over the wire.

So this simple code

public class App {

    public static void main(String[] args) throws IOException {

        // Create the low-level client
        RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200))
            .setHttpClientConfigCallback(builder -> {
                builder.setProxy(new HttpHost("localhost", 8080));
                return builder;
            })
            .build();

        // Create the transport that provides JSON and http services to API clients
        Transport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());

        // And create our API client
        ElasticsearchClient client = new ElasticsearchClient(transport);

        // Search all items in an index that contains documents of type AppData
        SearchResponse<AppData> search = client.search(s -> s
                .index("appdata-index"),
            AppData.class
        );

        if (search.hits().hits().isEmpty()) {
            System.out.println("No match");
        } else {
            for (Hit<AppData> hit : search.hits().hits()) {
                processAppData(hit._source());
            }
        }
    }

    private static void processAppData(AppData appData) {
        if (appData != null) {
            System.out.println(appData.toString());
        }
    }
}

leads to this error:

20:06:06: Executing task 'App.main()'...

> Task :compileJava UP-TO-DATE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE

> Task :App.main()
Exception in thread "main" java.lang.NullPointerException: took
	at java.base/java.util.Objects.requireNonNull(Objects.java:233)
	at co.elastic.clients.elasticsearch._global.SearchResponse.<init>(SearchResponse.java:105)
	at co.elastic.clients.elasticsearch._global.SearchResponse$Builder.build(SearchResponse.java:381)
	at co.elastic.clients.elasticsearch._global.SearchResponse$Builder.build(SearchResponse.java:365)
	at co.elastic.clients.json.JsonpObjectBuilderParser.parse(JsonpObjectBuilderParser.java:43)
	at co.elastic.clients.json.JsonpValueParser.parse(JsonpValueParser.java:91)
	at co.elastic.clients.base.RestClientTransport.getHighLevelResponse(RestClientTransport.java:175)
	at co.elastic.clients.base.RestClientTransport.performRequest(RestClientTransport.java:65)
	at co.elastic.clients.elasticsearch.ElasticsearchClient.search(ElasticsearchClient.java:1227)
	at co.elastic.clients.elasticsearch.ElasticsearchClient.search(ElasticsearchClient.java:1246)
	at com.sothawo.elasticjavatest.App.main(App.java:39)

That's when parsing the response, not even on parsing the returned data.

In the proxy I see the following request

POST http://localhost:9200/appdata-index/_search HTTP/1.1
Content-Length: 2
Content-Type: application/json; charset=UTF-8
Proxy-Connection: Keep-Alive
User-Agent: elasticsearch-java/7.12.1-SNAPSHOT (Java/16.0.1)
X-Elastic-Client-Meta: es=7.12.1-SNAPSHOT,jv=16,t=7.12.1-SNAPSHOT,hc=4.1.4
Host: localhost:9200

{}

and this response:

HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 408

{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 1.0,
        "hits": [
            {
                "_index": "appdata-index",
                "_type": "_doc",
                "_id": "5sko2HkB1yiMr4eS5Dmo",
                "_score": 1.0,
                "_source": {
                    "foo": "foo1",
                    "bar": "bar1"
                }
            },
            {
                "_index": "appdata-index",
                "_type": "_doc",
                "_id": "58ko2HkB1yiMr4eS-jlu",
                "_score": 1.0,
                "_source": {
                    "foo": "foo2",
                    "bar": "bar2"
                }
            }
        ]
    }
}

So the request and response over the wire are ok. Taking the proxy out yields the same result.

What could be the reason for this error?

@sothawo sothawo changed the title Cannot run the simple example from the readme doc Example from the readme doc fails with Jackson, works with Yasson Jun 5, 2021
@sothawo
Copy link
Contributor Author

sothawo commented Jun 5, 2021

Addition: When I change to the Yasson jsonb processing by using this:

Transport transport = new RestClientTransport(restClient, new JsonbJsonpMapper());

instead of the JacksonJsonpMapper() the call succeeds.

@swallez
Copy link
Member

swallez commented Jun 10, 2021

Thanks for trying out the new Java client! Still early days, but feedback is very welcome!

There's an issue in the JacksonJsonpParser class that converts Jackson parser events into JSON-P events. I'm currently working on it, and will update once I've fixed it.

@sothawo
Copy link
Contributor Author

sothawo commented Jun 10, 2021

Looks great up to now. I wrote reactive counterparts to ApiClient, Transport and ElasticsearchClient (the last one just for the first search method) and can reuse the Endpoints and part of the code from the RestClientTransport to send the requests and parse the responses over the wire for imperative and reactive code. That will definitely allow me to clean up the codebase in Spring Data Elasticsearch when we use this for reactive and imperative code.
My biggest problem seems to be that I already have a class named ReactiveElasticsearchClient and I need to support them both until version 8 of ES.

@swallez
Copy link
Member

swallez commented Jun 11, 2021

Fixed in 3bef3fd that also adds tests. I've pushed a new snapshot that also includes your changes from #6. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants