Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configuring Integration Tests using Spring/Jetty (or Tomcat)/Maven for REST tests

I would like to test our REST service with HTTP requests (kinda blackbox testing). However, after a couple of hours googling and trying different configs, I am still not able to start Jetty correctly. Here is the my current configuration (I tried multiple different versions):

pom.xml

        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.8</version>
            <configuration>
                <junitArtifactName>junit:junit</junitArtifactName>
                <excludes>
                    <exclude>**/*_Roo_*</exclude>
                    <exclude>**/*Util*</exclude>
                    <exclude>**/*IT*</exclude>
                </excludes>
                <forkMode>once</forkMode>
                <argLine>-javaagent:'${settings.localRepository}/org/springframework/spring-instrument/${org.springframework-version}/spring-instrument-${org.springframework-version}.jar' -javaagent:'${settings.localRepository}/org/aspectj/aspectjweaver/${org.aspectj-version}/aspectjweaver-${org.aspectj-version}.jar'</argLine>
                <useSystemClassLoader>true</useSystemClassLoader> 
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>2.8</version>
            <configuration>
                <forkMode>once</forkMode>
                <argLine>-javaagent:'${settings.localRepository}/org/springframework/spring-instrument/${org.springframework-version}/spring-instrument-${org.springframework-version}.jar' -javaagent:'${settings.localRepository}/org/aspectj/aspectjweaver/${org.aspectj-version}/aspectjweaver-${org.aspectj-version}.jar'</argLine>
                <useSystemClassLoader>false</useSystemClassLoader>
            </configuration>
            <executions>
                <execution>
                    <id>integration-test</id>
                    <goals>
                        <goal>integration-test</goal>
                    </goals>
                </execution>
                <execution>
                    <id>verify</id>
                    <goals>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>  
            <groupId>org.mortbay.jetty</groupId>  
            <artifactId>maven-jetty-plugin</artifactId>  
            <version>6.1.10</version>  
            <configuration>  
                <scanintervalseconds>10</scanintervalseconds>  
                <stopkey>foo</stopkey>  
                <stopport>9999</stopport>  
                <contextpath>/${project.artifactId}</contextpath>  
                <connectors>  
                    <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">  
                        <port>9090</port>  
                    </connector>  
                </connectors>  
            </configuration>  
            <executions>  
                <execution>  
                    <id>start-jetty</id>  
                    <phase>pre-integration-test</phase>  
                    <goals>  
                        <goal>run</goal>  
                    </goals>  
                    <configuration>  
                        <scanintervalseconds>0</scanintervalseconds>  
                        <daemon>true</daemon>  
                    </configuration>  
                </execution>  
                <execution>  
                    <id>stop-jetty</id>  
                    <phase>post-integration-test</phase>  
                    <goals>  
                        <goal>stop</goal>  
                    </goals>  
                </execution>  
            </executions>  
        </plugin>
        ...

orm.xml

<!-- <context:load-time-weaver/> -->
<context:load-time-weaver weaver-class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
<context:spring-configured/>
<context:annotation-config />
<context:component-scan base-package="com.example.jump.domain">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
    <tx:annotation-driven transaction-manager="transactionManager" />

Right now, I am getting the exception:

  • java.lang.IllegalStateException: ClassLoader [org.mortbay.jetty.webapp.WebAppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar

I understand the exception, but I wasn't able to fix it. I also tried a couple of other approaches, like giving the javaagent via MAVEN_OPTS or trying to set VM args to Jetty. The problem is Google gives back a bunch of 'solutions' for different versions and none was working.

I am currently pretty frustrated that a common scenario like doing REST services tests, is so hard to achieve in Spring. So if you are clever enough to find the right configuration, please share it with me in a way that even a monkey could configure it and I promise if we ever met the beers are on me.

Here are the versions I use:

<properties>
    <java-version>1.6</java-version>
    <org.springframework-version>3.0.5.RELEASE</org.springframework-version>
    <org.aspectj-version>1.6.9</org.aspectj-version>
    <org.slf4j-version>1.5.10</org.slf4j-version>
    <redis.version>1.0.0.BUILD-SNAPSHOT</redis.version>
    <org.jboss.hibernate.version>3.6.0.Final</org.jboss.hibernate.version>
    <net.sf.ehcache.version>2.3.1</net.sf.ehcache.version>
</properties>

Maven 2.21

I happily provide more information if needed. Like I said every help appreciated.

like image 575
hjuskewycz Avatar asked Apr 04 '11 12:04

hjuskewycz


2 Answers

The jetty-maven-plugin now supports the run-forked goal, where you can pass JVM arguments. Much easier than tomcat with cargo or MAVEN_OPTS.

like image 122
Bob Fields Avatar answered Oct 06 '22 11:10

Bob Fields


This isn't really related to ReST services, and it's only incidentally related to Spring. Your problem is centered around AspectJ and enabling load-time weaving in the JVM. You say that you understand the exception, but I'm not sure you do. Have you read the section on Load-time weaving with AspectJ in the Spring reference? Pay particular attention to the environment-specific configuration. The problem is that Jetty's ClassLoader implementation doesn't support class transformation, and I'm not aware of any alternatives that do, so the only option left is to use the agent. Ideally, this would be a configuration option on the Maven Jetty plugin, but to my knowledge, it still doesn't have the ability to spawn a new JVM for the Jetty server, which is unfortunate. Therefore, since Jetty is running in the same JVM as Maven, you have to specify the agent there. You say you've already done that, but you must be missing something. I've posted an executable example on github. You can take a look at the source code or clone and run the example with:

git clone git://github.com/zzantozz/testbed.git tmp
export MAVEN_OPTS=-javaagent:org.springframework.instrument-3.0.5.RELEASE.jar
cd tmp/spring-aspectj-load-time-weaving-in-jetty
mvn jetty:run

Then visit http://localhost:8080/spring-aspectj-load-time-weaving-in-jetty/ to see it work. Incidentally, this isn't really related to ReST services, and it's only incidentally related to Spring.

like image 43
Ryan Stewart Avatar answered Oct 06 '22 13:10

Ryan Stewart