arquillian-core
arquillian-core copied to clipboard
Linkage error with arquillian-junit.jar
Hi,
We are trying to test our WAR file using Arquillian and restassured; everything was fine until we upgraded to arquillian-tomcat-embedded-7 1.0.0.CR7 with Tomcat 7.0.55 (from 1.0.0.CR5 with 7.0.47). Now, whenever we try to execute a restassured method whose signature contains a hamcrest Matcher, we are getting a linkage error like this:
java.lang.LinkageError: loader constraint violation: when resolving interface method "com.jayway.restassured.specification.ResponseSpecification.statusCode(Lorg/hamcrest/Matcher;)Lcom/jayway/restassured/specification/ResponseSpecification;" the class loader (instance of org/apache/catalina/loader/WebappClassLoader) of the current class, com/wibble/web/resources/HealthResourceBeanIT, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for resolved class, com/jayway/restassured/specification/ResponseSpecification, have different Class objects for the type cification.statusCode(Lorg/hamcrest/Matcher;)Lcom/jayway/restassured/specification/ResponseSpecification; used in the signature at com.wibble.web.resources.HealthResourceBeanIT.getMessage(HealthResourceBeanIT.java:22)
This problem only happens with arquillian-junit-container. Switching the project to use TestNG and the arquillian-testng-container fixes everything.
My other solution is to create my own local version of org.jboss.arquillian.junit.container.JUnitDeploymentAppender.java that does not include "org.hamcrest".
Both of these solutions suggest that arquillian-junit.jar must not contain its own copy of the hamcrest classes.
Could you provide your pom.xml ?
I doubt the pom.xml will be particularly useful because it is a module in a much larger project:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>wibble-server</artifactId>
<groupId>wibble.studio</groupId>
<version>1.0.4-SNAPSHOT</version>
</parent>
<groupId>wibble.studio</groupId>
<artifactId>wibble-server-web</artifactId>
<packaging>war</packaging>
<name>wibble-studio: Server: Web</name>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<hamcrest.version>1.3</hamcrest.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>1.1.6.Final</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<version>3.0.9.Final</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>wibble.studio</groupId>
<artifactId>wibble-studio-api-rest</artifactId>
<exclusions>
<exclusion>
<groupId>com.twitter</groupId>
<artifactId>finagle-core_2.9.2</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>wibble.gateway</groupId>
<artifactId>gateway-api-remote-finagle6</artifactId>
<exclusions>
<exclusion>
<groupId>com.twitter</groupId>
<artifactId>finagle-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.twitter</groupId>
<artifactId>finagle-http</artifactId>
</exclusion>
<exclusion>
<groupId>com.twitter</groupId>
<artifactId>finagle-serversets</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>wibble.genesis</groupId>
<artifactId>genesis-remote</artifactId>
<version>1.0.21</version>
<type>jar</type>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-cdi</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>async-http-servlet-3.0</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-fastinfoset-provider</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<dependency>
<!-- This provides the SLF4J bindings -->
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- inject version info into responses -->
<dependency>
<groupId>wibble.commons.monitor</groupId>
<artifactId>monitor-app-version-filter</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>wibble.commons.metrics</groupId>
<artifactId>metrics-librato-servlet</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>wibble.metrics</groupId>
<artifactId>wibble-standard-metrics</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>wibble.metrics</groupId>
<artifactId>aws-sdk-metrics</artifactId>
<version>1.1.0</version>
<exclusions>
<exclusion>
<groupId>com.twitter</groupId>
<artifactId>finagle-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>wibble.ms.auth</groupId>
<artifactId>ms-auth</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<!-- CDI and WELD -->
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet-core</artifactId>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>org.jboss.spec.javax.el</groupId>
<artifactId>jboss-el-api_3.0_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.jboss.spec.javax.el</groupId>
<artifactId>jboss-el-api_3.0_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>wibble.studio</groupId>
<artifactId>wibble-studio-api-schema</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
</dependency>
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.1.2</version>
</dependency>
<!-- Trace logging -->
<dependency>
<groupId>com.omnifone.trace</groupId>
<artifactId>trace-logback</artifactId>
<exclusions>
<exclusion>
<groupId>com.twitter</groupId>
<artifactId>finagle-core_2.9.2</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.omnifone.trace</groupId>
<artifactId>trace-servlet</artifactId>
<exclusions>
<exclusion>
<groupId>com.twitter</groupId>
<artifactId>finagle-core_2.9.2</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>wibble.trace</groupId>
<artifactId>trace-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>com.twitter</groupId>
<artifactId>finagle-core_2.9.2</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Start rest-assured deps -->
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>1.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>json-path</artifactId>
<version>1.8.1</version>
<scope>test</scope>
</dependency>
<!-- End rest-assured -->
<!-- Start arquillian testing -->
<dependency>
<groupId>org.jboss.shrinkwrap.resolver</groupId>
<artifactId>shrinkwrap-resolver-api</artifactId>
<scope>test</scope>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.jboss.shrinkwrap.resolver</groupId>
<artifactId>shrinkwrap-resolver-impl-maven</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-tomcat-embedded-7</artifactId>
<version>1.0.0.CR7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>${tomcat.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>${tomcat.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jdt.core.compiler</groupId>
<artifactId>ecj</artifactId>
<version>4.2.2</version>
<scope>test</scope>
</dependency>
<!-- End Arquillian testing deps -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.6.3.201306030806</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
<showWarnings>true</showWarnings>
<optimize>true</optimize>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>6.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertiesFile>src/test/resources/arquillian.properties</systemPropertiesFile>
<classpathDependencyExcludes>
<classpathDependencyExcludes>org.jboss.resteasy:resteasy-cdi</classpathDependencyExcludes>
</classpathDependencyExcludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<systemPropertiesFile>src/test/resources/arquillian.properties</systemPropertiesFile>
<classpathDependencyExcludes>
<classpathDependencyExcludes>org.jboss.resteasy:resteasy-cdi</classpathDependencyExcludes>
</classpathDependencyExcludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
There's a higher-level dependencyManagement section that declares the following versions: org.mockito:mockito-core:1.9.5 junit:junit:4.12 org.apache.httpcomponents:httpclient:4.2.6 org.apache.httpmime:4.2.6 org.apache.tomcat:tomcat-servlet-api:7.0.55 org.apache.tomcat:tomcat-el-api:7.0.55 org.jboss.weld.servlet:weld-servlet-core:2.1.2.Final org.jboss.weld:weld-core:2.1.2.Final
Other Tomcat and RESTeasy artifacts are consistent at 7.0.55 and 3.0.9.Final respectively.
I've written a tiny Maven project which reproduces this issue: raised as ARQ-1944.
I ran into this error using arquillian-tomcat-embedded with Tomcat 7.0.52 and 8.0.28. It appears that a change was made to the which classloader is used by default for Tomcat versions after 7.5.0:
https://bz.apache.org/bugzilla/show_bug.cgi?id=55943 https://tomcat.apache.org/tomcat-7.0-doc/changelog.html#Tomcat 7.0.51 (violetagg) https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html#Class_Loader_Definitions
I was able to successfully work around the issue by adding the following line to context.xml: <Loader delegate="true"/>
Alternatively, if your tests are only running as a client against an embedded Tomcat then you can also work around this by not including the Arquillian JARs in your deployment in the first place.
@Deployment(testable = false)
will achieve this, and then you annotate your test classes as @RunAsClient
.