Подтвердить что ты не робот

Java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE от Mashape Unirest в приложении Java

У меня есть проект Maven Java, который использует Mashape Unirest для отправки HTTP-запросов на другие URL-адреса. В настоящее время я пишу интеграционный тест (используя TestNG), который отправляет обычный HTTP-запрос с использованием Unirest. Когда я запускаю интеграционный тест через Maven (через плагин Failsafe), запрос отправляется успешно. Однако, когда я пытаюсь запустить интеграционный тест через Eclipse, я продолжаю получать следующую ошибку:

FAILED: getCurrentTimeTest
java.lang.NoSuchFieldError: INSTANCE
    at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:52)
    at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:56)
    at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<clinit>(DefaultHttpRequestWriterFactory.java:46)
    at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:72)
    at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:84)
    at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<clinit>(ManagedHttpClientConnectionFactory.java:59)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory.<init>(PoolingHttpClientConnectionManager.java:487)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:147)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:136)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:112)
    at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:726)
    at com.mashape.unirest.http.options.Options.refresh(Options.java:41)
    at com.mashape.unirest.http.options.Options.<clinit>(Options.java:27)
    at com.mashape.unirest.http.HttpClientHelper.prepareRequest(HttpClientHelper.java:141)
    at com.mashape.unirest.http.HttpClientHelper.requestAsync(HttpClientHelper.java:80)
    at com.mashape.unirest.request.BaseRequest.asStringAsync(BaseRequest.java:56)
    at ...

Я также могу воспроизвести эту ошибку, используя базовое Java-приложение script.

Я убедился, что зависимости, которые я использую в моем файле pom.xml, являются самыми последними и наибольшими, как показано ниже:

<dependency>
    <groupId>com.mashape.unirest</groupId>
    <artifactId>unirest-java</artifactId>
    <version>1.3.5</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.3.2</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpasyncclient</artifactId>
    <version>4.0</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.3.2</version>
</dependency>
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20140107</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.3.2</version>
</dependency>

Я также проверил исходный код BasicLineFormatter.java, как из исходного файла, загруженного в Eclipse, так и из Apache Httpcore Github repo, В репозитории Github обратите внимание, как поле INSTANCE определено для ветки 4.3.x и ветки соединительной линии, но не в старых ветвях, таких как 4.2.x. Тем не менее, я действительно использую версию 4.3.2 в своем проекте, поэтому я должен использовать JAR файл для Httpcore с последней версией BasicLineFormatter. Я знаю, что на основе файлов JAR Maven Dependencies, которые находятся в моем проекте, я действительно использую последние версии этих зависимостей Apache, а не более старые версии, указанные как нисходящие зависимости моего проекта.

Я проверил другие сообщения SOF и блога об этой проблеме, такие как Mashape Unirest Java: java.lang.NoClassDefFoundError и это сообщение в блоге тоже, но все они, похоже, говорят о решении проблемы NoSuchFieldError для Android. Тем не менее, я имею дело с автономным Java-приложением, а не с Android-приложением.

Я затрудняюсь определить, как устранить эту проблему. Кто-нибудь знает, что мне нужно делать?

UPDATE

Вместо того, чтобы показывать мой тестовый пример, я уменьшу иллюстрацию воспроизведения этой проблемы до простого однострочного Java-приложения, поскольку проблема существует с любым Java-приложением или тестовым сценарием, выполняемым через Eclipse, а не только с одним конкретным тест:

System.out.println(Unirest.get("http://www.google.com").asStringAsync().get().getBody());

Обычно это должно печатать HTML-страницы главной страницы Google, но вместо этого я получаю трассировку стека NoSuchFieldError.


ИСПРАВЛЕНО!

Проблема заключалась в том, что AWS SDK (он на моем пути к классам, потому что я разрабатываю для Elastic Beanstalk) имел противоречивый JAR файл. Используя решение Oleg (спасибо BTW), я напечатал следующий вывод в unit test:

jar:file:/some/path/aws-java-sdk/1.7.1/third-party/httpcomponents-client-4.2.3/httpcore-4.2.jar!/org/apache/http/message/BasicLineFormatter.class

Мне придется перестроить мой путь к классам, чтобы AWS SDK больше не противоречил.

4b9b3361

Ответ 1

Единственное правдоподобное объяснение этой проблемы - это более старая версия HttpCore в пути к классам (если вы также не хотите рассматривать возможность того, что зеленые люди с Марса будут возиться с вашим компьютером удаленно от летающей тарелки).

Вы можете добавить этот фрагмент кода в свой код, чтобы узнать, из какой jar получает класс. Это может помочь выяснить, почему эта банка находится на вашем пути к классам.

ClassLoader classLoader = MyClass.class.getClassLoader();
URL resource = classLoader.getResource("org/apache/http/message/BasicLineFormatter.class");
System.out.println(resource);

В основном это говорит о том, что в моем случае jar находится в локальном репозитории maven и, вероятно, был добавлен в путь к классам Maven

jar:file:/home/oleg/.m2/repository/org/apache/httpcomponents/httpcore/4.3.1/httpcore-4.3.1.jar!/org/apache/http/message/BasicLineFormatter.class

Ответ 2

Как уже упоминалось в предыдущих комментариях, в основном из-за противоречивых версий httpcore jar, статическое поле INSTANCE добавлено в класс BasicLineFormatter в versions > 4.3.1. Хотя вы, возможно, добавили последнюю версию httpcore jar в ваших зависимостях, но очень возможно, что другая (более низкая) версия jar получает поднятую.

Итак, сначала, чтобы подтвердить, что неправильная банка подбирается, используйте следующую строку кода -

ClassLoader classLoader = <Your Class>.class.getClassLoader();
URL resource = classLoader.getResource("org/apache/http/message/BasicLineFormatter.class");
System.out.println(resource);

Если это печатает, более низкую версию банку, то она подтвердила, что она выбирает нижнюю версию httpcore jar (может быть, из других зависимостей вашего проекта),

Решение -

Добавьте следующие зависимости maven/ gradle в верхней части списка зависимостей (или выше другой зависимости проекта, вызвавшей конфликт) -

<dependency>
     <groupId>com.mashape.unirest</groupId>
     <artifactId>unirest-java</artifactId>
     <version>1.4.5</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.4.1</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.4.1</version>
</dependency>

Ответ 3

Я столкнулся с тем же исключением, используя unirest:

java.lang.NoSuchFieldError: INSTANCE
        at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:52)
at com.mashape.unirest.http.options.Options.refresh(Options.java:55)
at com.mashape.unirest.http.options.Options.<clinit>(Options.java:36)

И нашел, что это произошло из-за DefaultConnectionKeepAliveStrategy.INSTANCE;, а конфликтная банка была apache-httpcomponents-httpclient.jar в моем пути к классам. Добавление этого сообщения, чтобы помочь любому, кто сталкивается с подобным исключением

Ответ 4

Я получил это исключение: Caused by: java.lang.NoSuchFieldError: INSTANCE

Решение:

Это происходит, если у вас есть два разных класса версий в вашем пути к классам.... [...], поэтому сначала я нахожу этот класс (одну версию класса), щелкаю этот класс, выбираю путь сборки, затем нажимаю удалить из пути сборки.

Ответ 5

если вы используете aws sdk, эта ошибка возникает из-за несоответствия зависимости. Чтобы избежать этой ошибки, выполните следующие действия: 1. Положите зависимости в требуемом порядке aws sdk, а конец предпочтительно 2. Добавить плагин к проекту

Это решило мою проблему

Ответ 6

В настоящее время у меня такая же проблема в моей среде Prod, у меня есть зависимость "compile" org.apache.httpcomponents: httpclient: 4.5.2 '"

Исключение вызвано: java.lang.NoSuchFieldError: org/apache/http/conn/ssl/AllowAllHostnameVerifier.INSTANCE.

По тому же файлу EAR нормально работает в тестовой среде.