-->

Elasticsearch Rest Client throws java.lang.ArraySt

2019-09-02 07:18发布

问题:

I am using Elasticsearch Rest Client v5.5.3 to execute Elasticsearch queries in a Java application. It always throws java.lang.ArrayStoreException. First I suspect frequency of query execution since application intensively executes queries but it throws exception very first query. Second I update some dependencies like Apache HttpCore.jar which Elasticsearch rest client uses. But either way I could not figure out how to solve it still throws exception. Stack trace is below;

java.lang.ArrayStoreException: org.apache.http.impl.cookie.RFC2965VersionAttributeHandler
    at org.apache.http.impl.cookie.DefaultCookieSpecProvider.create(DefaultCookieSpecProvider.java:92) ~[httpclient-4.5.2.jar:4.5.2]
    at org.apache.http.client.protocol.RequestAddCookies.process(RequestAddCookies.java:152) ~[flux-core-1.1.0.jar:1.1.0]
    at org.apache.http.protocol.ImmutableHttpProcessor.process(ImmutableHttpProcessor.java:132) ~[flux-core-1.1.0.jar:1.1.0]
    at org.apache.http.impl.nio.client.MainClientExec.prepareRequest(MainClientExec.java:520) ~[httpasyncclient-4.1.2.jar:4.1.2]
    at org.apache.http.impl.nio.client.MainClientExec.prepare(MainClientExec.java:146) ~[httpasyncclient-4.1.2.jar:4.1.2]
    at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.start(DefaultClientExchangeHandlerImpl.java:124) ~[httpasyncclient-4.1.2.jar:4.1.2]
    at org.apache.http.impl.nio.client.InternalHttpAsyncClient.execute(InternalHttpAsyncClient.java:141) ~[httpasyncclient-4.1.2.jar:4.1.2]
    at org.elasticsearch.client.RestClient.performRequestAsync(RestClient.java:343) ~[rest-5.5.3.jar:5.5.3]
    at org.elasticsearch.client.RestClient.performRequestAsync(RestClient.java:325) ~[rest-5.5.3.jar:5.5.3]
    at org.elasticsearch.client.RestClient.performRequest(RestClient.java:218) ~[rest-5.5.3.jar:5.5.3]
    at org.elasticsearch.client.RestClient.performRequest(RestClient.java:191) ~[rest-5.5.3.jar:5.5.3]
    at com.nova.stats.platform.are.batch.rule.ElasticsearchQueryExecutor.execute(ElasticsearchQueryExecutor.java:36) [classes/:?]

The method executes queries;

public String execute(String query, QueryParameters parameters) throws IOException {
        String index = (String) parameters.getParameter(GlobalConfigurations.ElasticsearchConfigurations.ConfigurationFields.INDEX);
        String type = (String) parameters.getParameter(GlobalConfigurations.ElasticsearchConfigurations.ConfigurationFields.TYPE);

        RestClient restClient = ElasticsearchRestClient.getClient();
        HttpEntity entity;
        Response response = null;
        try {
            entity = new NStringEntity(query);
            response = restClient.performRequest("GET", "/" + index + "/" + type + "/_search",
                    Collections.singletonMap("pretty", "true"), entity);
        } catch (Exception e) {
            logger.error("Could not perform request, query: " + query, e);
        }

        String responseStr = responseStr = EntityUtils.toString(response.getEntity());


        return responseStr;
    }

回答1:

Problem description

The problem root cause is "JAR Hell" due to conflicts httpclient-4.5.2 and flux-core-1.1.0. I don't know why but flux-core-1.1.0 jar contains inside full httpclient codebase version 4.3.3 which is not compatible with 4.5.2.

What is ArrayStoreException, Javadoc quote:

public class ArrayStoreException extends RuntimeException Thrown to indicate that an attempt has been made to store the wrong type of object into an array of objects. For example, the following code generates an ArrayStoreException: Object x[] = new String[3]; x[0] = new Integer(0);

In version httpclient-4.3.3 RFC2965VersionAttributeHandler looks like

@Immutable
public class RFC2965VersionAttributeHandler implements CookieAttributeHandler {

In version httpclient-4.5.2 RFC2965VersionAttributeHandler looks like

@Immutable
public class RFC2965VersionAttributeHandler implements CommonCookieAttributeHandler {

And the problem in DefaultCookieSpec which tries to invoke constructor of RFC2965Spec of version 4.5.2 with RFC2965VersionAttributeHandler from 4.3.3, which in not implements CommonCookieAttributeHandler:

RFC2965Spec(final boolean oneHeader,
            final CommonCookieAttributeHandler... handlers) {
    super(oneHeader, handlers);
}

Solution

The most probably reason of "JAR Hell" - your pom.xml (or gradle) has dependency for httpclient-4.5.2. You should remove it from dependencies or downgrade to 4.3.3 version. Also your pom.xml may have dependency for httpasyncclient-4.1.2 - in this case you also could remove it from dependencies or downgrade to 4.0.x version. At worth your project could have transitive dependency for httpclient or httpasyncclient - in such case you need to find and fix it.