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

3

5

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.

Maciemaciel answered 4/4, 2011 at 12:38 Comment(4)
Do you need load time weaving for the integration test?Illsorted
Googling around it seems like MAVEN_OPTS is the the way to go and you need to make sure there are no spaces in your path to the jar.Illsorted
Like I wrote, I did google around a lot and I also found MAVEN_OPTS, nevertheless, no solution worked, no spaces in the path.Maciemaciel
about do I need load time weaving for the integration test, actually I am not 100% sure. In our app we use it for annotation support and transactions, so I am thinking yes.Maciemaciel
P
4

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.

Perique answered 24/10, 2012 at 18:13 Comment(0)
D
3

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.

Domesday answered 18/9, 2011 at 15:7 Comment(0)
R
0

I have issues too with Jetty.

If you are like me using Tomcat without problem for developpement i would advice you to stick to tomcat to automatic tests them.
Example of using Jetty on different tutorials works great because their sample app. is over simple (hello world jsp...).

For real world application the configuration of jetty is more complicated and the benefits of using it are gone with that.

Jetty requires others configuration than with the one with Tomcat.
So it is a pain in .. to maintain this and i found no value with their poor documentation.

I'm using right now a local tomcat with cargo : start it launch them, stop tomcat. You dont need to learn jetty stuff just reuse your actual tomcat configuration.
The only prerequirement is to have tomcat already installed on your machin and a environment variable pointing to it.

You can even skip that and download it automatically the first time with a cargo configuration.

Ruhl answered 18/9, 2011 at 11:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.