web-dev-qa-db-fra.com

java.lang.NoSuchFieldError: org.Apache.http.message.BasicLineFormatter.INSTANCE de Mashape Unirest dans Java application

J'ai un Maven Java qui utilise Mashape Unirest pour envoyer des requêtes HTTP à d'autres URL. J'écris actuellement un test d'intégration (en utilisant TestNG ) qui envoie une demande HTTP normale en utilisant Unirest. Lorsque j'exécute le test d'intégration via Maven (via le plugin Failsafe), la demande est envoyée avec succès. Cependant, lorsque j'essaie d'exécuter le test d'intégration via Eclipse, je continue à obtenir l'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 peux également reproduire cette erreur en utilisant un script d'application de base Java.

Je me suis assuré que les dépendances que j'utilise dans mon fichier pom.xml sont les plus récentes et les plus importantes, comme indiqué 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 également vérifié le code source de BasicLineFormatter.Java, à la fois depuis le fichier source téléchargé sur Eclipse et depuis Repo Httpcore Github d'Apache . Dans le référentiel Github, notez comment le champ INSTANCE est défini pour la branche 4.3.x et la branche trunk, mais pas dans les branches plus anciennes comme 4.2.x. Cependant, j'utilise bien 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, sur la base des fichiers JAR des dépendances Maven qui se trouvent dans mon projet, j'utilise effectivement 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é divers autres SOF et articles de blog sur ce problème, tels que Mashape Unirest Java: Java.lang.NoClassDefFoundError and cet article de blog aussi) , mais ils semblent tous parler de la résolution du problème NoSuchFieldError pour Android. Cependant, j'ai affaire à une application autonome Java, pas à une application Android.

Je n'arrive pas à déterminer comment résoudre ce problème. Quelqu'un a une idée de ce que je dois faire?

MISE À JOUR

Au lieu de montrer mon cas de test, je vais réduire l'illustration d'une reproduction de ce problème à une simple application à une ligne Java application, car le problème existe avec n'importe quel Java application ou scénario de test exécuté via Eclipse, pas seulement un test particulier:

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

Normalement, cela devrait imprimer le code HTML de la page d'accueil de Google, mais j'obtiens à la place la trace de la pile NoSuchFieldError.


FIXÉ!

Le problème était que le AWS SDK (il est sur mon chemin de classe parce que je développe pour Elastic Beanstalk) 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 devoir réorganiser mon chemin de classe pour qu'AWS SDK ne soit plus en conflit.

36
ecbrodie

La seule explication plausible à ce problème est qu'il existe une ancienne version de HttpCore sur le chemin de classe (sauf si vous souhaitez également envisager la possibilité que des hommes verts de Mars jouent à distance avec votre ordinateur à partir d'une soucoupe volante).

Vous pouvez ajouter cet extrait à votre code pour découvrir de quel pot la classe est récupérée. Cela pourrait aider à découvrir pourquoi ce pot 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);

Cela me dit essentiellement que dans mon cas, le pot réside dans le référentiel maven local et a probablement été ajouté au chemin de classe 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
95
ok2c

Comme déjà mentionné par les commentaires précédents, c'est principalement à cause des versions conflictuelles de httpcore jar, le champ statique INSTANCE a été ajouté à la classe BasicLineFormatter dans versions > 4.3.1, Bien que vous ayez peut-être ajouté la dernière version du pot httpcore dans vos dépendances, mais il est fort possible qu'une autre version (inférieure) du pot soit récupérée.

Donc, d'abord pour confirmer que le mauvais pot est récupéré, 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 s'imprime, la version inférieure du pot, il est confirmé qu'il choisit la version inférieure du pot httpcore (peut provenir d'autres dépendances de votre projet),

Solution -

Ajoutez les dépendances maven/gradle suivantes en haut de la liste des dépendances (ou au-dessus des autres dépendances du projet qui ont provoqué 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
Anand Immannavar

J'ai fait face à la même exception en utilisant 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é que c'était dû à DefaultConnectionKeepAliveStrategy.INSTANCE; et le pot en conflit était Apache-httpcomponents-httpclient.jar dans mon chemin de classe. Ajout de ce message pour aider toute personne confrontée à une exception similaire

4
Nivedita Dixit

J'ai obtenu cette exception: Caused by: Java.lang.NoSuchFieldError: INSTANCE

Solution:

Cela se produit si vous avez deux classes de version différentes dans votre chemin de classe…. […], Donc je trouve d'abord cette classe (une version de classe), cliquez sur cette classe, sélectionnez chemin de génération, puis je clique sur supprimer du chemin de génération.

1
vijay m p

si vous utilisez aws sdk, cette erreur se produit en raison d'une incompatibilité de dépendance. Pour éviter cette erreur, procédez comme suit: 1.Placez les dépendances dans l'ordre requis aws sdk et la fin de préférence 2.Ajoutez le plugin d'ombre au projet

Cela a résolu mon problème

0
SamsonFrancis