38

I have a Maven Java project that uses Mashape Unirest for sending HTTP requests to other URLs. I am currently writing an integration test (using TestNG) that sends a normal HTTP request using Unirest. When I run the integration test through Maven (via the Failsafe plugin), the request is sent out successfully. However, when I try to run the integration test via Eclipse, I keep on getting the following error:

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

I am also able to reproduce this error using a basic Java application script.

I have made sure that the dependencies I am using in my pom.xml file are the latest and greatest, as seen below:

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

I have also checked out the source code of BasicLineFormatter.java, both from the source file downloaded to Eclipse and from Apache's Httpcore Github repo. In the Github repo, notice how the INSTANCE field is defined for the 4.3.x branch and the trunk branch, but not in older branches like 4.2.x. However, I am indeed using version 4.3.2 in my project, so I should be using a JAR file for Httpcore that has the latest version of BasicLineFormatter. I know that, based on the Maven Dependencies JAR files that are in my project, that I am indeed using the latest versions of these Apache dependencies, not the older versions specified as downstream dependencies of my project.

I have checked other various SOF and blog posts about this issue, such as Mashape Unirest Java : java.lang.NoClassDefFoundError and this blog post too, but they all seem to be talking about solving the NoSuchFieldError problem for Android. However, I'm dealing with a standalone Java application, not an Android application.

I am at a loss in determining how to troubleshoot this issue. Anyone have any idea what I need to do?

UPDATE

Instead of showing my test case, I will reduce the illustration of a reproduction of this problem to just a simple one-liner Java application, because the problem exists with any Java application or test case run through Eclipse, not just one particular test:

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

Normally, this should print the HTML of the Google home page, but I instead get the NoSuchFieldError stack trace.


FIXED!

The problem was that the AWS SDK (it's on my classpath because I'm developing for Elastic Beanstalk) had a conflicting JAR file. Using Oleg's solution (thanks BTW), I printed the following output in a 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

I'll have to rearrange my classpath so that AWS SDK is no longer conflicting.

Community
  • 1
  • 1
ecbrodie
  • 11,246
  • 21
  • 71
  • 120
  • Could you also provide your Java test class? – Peter Keller Feb 18 '14 at 20:51
  • In my experience NoSuchFieldError usually means that you compiled with one version of a library/jarfile, but are executing against another which has revised that class. If you moved from one environment to another, check that your libraries were at the same levels (you may need to drag private copies of them with you and play classloader ordering games), and/or rebuild against the version the new environment provides. – keshlam Feb 18 '14 at 21:35
  • Thank you for the comment, but no, that is not the case with my project because it is a completely brand new project, not copied over from another location. And I have no `lib/` folder at all in the project with any jars because it is an Eclipse Maven project, so jars are pulled in from my local `~/.m2` repo. In fact, I already tried clearing the repo for `org.apache.httpcomponents` and redownloading, to no avail. – ecbrodie Feb 18 '14 at 21:38
  • 2
    Did [this workaround](https://github.com/Mashape/unirest-java/issues/15) help? [liutingdu](https://github.com/liutingdu) reported she was able to workaround the the issue "by relocating package org.apache.http using Maven shade plugin." – Ingo Feb 18 '14 at 21:56
  • There has to be a better way than the Shade plugin. I can try it, still would like to hear back from other people. – ecbrodie Feb 18 '14 at 22:13
  • Thank you for the "FIXED!" section .. an AWS SDK conflict was the cause of that error for me too. If you had posted that as an answer to your own question, I would've up-voted it. – RichW Jun 11 '15 at 16:55
  • You're welcome. There was no need to post that as the answer because it had already been done. See the accepted answer. – ecbrodie Jun 12 '15 at 00:02
  • @ecbrodie How did you know BasicLineFormatter.java was the culprit? I had this issue and your solution helped me but nothing in the error logs or stack trace mentioned this class but it was indeed the source of the issue. How did you identify BasicLineFormatter? – Usman Mutawakil Mar 01 '16 at 14:44
  • @UsmanMutawakil have you seen the accepted answer yet? If I remember correctly (it was a long while ago and I am no longer a part of that project), the outlined solution was exactly what I did. – ecbrodie Mar 02 '16 at 04:16

6 Answers6

101

The only plausible explanation to this problem is there is an older version of HttpCore on the classpath (unless you also want to consider a possibility of green men from Mars messing with your computer remotely from a flying saucer).

You can add this snippet to your code to find out what jar the class gets picked up from. This might help find out why that jar is on your classpath in the first place.

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

This basically tells me that in my case the jar resides in the local maven repository and likely to have been added to the classpath by 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
ok2c
  • 26,450
  • 5
  • 63
  • 71
  • 11
    This answer is GENIUS! – ecbrodie Feb 19 '14 at 15:42
  • 1
    I second that wholeheartedly! After a long 3 days of trying to figure out a similar case, I revisited this and it was this method that led me to find the problem jars. – arthur.e.anderson Nov 20 '14 at 21:01
  • 1
    @oleg I'm getting a null as resource here, any idea of what could be an issue to this? I've added http core and client to my libs folder of the project. – mathletics Apr 20 '15 at 12:01
  • Just wondering how is this possible that DefaultHttpRequestWriterFactory is coming from 4.3.# but BasicLineFormatter is coming from another, older jar? These 2 classes are in the same distribution jar right (httpcore). – Kirill G. Nov 17 '15 at 08:50
  • My code was using httpcore 4.1.2. When i updated to 4.4.1, things worked fine. – Sacky San Aug 07 '17 at 03:28
  • 2
    Why would System.out.println(resource) return null? – Robs Nov 23 '17 at 19:04
  • I am getting the same error while trying to access upload file to Aws S3 and trying to use oleg's code gives me "jar:file:/C:/Users/<>/IdeaProjects/es_sql/lib/truezip-samples-7.7.3-jar-with-dependencies.jar!/org/apache/http/message/BasicLineFormatter.class" I am confused how truezip-samples is used in aws s3. – user3115056 Jul 29 '19 at 21:53
7

As already mentioned by previous comments, It's mainly because of the conflicting versions of httpcore jar, the static field INSTANCE is been added to BasicLineFormatter class in versions > 4.3.1, Though you might have added the latest version of the httpcore jar in your dependencies, but its highly possible that other (lower) version of jar is getting picked up.

So, first to confirm that, wrong jar is getting picked up, Use the following line of code -

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

If this prints, the lower version of the jar, then it's confirmed that it's picking the lower version of the httpcore jar (May be from other dependencies of your project),

Solution -

Add following maven/gradle dependencies at the top of dependency list (Or above the other project dependency which caused the conflict) -

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

I faced the same exception using 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)

And found it was due to DefaultConnectionKeepAliveStrategy.INSTANCE; and the conflicting jar was apache-httpcomponents-httpclient.jar in my classpath. Adding this post to help anyone who faces similar exception

Rizier123
  • 58,877
  • 16
  • 101
  • 156
Nivedita Dixit
  • 181
  • 1
  • 3
  • 12
1

I got this Exception: Caused by: java.lang.NoSuchFieldError: INSTANCE

Solution:

This happens if you have two different version classes in your classpath…. […], So I first find that class (one version of class), click that class, select build path, then I click remove from build path.

enb081
  • 3,831
  • 11
  • 43
  • 66
vijay m p
  • 101
  • 1
  • 3
0

if you are using aws sdk this error occurs because of dependency mismatch. To avoid this error do the following: 1.Put the dependecies in the required order aws sdk and the end preferably 2.Add shade plugin to the project

This solved my problem

  • Another reason for this exception is dependency version. By default the maven build tools or jdk takes the lowest version of the dependency. Therefore you need remove the outdated version of the dependency. – SamsonFrancis Mar 13 '17 at 13:03
0

you can refer to my answer in
HTTPClient Example - Exception in thread "main" java.lang.NoSuchFieldError: INSTANCE


my case is i have httpclient-4.4.1.jar, and httpcore-4.4.1.jar in my class path,
but JVM loaded BasicLineFormatter from httpcore-4.0.jar

Maxwell Cheng
  • 1,050
  • 10
  • 17