How to run embedded Tomcat 9 inside Maven 3 for integration testing purposes? - maven

I am trying to run embedded Tomcat 9 inside Maven 3 for integration testing purposes. I was led to cargo-maven2-plugin by other SO answers.
So, attempting to follow the instructions found here:
https://codehaus-cargo.github.io/cargo/Static+deployment+of+WAR.html
I have this fragment in a simple POM:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.7.6</version>
<configuration>
<container>
<containerId>tomcat9x</containerId>
<type>embedded</type>
</container>
<deployables>
<deployable>
<type>war</type>
<properties>
<file>path/to/myapp.war</file>
</properties>
</deployable>
</deployables>
</configuration>
</plugin>
</plugins>
</build>
Which I try to execute with mvn org.codehaus.cargo:cargo-maven2-plugin:run
It fails with the error:
[INFO] [en2.ContainerRunMojo] Resolved container artifact
org.codehaus.cargo:cargo-core-container-tomcat:jar:1.7.6 for container
tomcat9x [WARNING] The defined deployable has the same groupId and
artifactId as your project's main artifact but the type is different.
You've defined a [war] type wher eas the project's packaging is [pom].
This is possibly an error and as a consequence the plugin will try to
find this deployable in the project's dependencies.
How can I make this work? I just want to launch the given WAR in an embedded tomcat9, from within Maven.

After trying many permutations, this finally worked for me:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.7.9</version>
<configuration>
<container>
<systemProperties>
<myvar1>${myEnvVar}</myvar1>
<myvar2>... stuff ...</myvar2>
</systemProperties>
<containerId>tomcat9x</containerId>
<zipUrlInstaller>
<url>https://repo.maven.apache.org/maven2/org/apache/tomcat/tomcat/9.0.29/tomcat-9.0.29.zip</url>
</zipUrlInstaller>
</container>
<deployables>
<deployable>
<groupId>org.codehaus.cargo</groupId>
<artifactId>simple-war</artifactId>
<type>war</type>
<location>path/to/myapp.war</location>
<properties>
<context>myapp</context>
</properties>
</deployable>
</deployables>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-server</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</configuration>
</plugin>
Use the failsafe plugin to automatically run the Integration Tests between the start and stop:
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.21.0</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
</configuration>
</execution>
</executions>
</plugin>

Related

Executing cargo:run from a maven profile

I am trying to write a maven profile that will run the cargo:run goal and will Start a container and wait for the user to press CTRL + C to stop. However when I run mvn clean install -PstartApplication, the command completes successfully without waiting. What am I missing?
<profile>
<id>startApplication</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<wait>true</wait>
<container>
<containerId>tomcat7x</containerId>
<type>installed</type>
<home>${catalina.home}</home>
</container>
<configuration>
<type>standalone</type>
<home>${project.basedir}/target/tomcat7x</home>
</configuration>
<deployables>
<deployable>
<properties>
<context>ROOT</context>
</properties>
<groupId>com.demo.web</groupId>
<artifactId>sample-web-app</artifactId>
<type>war</type>
</deployable>
</deployables>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Check the plugin configuration: the executions element in the code you posted is within the configuration element, which is not correct and as such it will be ignored by Maven. (Check the official documentation for more details).
The executions section should be out of a configuration section (and at the same nested level). They could then also include a further configuration section, which will be the configuration used by that specific wrapping execution, while the previous would be a more generic configuration applied by default to all listed executions.
In this specific case, the Cargo Plugin also provides a further configuration element within the Maven configuration section, which makes things a bit confusing and misleading (a different name should have been chosen, in my opinion).
Hence, in your case, you should move out the executions section from the configuration section, as following:
<profile>
<id>startApplication</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<wait>true</wait>
<container>
<containerId>tomcat7x</containerId>
<type>installed</type>
<home>${catalina.home}</home>
</container>
<configuration>
<type>standalone</type>
<home>${project.basedir}/target/tomcat7x</home>
</configuration>
<deployables>
<deployable>
<properties>
<context>ROOT</context>
</properties>
<groupId>com.demo.web</groupId>
<artifactId>sample-web-app</artifactId>
<type>war</type>
</deployable>
</deployables>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>

Maven cargo in parent project with multiple submodules: tomcat port number is in use

I use maven cargo plugin and maven failsafe plugin to run my integration tests.
I have a parent project and two submodule projects:
IT-parent
--> IT-submodule1
--> IT-submodule2
My problem is Maven Cargo on parent project starts the tomcat, then also the submodules start and stop tomcat.
Parent pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.8.1</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.4.15</version>
<configuration>
<container>
<containerId>tomcat7x</containerId>
<type>installed</type>
<home>${CATALINA_HOME}</home>
</container>
<configuration>
<type>existing</type>
<home>${CATALINA_HOME}</home>
<properties>
<cargo.servlet.port>7080</cargo.servlet.port>
<cargo.tomcat.ajp.port>7009</cargo.tomcat.ajp.port>
<cargo.jvmargs>-Xms128m -Xmx512m -XX:MaxPermSize=256m</cargo.jvmargs>
</configuration>
<deployables>
...
</deployables>
</configuration>
<executions>
<!-- start server before integration tests -->
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deployer-deploy</goal>
<goal>start</goal>
</goals>
</execution>
<!-- stop server after integration tests -->
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>deployer-undeploy</goal>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Submodule pom.xml has no <build> section.
Is there a way to start tomcat with maven cargo once at parent project and submodules run only integration tests in that container. So I wouldn't have a series of start/stop tomcat equals to the number of submodules.
1.Parent pom.xml
Move maven-failsafe-plugin to plugin management:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.8.1</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
..
..
2.Parent pom.xml
+ IT-submodule1
+ IT-submodule2
Activate maven-failsafe-plugin in IT-submodule1 =>
Add declaration
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<plugin>
</plugins>

Tomcat-users.xml is rewritten on container restart - how do I supply credentials?

Im using cargo to deploy a war file to a tomcat server. I'm unable to login to the manager however as conf/tomcat-users.xml is rewritten when I start the container ie
mvn cargo:run
how I can supply user/password creds to access the manager?
cheers!
Edit: Cargo configuration
<plugins>
<!-- Start's the plugin tag for Cargo! -->
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<wait>false</wait>
<container>
<containerId>tomcat${tomcat.major}x</containerId>
<zipUrlInstaller>
<url>http://archive.apache.org/dist/tomcat/tomcat-${tomcat.major}/v${tomcat.version}/bin/apache-tomcat-${tomcat.version}.tar.gz</url>
<extractDir>${project.build.directory}/extract/</extractDir>
<downloadDir>${project.build.directory}/download/</downloadDir>
</zipUrlInstaller>
<output>${project.build.directory}/tomcat${tomcat.major}x.log</output>
<log>${project.build.directory}/cargo.log</log>
</container>
<configuration>
<home>${project.build.directory}/tomcat-${tomcat.version}/container</home>
<properties>
<cargo.logging>high</cargo.logging>
<cargo.servlet.port>9080</cargo.servlet.port>
<cargo.tomcat.ajp.port>9008</cargo.tomcat.ajp.port>
</properties>
</configuration>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
<goal>deploy</goal>
</goals>
<configuration>
<deployer>
<deployables>
<deployable>
<groupId>${project.groupId}</groupId>
<artifactId>mod-war</artifactId>
<type>war</type>
<pingURL>http://localhost:9080/mod-war</pingURL>
<pingTimeout>30000</pingTimeout>
<properties>
<context>mod-war</context>
</properties>
</deployable>
</deployables>
</deployer>
</configuration>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
Found it. You can supply custom configuration through the following xml (link to cargo docs in the above comments)
<files>
<copy>
<file>tomcat-users.xml</file>
<tofile>conf/tomcat-users.xml</tofile>
<configfile>true</configfile>
<overwrite>true</overwrite>
</copy>
</files>
So you can specify your own conf/*.xml or anything else and it will be copied before the container starts. I can login to the manager now :)
Cheers

Maven cargo jetty6x: is it possible to provide additional Jetty configuration?

I have application launched using maven cargo plugin with jetty6x. I get HTTP/1.1 413 FULL head on certain requests. I found out, that I need to specify larger headerBufferSize (due to large request header size). Is there a way to provide it to the cargo configuration?
My cargo configuration:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.1.2</version>
<configuration>
<contextPath>/${jetty.admin.context}</contextPath>
<container>
<containerId>jetty6x</containerId>
<type>embedded</type>
</container>
<configuration>
<properties>
<cargo.servlet.port>${jetty.port}</cargo.servlet.port>
</properties>
<deployables>
<deployable>
<properties>
<context>/http</context>
</properties>
<groupId>xxx.xxx.server</groupId>
<artifactId>http</artifactId>
<type>war</type>
</deployable>
</deployables>
</configuration>
<wait>false</wait>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
You want to specify the additional configuration files and the directories where they go under
<configuration><configfiles>...
in the configuration of the cargo plugin
see this post or the cargo site.

Maven: How do I configure tests to run in integration-test phase?

I'm using Maven 3.0.3. I want to run some Junit tests in my test phase and others in my integration-test phase. Problem is nothing is running during the integration-test phase. I run the command
mvn clean install
to kick everything off. Here is how I've configured my surefire-plugin ...
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<skip>false</skip>
<additionalClasspathElements>
<additionalClasspathElement>${project.build.sourceDirectory}</additionalClasspathElement>
<additionalClasspathElement>${project.build.testSourceDirectory}</additionalClasspathElement>
</additionalClasspathElements>
<useManifestOnlyJar>false</useManifestOnlyJar>
<forkMode>always</forkMode>
<systemProperties>
<property>
<name>gwt.args</name>
<value>-out \${webAppDirectory}</value>
</property>
</systemProperties>
<excludes>
<exclude>**/integration/**</exclude>
</excludes>
</configuration>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
<includes>
<include>**/integration/**</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
I have two JUnit tests in my "integration" directory. I'm using the Maven Cargo plugin to spin up a server during the integration phase. Here is that configuration ...
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<container>
<containerId>tomcat${tomcat.major}x</containerId>
<zipUrlInstaller>
<url>http://archive.apache.org/dist/tomcat/tomcat-${tomcat.major}/v${tomcat.version}/bin/apache-tomcat-${tomcat.version}.tar.gz</url>
<downloadDir>${project.build.directory}/downloads</downloadDir>
<extractDir>${project.build.directory}/extracts</extractDir>
</zipUrlInstaller>
<output>${project.build.directory}/tomcat${tomcat.major}x.log</output>
<log>${project.build.directory}/cargo.log</log>
</container>
<configuration>
<home>${project.build.directory}/tomcat-${tomcat.version}/container</home>
<properties>
<cargo.logging>high</cargo.logging>
<cargo.servlet.port>${tomcat.servlet.port}</cargo.servlet.port>
<cargo.tomcat.ajp.port>${tomcat.ajb.port}</cargo.tomcat.ajp.port>
</properties>
</configuration>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
<goal>deploy</goal>
</goals>
<configuration>
<deployer>
<deployables>
<deployable>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<type>war</type>
<pingURL>http://localhost:${tomcat.servlet.port}/${project.artifactId}</pingURL>
<pingTimeout>30000</pingTimeout>
<properties>
<context>${project.artifactId}</context>
</properties>
</deployable>
</deployables>
</deployer>
</configuration>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
Any ideas how I change/enhance my configuration so that my integration tests will run? - Dave
Have a look at Maven Failsafe Plugin

Resources