java gradle apache-httpclient-4.x

java - NoSuchFieldError INSTANCE en org.apache.http.impl.io.DefaultHttpRequestWriterFactory



gradle apache-httpclient-4.x (5)

java version "1.7.0_71" Gradle 2.1

Hola,

UPDATE:

Las dependencias

gradle dependencies | grep httpcore | +--- org.apache.httpcomponents:httpcore:4.3.3 | +--- org.apache.httpcomponents:httpcore:4.3.3 | +--- org.apache.httpcomponents:httpcore:4.3.3 | +--- org.apache.httpcomponents:httpcore:4.3.3 | | | | | +--- org.apache.httpcomponents:httpcore:4.1 -> 4.3.3 | +--- org.apache.httpcomponents:httpcore:4.3.3 | | | | | +--- org.apache.httpcomponents:httpcore:4.1 -> 4.3.3

¿Esto significa que tengo 4.1 que es un enlace suave a 4.3.3? Parece extraño, ya que cuando imprimo lo que carga el cargador de clases, parece cargar 4.3.3: /home/steve/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.3.3/f91b7a4aadc5cf486df6e4634748d7dd7a73f06d/httpcore-4.3.3.jar parece muy extraño.

Sigo recibiendo este error cuando intento ejecutar mi httpClient. Todo compila bien

java.lang.NoSuchFieldError: INSTANCE at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:52

Mi código es muy simple, eliminó el código no importante para mantenerlo pequeño:

public class GenieClient { private CloseableHttpClient mClient; public GenieClient() { ClassLoader classLoader = GenieClient.class.getClassLoader(); URL resource = classLoader.getResource("org/apache/http/message/BasicLineFormatter.class"); log.log(Level.INFO, "resource: " + resource); mClient = HttpClientBuilder.create().build(); } public int sendRequest() { int responseCode = -1; try { HttpResponse response = mClient.execute(new HttpPost("http://www.google.com")); responseCode = response.getStatusLine().getStatusCode(); } catch(IOException ex) { log.log(Level.SEVERE, "IOException: " + ex.getMessage()); } return responseCode; } }

El resultado que obtengo del classLoader es este:

INFO: resource: jar:file:/home/steve/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.3.3/f91b7a4aadc5cf486df6e4634748d7dd7a73f06d/httpcore-4.3.3.jar!/org/apache/http/message/BasicLineFormatter.class

Estoy usando gradle como mi herramienta de compilación y he configurado las dependencias de este modo en mi archivo build.gradle :

dependencies { compile ''org.apache.httpcomponents:httpclient:4.3.6'' }

También intenté incluir el siguiente httpcore, pero sigo teniendo el mismo error:

compile ''org.apache.httpcomponents:httpcore:4.4''

Todo se construye bien, es solo cuando ejecuto mi httpClient,

Muchas gracias por las sugerencias,


Parece que BasicLineFormatter obtuvo su INSTANCE in 4.3-beta1 estática INSTANCE in 4.3-beta1 enlace y enlace INSTANCE in 4.3-beta1


org.apache.httpcomponents:httpcore:4.1 -> 4.3.3 means 4.1 es la versión solicitada, que se resuelve en 4.3.3 por resolución de conflictos. Ejecutando algo como gradle -q dependencyInsight --configuration compile --dependency httpcore debería darle más información sobre esto.

Debería verificar el resultado de compilación y ver qué jarras están realmente empaquetados con su aplicación. Además, al usar un administrador de archivos, ejecute una búsqueda de BasicLineFormatter.class través de la salida de compilación (incluidos los archivos, por supuesto), esto debería darle una respuesta definitiva sobre qué jarrones contienen qué versión de esta clase.

Si solo hay una versión (4.3.3), esto debe significar que la otra versión proviene del contenedor que ejecuta su aplicación. Las formas de resolver esto dependen del contenedor.

Si encuentra varias versiones, puede intentar excluir la dependencia transitiva de httpcore globalmente en el proyecto (capítulo 51.4.7 de la guía del usuario ).

Si define una exclusión para una configuración particular, la dependencia transitiva excluida se filtrará para todas las dependencias al resolver esta configuración o cualquier configuración heredada.


Comience su jvm con -verbose: class, le mostrará qué clase se está cargando desde dónde.

Tuve tales problemas en el pasado en dos escenarios:

  1. uno de los archivos jar que está cargando tiene un manifiesto con una cláusula Classpath que hace referencia a la versión incorrecta de httpcore.

  2. se está ejecutando dentro de algún contenedor (tomcat o sth) con los cargadores de clase propios y algunas clases se cargan, por ejemplo, en el contenedor de un contenedor diferente.

Tampoco creo que el código que muestra el recurso para la clase funcione, ya que utiliza explícitamente el cargador de clases de GenieClient. Probablemente usar BasicLineFormatter.class.getClassloader() daría resultados diferentes. Pero mejor intente con -verbose:class .


  1. encontrar httpcore que es de una versión anterior a 4.3
  2. elimine la versión anterior del jar de httpcore de las Bibliotecas referenciadas.

Claramente, hay alguna versión anterior de BasicLineFormatter en su classpath, una que tiene el campo DEFAULT lugar de INSTANCE . Ver por ej .

Pero su cargador de clases informa que está usando httpcore-4.3.3, y su árbol de dependencias de Gradle lo respalda.

Parece que tiene otro JAR que tiene una versión anterior de BasicLineFormatter . Es posible que deba revisar sus JAR de dependencia y simplemente verifique si están allí. Pruebe un jar tf *.jar | grep ''BasicLineFormatter'' jar tf *.jar | grep ''BasicLineFormatter'' para ver qué JAR pueden estar involucrados.

Además, esto puede ser relevante. Miré tus etiquetas y parece que haces algo de desarrollo de Android. Por lo tanto, la siguiente pregunta sobre desbordamiento de pila puede ser de interés:

Incluso si ese no es el problema exacto, muestra cómo puede tener un viejo BasicLineFormatter incluso si tiene la dependencia correcta de httpcore.