我在带有 JBoss-7.1.1-Final 的
@Named @ViewScoped
Bean 中使用 RestEasy 客户端框架,通过自定义 HttpRequestInterceptor
: 从 REST 服务检索数据
RegisterBuiltin.register(ResteasyProviderFactory.getInstance());
DefaultHttpClient httpClient = new DefaultHttpClient();
httpClient.addRequestInterceptor(new PreemptiveAuthInterceptor("test","test"), 0);
ClientExecutor clientExecutor = new ApacheHttpClient4Executor(httpClient); //<---
//The error occurs above, the code below is only for completeness
MyRest rest = ProxyFactory.create(MyRest.class,
"http://localhost:8080/rest",clientExecutor);
这在独立客户端应用程序中工作得很好(当我删除
ClientExecutor
时也可以,但我需要它来验证 REST 服务)。该 bean 位于 WAR
内的 EAR
模块中,resteasy 的依赖层次结构解析为以下内容:
httpclient
或httpcore
中没有WAR
或EAR
。在 Bean 内部,我遇到以下异常:
java.lang.NoClassDefFoundError: org/apache/http/HttpRequestInterceptor
似乎很容易(尽管我想知道resteasy包装),我添加了
org.apache.httpcomponents:httpclient
和compile范围:
不,我遇到了以下异常:
java.lang.LinkageError: loader constraint violation: when resolving method
"org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor.<init>
(Lorg/apache/http/client/HttpClient;)V"
the class loader (instance of org/jboss/modules/ModuleClassLoader)
of the current class, my/TestBean, and
the class loader (instance of org/jboss/modules/ModuleClassLoader)
for resolved class,
org/jboss/resteasy/client/core/executors/ApacheHttpClient4Executor,
have different Class objects for the type org/apache/http/client/HttpClient
used in the signature my.TestBean.init(TestBean.java:65)
更新 要重现此问题,您不需要 REST 接口,实例化
ApacheHttpClient4Executor
时会发生错误,但您可能需要自定义 PreemptiveAuthInterceptor
:
public class PreemptiveAuthInterceptor implements HttpRequestInterceptor
{
private String username;
private String password;
public PreemptiveAuthInterceptor(String username, String password)
{
this.username=username;
this.password=password;
}
@Override
public void process(org.apache.http.HttpRequest request, HttpContext context) throws HttpException, IOException
{
AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
authState.setAuthScope(org.apache.http.auth.AuthScope.ANY);
authState.setCredentials(new UsernamePasswordCredentials(username,password));
authState.setAuthScheme(new BasicScheme());
}
}
为了避免在 JBoss 上部署应用程序时发生链接错误,请在 JBoss 安装的模块文件夹中配置模块
org.apache.httpcomponents
,但避免将 HttpComponents 中的 JAR 包含在您的应用程序中:
modules/org/apache/httpcomponents/main
。module.xml
中列出这些 JAR。Dependencies: org.apache.httpcomponents
添加到组件的 MANIFEST.MF
。请注意,步骤 1 和 2 中引用的模块已经存在。但是,您可能想要包含其他 JARS(例如
httpclient-cache-x.y.z.jar
)或不同版本。
在您的开发环境中解决类是另一回事。
我在类似的情况下也遇到了同样的问题。所需的 HttpComponents 模块已位于我的 JBoss (AS 7.1.1) 模块目录中。因此,要解决这个问题,我所要做的就是按照 Eustachius 的描述添加一个清单条目,在 Maven 中你可以这样做:
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Dependencies>org.apache.httpcomponents</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
maven-war-plugin 的配置相同。
如果 Arquillian 测试中需要模块......
使用以下内容在 src/test/resources 中创建 arquillian-manifest.mf:
Manifest-Version: 1.0
Dependencies: org.jboss.resteasy.resteasy-jaxrs,org.apache.httpcomponents
然后当你ShrinkWrap时:
WebArchive war = ShrinkWrap.create...
.addAsManifestResource("arquillian-manifest.mf", "MANIFEST.MF")
但是将依赖项:org.apache.httpcomponents 添加到组件的 MANIFEST.MF 中。
导致异常 - 引起原因:java.lang.IllegalStateException:JBAS014744:找不到 org.apache.httpcomponents:main 的 META-INF/services/org.jboss.as.controller.Extension 在 org.jboss.as.controller.parsing.ExtensionXml.loadModule(ExtensionXml.java:191) [jboss-as-controller-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
最后我的最终方法:
resteasy-jaxrs
定义为 provided
依赖项,与 httpcomponents:httpclient
copy-dependency
和 jib
maven 插件将更高版本的 resteasy-jaxrs
jar 及其依赖项复制到 main
的 resteasy-jaxrs
插槽(要查找所需的其他 jar,请检查 module.xml
中的原始 main
)基础镜像/服务器的插槽,并根据需要进行升级;在 pom.xml
中将它们定义为 runtime
依赖项,因为您不需要它们进行编译,只需要复制 jar httpcomponents:httpclient
jar 执行相同操作(因为它是 resteasy-jaxrs
的隐式依赖)jib
插件,覆盖两个 modules.xml
插槽中的 main
以指向更高版本的 jar 文件名确保复制 jar 发生在 jib 构建镜像之前的 Maven 构建阶段。例如,
prepare-package
在 package
之前。
我的理论是,
resteasy-jaxrs
是JBoss EAP服务器的隐式依赖,它们的类加载器具有最高优先级,因此它们会首先加载他们想要的类,并且仅加载main
槽,然后再加载任何显式依赖/jboss-deployment-struct.xml 依赖项/其他。所以我唯一的办法就是改变main
插槽。