简体   繁体   中英

JBoss7: loader constraint violation with ReastEasy and httpclient with custom HttpRequestInterceptor

I'm using the RestEasy Client Framework in a @Named @ViewScoped Bean with JBoss-7.1.1-Final to retrieve data from a REST service with a custom HttpRequestInterceptor :

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

This works fine in a standalone client application (also ok when I remove the ClientExecutor , but I need it to authenticate REST service). The bean is in a WAR module inside an EAR , the dependency hierarchy of resteasy resolves to the following:

Resteasy依赖

There are no httpclient or httpcore in the WAR or EAR . Inside the Bean I get the following exception:

java.lang.NoClassDefFoundError: org/apache/http/HttpRequestInterceptor

Seems to be easy (although I'm wondering about the resteasy packaging) and I added org.apache.httpcomponents:httpclient with compile scope:

在此输入图像描述

No I'm getting he following exception:

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)

Update To reproduce this you don't need REST interfaces, the error occurs while instantiating the ApacheHttpClient4Executor , but you may need the custom 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());

  }
}

To avoid the linkage error when deploying the application on JBoss, configure module org.apache.httpcomponents within the modules folder of the JBoss installation, but avoid including the JARs from HttpComponents with your application:

  1. Place the required JARs from HttpComponents in modules/org/apache/httpcomponents/main .
  2. List these JARs in module.xml within this directory.
  3. Add Dependencies: org.apache.httpcomponents to the MANIFEST.MF of your component.

Note that the module referred to in step 1 and 2 already exists. You may however want to include additional JARS (eg httpclient-cache-xyzjar ) or different versions.

Resolving classes within your development environment is another matter of course.

I had the same problem in similar circumstances. The HttpComponents module required was already in my JBoss (AS 7.1.1) modules directory. Therefore, all I had to do to resolve the issue was to add a manifest entry as described by Eustachius, which in Maven you can do like so:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifestEntries>
                        <Dependencies>org.apache.httpcomponents</Dependencies>
                    </manifestEntries>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

The configuration is the same for the maven-war-plugin.

If a module is needed in an Arquillian test...

Create arquillian-manifest.mf in src/test/resources with the following:

Manifest-Version: 1.0
Dependencies: org.jboss.resteasy.resteasy-jaxrs,org.apache.httpcomponents

Then when you ShrinkWrap:

WebArchive war = ShrinkWrap.create...
    .addAsManifestResource("arquillian-manifest.mf", "MANIFEST.MF")

But Add Dependencies: org.apache.httpcomponents to the MANIFEST.MF of your component.

causing an exception - Caused by: java.lang.IllegalStateException: JBAS014744: No META-INF/services/org.jboss.as.controller.Extension found for org.apache.httpcomponents:main at 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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM