Java.lang.NoSuchFieldError: org.Apache.http.message.BasicLineFormatter.Exemple de Mashape Unirest dans L'application Java

j'ai un projet Java Maven qui utilise Mashape Unirest pour envoyer des requêtes HTTP à D'autres URLs. Je suis en train d'écrire un test d'intégration (en utilisant TestNG ) qui envoie une requête HTTP normale en utilisant Unirest. Lorsque j'exécute le test d'intégration via Maven (via le plugin Failsafe), la requête est envoyée avec succès. Cependant, lorsque j'essaie d'exécuter le test d'intégration via Eclipse, j'obtiens toujours la erreur suivante:

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 ...

je suis également capable de reproduire cette erreur en utilisant un script D'application Java de base.

j'ai fait en sorte que les dépendances j'utilise dans mon pom.les fichiers xml sont les plus récents et les plus importants, comme on le voit ci-dessous:

<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>

j'ai aussi vérifié le code source de BasicLineFormatter.java , à la fois à partir du fichier source téléchargé sur Eclipse et de Httpcore D'Apache Dépôt Github . Dans le GitHub repo, notez comment le champ INSTANCE est défini pour le 4.3.la branche x et la branche trunk, mais pas dans les branches plus anciennes comme 4.2.x. Cependant, j'utilise effectivement la version 4.3.2 dans mon projet, donc je devrais utiliser un fichier JAR pour Httpcore qui a la dernière version de BasicLineFormatter . Je sais que, basé sur les fichiers JAR Maven Dependencies qui sont dans mon projet, j'utilise en effet les dernières versions de ces dépendances Apache, pas les anciennes. versions spécifiées comme dépendances en aval de mon projet.

j'ai vérifié d'autres différents articles de SOF et de blog sur cette question, tels que Mashape Unirest Java : java.lang.Noclassdeffonderror et ce billet de blog trop , mais ils semblent tous parler de résoudre le problème NoSuchFieldError pour Android . Cependant, je traite avec une application Java autonome, pas une application Android.

Je ne sais pas comment résoudre ce problème. Quelqu'un a une idée de ce que je dois faire?

UPDATE

au lieu de montrer mon cas de test, je réduirai l'illustration d'une reproduction de ce problème à une simple application Java à une seule couche, parce que le problème existe avec n'importe quelle application Java ou cas de test exécuté par Eclipse, et pas seulement un test en particulier:

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

Normalement, cela devrait imprimer le HTML de la page D'accueil de Google, mais je reçois à la place la trace de pile NoSuchFieldError.


fixe!

le problème était que le AWS SDK (il est sur mon chemin de classe parce que je me développe pour le haricot élastique) avait un fichier JAR en conflit. En utilisant la solution D'Oleg (merci BTW), j'ai imprimé la sortie suivante dans un test unitaire:

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

je vais prendre pour réorganiser mon chemin de classe pour QU'AWS SDK ne soit plus en conflit.

35
demandé sur Community 2014-02-19 00:24:13

5 réponses

la seule explication plausible à ce problème est qu'il existe une version plus ancienne de HttpCore sur le chemin de classe (à moins que vous ne vouliez également envisager une possibilité d'hommes verts de Mars jouer avec votre ordinateur à distance à partir d'une soucoupe volante).

vous pouvez ajouter cet extrait à votre code pour savoir à quel bocal la classe est ramassée. Cela pourrait aider à découvrir pourquoi ce bocal est sur votre chemin de classe en premier lieu.

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

This fondamentalement me dit que dans mon cas le pot réside dans le dépôt maven local et probablement avoir été ajouté à la classpath par 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
91
répondu oleg 2014-02-19 09:37:01

comme déjà mentionné dans les commentaires précédents, c'est principalement à cause des versions en conflit du httpcore jar, L'INSTANCE de champ statique a été ajoutée à la classe BasicLineFormatter dans versions > 4.3.1 , bien que vous ayez pu ajouter la dernière version du httpcore jar dans vos dépendances, mais il est très possible que d'autres version (inférieure) du jar soit repris.

donc, d'abord pour confirmer que, mauvaise jarre est d'obtenir ramassé, utilisez la ligne de code suivante -

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

si cela imprime, la version inférieure du pot, alors il est confirmé qu'il choisit la version inférieure du pot httpcore (peut être d'autres dépendances de votre projet),

Solution -

ajouter les dépendances maven/gradle suivantes en haut de la liste des dépendances (ou au-dessus de l'autre dépendance du projet qui a causé le conflit) -

<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>
5
répondu Anand Immannavar 2015-08-16 15:00:37

j'ai fait face à la même exception à l'aide de 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)

et j'ai trouvé qu'il était dû à DefaultConnectionKeepAliveStrategy.INSTANCE; et le pot en conflit était apache-httpcomponents-httpclient.jar dans mon chemin de classe. Ajouter ce post pour aider quiconque fait face à la même exception

4
répondu Nivedita Dixit 2014-12-06 10:27:32

j'ai eu cette Exception: Caused by: java.lang.NoSuchFieldError: INSTANCE

Solution:

cela se produit si vous avez deux classes de version différentes dans votre classpath.... [ ... ], Donc je trouve d'abord cette classe (une version de la classe), cliquez sur cette classe , sélectionnez build path , puis je clique sur remove from build path .

1
répondu vijay m p 2015-04-27 08:40:40

si vous utilisez aws sdk, cette erreur est due à une inadéquation de la dépendance. Pour éviter cette erreur, faites ce qui suit:: 1.Mettez les dépendances dans l'ordre requis aws sdk et la fin de préférence 2.Ajouter le plugin shade au projet

Cela a résolu mon problème

0
répondu SamsonFrancis 2017-03-13 13:02:02