Maven 3 Plugin Tips

Tips

Starting multiple containers conditionally

Maven 3 supports the notion of profiles which can be used with Cargo to decide for example when to run tests on a specific container. Here's how you could use the Cargo Maven 3 plugin to that effect:

<project>
[...]
  <profiles>
    <profile>
      <id>tomcat5x</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven3-plugin</artifactId>
            <configuration>
              <container>
                <containerId>tomcat5x</containerId>
                <zipUrlInstaller>
                  <url>http://www.apache.org/dist/jakarta/tomcat-5/v5.0.30/bin/jakarta-tomcat-5.0.30.zip</url>
                  <downloadDir>${project.build.directory}/downloads</downloadDir>
                  <extractDir>${project.build.directory}/extracts</extractDir>
                </zipUrlInstaller>
              </container>
              <configuration>
                <home>${project.build.directory}/tomcat5x/container</home>
              </configuration>
            </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>
        </plugins>
      </build>
    </profile>
    <profile>
      <id>orion2x</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven3-plugin</artifactId>
            <configuration>
              <container>
                <containerId>orion2x</containerId>
                <zipUrlInstaller>
                  <url>http://www.orionserver.com/distributions/orion2.0.5.zip</url>
                  <downloadDir>${project.build.directory}/downloads</downloadDir>
                  <extractDir>${project.build.directory}/extracts</extractDir>
                </zipUrlInstaller>
              </container>
              <configuration>
                <home>${project.build.directory}/orion2x/container</home>
              </configuration>
            </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>
        </plugins>
      </build>
    </profile>
  </profiles>
</project>

Then to start the tomcat 5.x container you would type mvn -P tomcat5x install. if you want to start both containers you would type mvn -P tomcat5x,orion2x install.

If you want to define a profile as the default you can use the <activation> element with an activation strategy. For example if you want a profile to be always on, use:

<profiles>
    <profile>
      <id>tomcat5x</id>
      <activation>
        <activeByDefault>true</activeByDefault>
       </activation>
[...]

Starting Tomcat in security mode

Warning: the proposed solution only works on Linux, see MNG-6437.

Cargo supports passing system properties. So, to start Tomcat in security mode, you need to specify two system properties:

  • java.security.manager
  • java.security.policy

For instance,

[...]
  <plugins>
    [...]
    <plugin>
      <groupId>org.codehaus.cargo</groupId>
      <artifactId>cargo-maven3-plugin</artifactId>
      <configuration>
        <container>
          <containerId>tomcat5x</containerId>
          <home>${catalina.home}</home>
          [...]
          <systemProperties>
            <java.security.manager>default</java.security.manager>
            <java.security.policy>${catalina.home}\conf\catalina.policy</java.security.policy>
          </systemProperties>
        </container>
      </configuration>
    </plugin>
    [...]
  </plugins>
[...]

How to get Tomcat 5 working with the Java 5 XML Parsers

Tip submitted by Ben P.

Imagine that you have some XML jars in the common/endorsed folder of Tomcat and you have edited your catalina.bat file to specify some extra JVM opts to specify the XML parser. Here's how to achieve the same using Cargo:

<plugin>
  <groupId>org.codehaus.cargo</groupId>
  <artifactId>cargo-maven3-plugin</artifactId>
  <configuration>
    <container>
      <containerId>tomcat5x</containerId>
      <home>${tomcat.home}</home>
      <dependencies>
        <dependency>
          <location>${tomcat.home}/common/endorsed/xalan.jar</location>
        </dependency>
        <dependency>
          <location>${tomcat.home}/common/endorsed/xercesImpl.jar</location>
        </dependency>
      </dependencies>
      <systemProperties>
        <javax.xml.parsers.DocumentBuilderFactory>
          org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
        </javax.xml.parsers.DocumentBuilderFactory>
        <javax.xml.parsers.SAXParserFactory>
          org.apache.xerces.jaxp.SAXParserFactoryImpl
        </javax.xml.parsers.SAXParserFactory>
      </systemProperties>
    </container>
    <configuration>
      <type>existing</type>
      <home>${tomcat.home}</home>
    </configuration>
  </configuration>
</plugin>

This shows how to add classpath elements to a Cargo container using the <dependencies> element.

How to run a Jetty webapp under a Java Security Manager

Tip submitted by Claude Brisson

This solution doesn't work on Windows for now: @cargo.repository@, @cargo.container@ and @cargo.webapp@ should be URIs and not paths.


Jetty 8.x has its own security manager, which can be enabled by enabling the jetty-policy.xml module, but it will search for its policies files under a lib/policy directory located in the same location as start.jar, inaccessible to Cargo's custom configuration folders.

So we'll stick to the Jetty 9.x container. In Jetty 9.x there is no internal security manager, so we'll directly run Jetty 9.x under the standard java.lang.SecurityManager.

We'll first need a mywebapp.policy policy file. It gives rights to Jetty itself:

src/main/policy/mywebapp.policy
///////////////////////////////////////////////////
//
// Give Maven repository libs all permissions
//
///////////////////////////////////////////////////

grant codeBase "file:@cargo.repository@/-"
{
    permission java.security.AllPermission "", "";
};

///////////////////////////////////////////////////
//
// Give Jetty libs all permissions
//
///////////////////////////////////////////////////

grant codeBase "file:@cargo.container@/-"
{
    permission java.security.AllPermission "", "";
};

///////////////////////////////////////////////////
//
// Give anyone basic and reflection runtime rights
//
///////////////////////////////////////////////////

grant
{
    permission java.lang.RuntimePermission "accessDeclaredMembers";
    permission java.lang.RuntimePermission "getProtectionDomain";
    permission java.lang.RuntimePermission "getClassLoader";
};

///////////////////////////////////////////////////
//
// Let webapp resolve classes dependencies
//
///////////////////////////////////////////////////

grant codeBase "file:@cargo.webapp@/WEB-INF/classes/-"
{
    permission java.io.FilePermission "@cargo.webapp@/WEB-INF/lib/*", "read";
    permission java.io.FilePermission "@cargo.webapp@/WEB-INF/classes/-", "read";
};

grant codeBase "file:@cargo.webapp@/WEB-INF/lib/*"
{
    permission java.io.FilePermission "@cargo.webapp@/WEB-INF/lib/*", "read";
    permission java.io.FilePermission "@cargo.webapp@/WEB-INF/classes/-", "read";
};

///////////////////////////////////////////////////
//
// Let mywebapp be given appropriate rights
//
///////////////////////////////////////////////////

grant codeBase "file:@cargo.webapp@/WEB-INF/lib/mywebapp.jar"
{
    // ...
};

... and then configure appropriately the Cargo Maven 3 plugin:

<plugin>
    <groupId>org.codehaus.cargo</groupId>
    <artifactId>cargo-maven3-plugin</artifactId>
    <version>1.6.8</version>
    <configuration>
        <container>
            <containerId>jetty9x</containerId>
        </container>
        <configuration>
            <files>
                <copy>
                    <file>${project.basedir}/src/main/policy/showcase.policy</file>
                    <todir>/</todir>
                    <configfile>true</configfile>
                </copy>
            </files>
            <properties>
                <cargo.container>${project.build.directory}/cargo/installs</cargo.container>
                <cargo.repository>${settings.localRepository}</cargo.repository>
                <cargo.webapp>${project.build.directory}/${project.artifactId}</cargo.webapp>
                <cargo.slf4j.version>${slf4j.version}</cargo.slf4j.version>
                <cargo.jvmargs>
                    <!-- enable security manager -->
                    -Djava.security.manager
                    -Djava.security.policy=${project.build.directory}/cargo/configurations/jetty9x/my_webapp.policy
                </cargo.jvmargs>
            </properties>
        </configuration>
    </configuration>
    <executions>
        <execution>
            <configuration>
                <wait>false</wait>
            </configuration>
            <id>start-server</id>
            <goals>
                <goal>start</goal>
            </goals>
            <phase>pre-integration-test</phase>
        </execution>
        <execution>
            <id>stop-server</id>
            <goals>
                <goal>stop</goal>
            </goals>
            <phase>post-integration-test</phase>
        </execution>
    </executions>
</plugin>