2014-02-18 53 views
34

我有一个Maven Java项目,它使用Mashape Unirest向其他URL发送HTTP请求。我目前正在写一个集成测试(使用TestNG的)发送使用Unirest一个正常的HTTP请求。当我通过Maven(通过Failsafe插件)运行集成测试时,请求被成功发送出去。然而,当我尝试运行通过Eclipse的集成测试,我不断收到以下错误:java.lang.NoSuchFieldError:org.apache.http.message.BasicLineFormatter.INSTANCE来自Mashape Unirest Java应用程序

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应用程序脚本此错误。

我已经确信,我用我的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's Httpcore Github repo。在Github上回购,请注意如何INSTANCE场的版本4.3.x分支和主干分支像4.2.x.老枝定义,但不不过,我确实在我的项目中使用的版本4.3.2,所以我应该使用的HttpCore JAR文件具有最新版本的BasicLineFormatter。我知道,基于我项目中的Maven Dependencies JAR文件,我确实在使用这些Apache依赖项的最新版本,而不是指定为我的项目的下游依赖项的旧版本。

我也查了一下这个问题,其他的各种SOF和博客文章,如Mashape Unirest Java : java.lang.NoClassDefFoundErrorthis blog post too,但他们似乎都在谈论解决NoSuchFieldError问题的的Android。但是,我正在处理独立的Java应用程序,而不是Android应用程序。

我在确定如何解决此问题方面处于困境。任何人都知道我需要做什么?

UPDATE

而不是显示我的测试情况下,我会减少这个问题,只是一个简单的一行Java应用程序的再现的例证,因为这个问题与任何Java应用程序或测试的情况下,通过运行存在Eclipse的,不只是一个特殊的测试:

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

通常情况下,这应该打印的谷歌主页的HTML,但我反而得到NoSuchFieldError堆栈跟踪。


固定!

的问题是,AWS SDK(它在我的类路径中,因为我开发弹性魔豆)有冲突的JAR文件。使用奥列格的解决方案(感谢BTW),我印在单元测试的输出如下:

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不再是相互矛盾的。

+0

是否也能提供您Java测试类? –

+0

请参阅我的更新。 – ecbrodie

+0

根据我的经验,NoSuchFieldError通常意味着您使用一个库/ jarfile版本进行编译,但是针对修改该类的另一个版本执行。如果您从一个环境迁移到另一个环境,请检查您的图书馆是否处于相同的级别(您可能需要拖动它们的私人副本并玩类加载器订购游戏),和/或根据新环境提供的版本进行重建。 – keshlam

回答

87

这个问题唯一合理的解释是类路径上有一个较旧版本的HttpCore(除非你也想考虑火星的绿人与飞碟从飞碟上遥相混淆的可能性)。

您可以将此代码段添加到您的代码中,以查明该类从哪个jar中获取。这可能有助于找出为什么那个jar放在你的classpath中。

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

这主要是告诉我,在我的情况罐子驻留在本地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 
+10

这个答案是天才! – ecbrodie

+1

我全身心投入!经过长达三天的试图找出类似的案例,我重新审视了这一点,正是这种方法导致我找到问题的瓶子。 –

+0

@oleg我在这里得到一个空的资源,任何想法可能是一个问题呢?我已经将http核心和客户端添加到项目的libs文件夹中。 – mathletics

2

我使用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。添加这篇文章,以帮助任何人谁面临着类似的异常

1

我得到这个异常:Caused by: java.lang.NoSuchFieldError: INSTANCE

解决方案:

出现这种情况,如果你在你的类路径中的两个不同版本的类...。 [...]所以我先找到那个班级(一个班级版本),点击那个班级,选择建立路径,然后我点击从建立路径删除。

+0

在我的情况下,这是问题,谢谢 –

5

由于已经由先前的评论中提到,这是因为该版本冲突httpcore罐子的为主,静态字段实例被添加到BasicLineFormatterversions > 4.3.1,虽然你可能在你的依赖增加了最新版本的httpcore罐子,但其他(较低)版本的jar很可能会被拾取。

所以,首先要确认的是,错误的罐子是越来越捞起,用下面的代码行 -

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

如果打印,罐子的较低版本,那么它的证实,它的采摘在罐子的HttpCore较低版本(可能是从项目的其他相关性),

解决方案 -

添加以下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> 
+0

哪个类应该是? – Robs

0

如果您正在使用AWS SDK这个错误的发生是因为依赖不匹配。 为了避免这种错误做到以下几点: 1.Put所需顺序AWS SDK的依赖条件和结束最好 2.增加遮阳插件项目

这解决了我的问题

+0

此异常的另一个原因是依赖版本。默认情况下,Maven构建工具或jdk采用最低版本的依赖关系。因此,您需要删除过时的依赖版本。 – SamsonFrancis