Ant support

Definition

Cargo provides Ant tasks to perform all the operations available from the Java API. The minimum supported version is Ant 1.9.15.

Security issues with older versions of Apache Ant

As documented in CVE-2020-1945, Apache Ant versions 1.1 to 1.9.14 and 1.10.0 to 1.10.7 use the default temporary directory identified by the Java system property java.io.tmpdir for several tasks and may thus leak sensitive information. Moreover, the fixcrlf and replaceregexp tasks copy files from the temporary directory back into the build tree allowing an attacker to inject modified source files into the Codehaus Cargo container configuration generation process, a security issue still existing in Apache Ant 1.9.15 and 1.10.8. Last but not least, Apache Ant versions up to 1.9.15 / 1.10.10 suffer from an issue where a specially crafted ZIP or TAR file can make the associated libraries allocate very large amounts of memory (and cause a JVM crash, as explained in CVE-2021-36373 and CVE-2021-36374).

We hence strongly recommend only using Apache Ant version 1.9.16 and above (if you need to stick to the Apache Ant 1.9.x branch), or Apache Ant version 1.10.11 and above in general.

Functional tests

The usage of Cargo for executing functional tests on a container does not mandate these Ant tasks. You could directly use the Cargo Java API from your Java unit test classes (JUnit, TestNG, etc), as described on the Functional testing page.

Explanation

Before using the Ant API you need to register the Cargo Ant tasks into Ant. This is done in the following manner:

<taskdef resource="cargo.tasks">
  <classpath>
    <pathelement location="${cargo-core-uberjar.jar}"/>
    <pathelement location="${cargo-ant.jar}"/>
  </classpath>
</taskdef>

Some additional dependencies might also be required for the Ant task. Please see the Installation page for details.

The Cargo Ant tasks in detail

Here are the different task actions available to call on this plugin:

Action

Description

start

Start a container. That task will:

Note: A container that's started with the start task will automatically shut down as soon as the parent Ant instance quits (i.e., you see a BUILD SUCCESSFUL or BUILD FAILED message). If you want to start a container and perform manual testing, see our next task run.

run

Start a container and wait for the user to press CTRL + C to stop. That task will:

stop

Stop a container.

restart

Stop and start again a container. If the container was not running before calling restart, it will simply be started.

configure

Create the configuration for a local container, without starting it. Note that the start and run actions will also install the container automatically.

daemon-start

Start a container using the Cargo Daemon.

daemon-stopStop a container using the Cargo Daemon.

deploy

Deploy a deployable to a running container.

undeploy

Undeploy a deployable from a running container.

redeploy

Undeploy and deploy again a deployable. If the deployable was not deployed before calling redeploy, it will simply be deployed.

Wait after the container has started

Many wonder the difference between the start and run actions:

  • If you want to just start the container and then do other tasks (for example, execute tests), use the start action. That action should therefore ONLY be used for integration testing.
  • If you want start the container and have Ant "blocked" afterwards (i.e., until you press CTRL + C to stop), use the run action. run is therefore the action to use for manual testing.

These are the various XML configuration elements that you can use to configure the Cargo Ant tasks. Make sure you also check the examples which show how to use them.

Top level configuration elements

Description

Mandatory?

Default value

<action>

Action to execute. These can be:

  • Container actions: configure, start, restartrun or stop
  • Deployer actions: deploy, undeploy or redeploy
  • Cargo Daemon actions: daemon-start or daemon-stop

(thumbs up)

No default

<containerId>

Id of the container to use. Valid values can be found in the description page for each container

(thumbs up)

No default

<containerType>

The container's type. Valid values are installed, embedded and remote

(thumbs down)

Default value is installed

<home>

Location where the container is installed. If specified in conjunction with the <zipUrlInstaller> element, it will override the home directory defined by the installer

(thumbs down)

No default

If the user has not defined any home nor <zipUrlInstaller> element then the Ant task will automatically attempt to download the container using the URL used by its tests (see the Tested On section of each container).

<zipUrlInstaller>

Defines the location of a container distribution zip that will be downloaded and installed

(thumbs down)

No default

If the user has not defined any home nor <zipUrlInstaller> element then the Ant task will automatically attempt to download the container using the URL used by its tests (see the Tested On section of each container).

<timeout>

The timeout after which Cargo reports an error if the container is not started or stopped

(thumbs down)

120000 ms (2 minutes)

<systemProperties>

List of <key>value</key> pairs to be passed as System properties to the container when it is started.


You can also use the <systemPropertiesFile> element to load system properties from a file.

(thumbs down)

No default

<extraClasspath>

Additional classpath entries for the classpath that will be used to start the containers.

(thumbs down)

No default

<sharedClasspath>

Classpath entries for the classpath that will be shared the applications deployed in a container. Shared application classpath deployment is only available for local containers which support shared Application Classpaths.

(thumbs down)

No default

<log>

Path to a file where Cargo logs are saved

(thumbs down)

Logs to the Ant console if no log file is specified

<output>

Path to a file where container logs are saved

(thumbs down)

Logs to the file specified by the <log> element or to the Ant console if no such file has been specified

<append>

If true, then the file specified by <output> will not be erased across different runs

(thumbs down)

false

<configuration>

Definition of a Configuration

(thumbs down)

Defaults to a standalone configuration if the container is of type local and a runtime one if it's of type remote

<daemon>

Additional configuration that is used when deploying with the Cargo Daemon.

(thumbs down)

For more information, please read: Cargo Daemon.

<configuration> elements

Description

Mandatory?

Default value

<type>

Configuration's type. Valid values are standalone, existing and runtime

(thumbs down)

standalone

<home>

For standalone configuration this is the location where Cargo will create the configuration and for existing configuration this is where it is located

(thumbs up)

No default

<properties>

Values to use for various Configuration properties.


You can also use the <propertiesFile> element to load configuration properties from a file.

(thumbs down)

Default configuration properties

Note that these configuration properties can also be overriden using Java properties; for example:

ant -Dcargo.servlet.port=8082

<deployables>

A list of deployables that are going to be deployed in the container when it is started or when deploy / undeploy is called.

(thumbs down)

No default

<fileConfigs>

List of Configuration files that are to be added to a local container's configuration. Each file is specified using a <fileConfig> element. Cargo token replacement is applied to the files and any existing file is overwritten.

(thumbs down)

No default

<files>

List of files that are to be added to a local container's configuration. Each file is specified using a <file> element.

(thumbs down)

No default

<xmlReplacements>

Values to use for various XML replacements.

(thumbs down)

No default

<users>List of users to be created in container configuration.

(thumbs down)

No default

<datasources>List of datasources to be created in container configuration.

(thumbs down)

No default

<fileConfigs> elements

Description

Mandatory?

Default value

<file>

The configuration file or directory containing configuration files.

(thumbs up)

No default

<todir>

The target directory, relative to configuration home, where the file should be copied

(thumbs down)

If not specified, the file will be copied to the configuration's home directory

<tofile>

The target file name to use

(thumbs down)

The original file name

<file> elements

Description

Mandatory?

Default value

<file>

The file, or directory, to add

(thumbs up)

No default

<todir>

The target directory, relative to configuration home, where the file should be copied

(thumbs down)

If not specified, the file will be copied to the configuration's home directory

<tofile>

The target file name to use

(thumbs down)

The original file name

<configfile>

Indicates if Cargo token replacement should be applied (true) when copying. Do not use this option on a non-ascii file as it will corrupt it!

(thumbs down)

false

<overwrite>

If any existing file should be overwritten or not

(thumbs down)

true

<deployable> elements

Description

Mandatory?

Default value

<type>

Deployable type, i.e. warearejb, etc.

(thumbs up)

No default

<file>

The deployable file.

(thumbs up)

No default

<pingURL>

URL on which to ping the deployed or undeployed application (to check if deployment or undeployment is successful), that should return an HTTP OK response only after the deployment is complete. If not set, the deployed or undeployed application will not be pinged, hence the deployment considered as complete as soon as the target server's method returns successfully.

(thumbs down)

No default

<pingTimeout>

If <pingURL> is set, the number of milliseconds after which the ping fails the build if still not successful.

(thumbs down)

20000 (i.e., 20 seconds)

<properties>

User-defined properties of a deployable.

(thumbs down)

No default

<properties> elements

 Deployable Type

Description

Mandatory?

Default value

<context>

WAR

The context name to use when deploying the web application.

(thumbs down)

Default's to the file name without the extension

<war>

WAR

The path of the WAR being deployed.

(thumbs down)

Default's to the file name without the extension

<ear>

EAR

The path of the EAR being deployed.

(thumbs down)

Default's to the file name without the extension

<name>

EAR

The name of EAR deployable (it can be anything, there's no special rule).

(thumbs down)

Default's to the file name without the extension

<ejb>

EJB

The path of the EJB being deployed.

(thumbs down)

Default's to the file name without the extension

About WAR contexts

Many containers have their specific files for redefining context roots (Tomcat has context.xml, JBoss has jboss-web.xml, etc.). If your WAR has such a file, the server will most probably use the context root defined in that file instead of the one you specify using the CARGO deployer.

<zipUrlInstaller> elements

Description

Mandatory?

Default value

<url>

URL from which to download the container's ZIP or TAR.GZ file.

(thumbs up)

No default

<downloadDir>

Directory in which the zipUrlInstaller should download the container's ZIP or TAR.GZ file.

(thumbs down)

${java.io.tmpdir}/cargo/installs

<extractDir>

Directory in which the zipUrlInstaller should extract the container's ZIP or TAR.GZ file.

(thumbs down)

${project.build.directory}/cargo/installs

<proxy>

Proxy server settings, if required.

(thumbs down)

No default

<proxy> elements (under the zipUrlInstaller element)

Description

Mandatory?

Default value

<host>

Proxy host name or IP address.

(thumbs up)

No default

<port>

Proxy port.

(thumbs down)

Very probably 80

<user>

User name to connect to the proxy server.

(thumbs down)

No default

<password>

Password to connect to the proxy server.

(thumbs down)

No default

<user> elementsDescriptionMandatory?Default value
<name>User name.

(thumbs up)

No default
<password>User password.

(thumbs down)

No default
<roles>

List of roles which should be assigned to user.

Example of roles configuration:

<roles>
    <role>cargo</role>
</roles>

(thumbs down)

No default

<datasource> elementsDescriptionMandatory?Default value
<jndiName>JNDI name where to find this DataSource.

(thumbs up)

No default
<connectionType>Type of this DataSource, for example: javax.sql.XADataSource

(thumbs down)

No default
<transactionSupport>Transaction support of the DataSource, for example: XA_TRANSACTION

(thumbs down)

No default
<driverClass>The class name of the driver, for example: org.hsqldb.jdbcDriver

(thumbs down)

No default
<url>DataSource connection URL.

(thumbs down)

No default
<username>DataSource username.

(thumbs down)

No default
<password>DataSource password.

(thumbs down)

Empty string
<id>Identifier used in configuration files.

(thumbs down)

No default
<connectionProperties>Extra properties passed to the DataSource.

(thumbs down)

No default

Daemon configuration

The Cargo Daemon is a Web-based application that uses the Cargo API to configure, start and stop containers on a remote machine. The daemon is meant to be listening 24/7, to allow users to deploy new containers and web applications at their command. For more information, please read: Cargo Daemon.

Container configuration for the Daemon

For the Ant tasks, the "daemonized server" is actually a local container with a hostname that points to a remote machine. This implies that:

  • You should not set the container type to a remote container nor add any remote deployers to the configuration; but instead define the container as a local container (with either a standalone or existing configuration)
  • When you define the home paths for the container and the configuration, remember these paths are for the machine where the Daemon is running (and, preferably, use absolute paths)

When you call daemon-start, the Ant tasks will do the following:

  • If an installer is defined:
    • Download the archive locally
    • Send the archive over to the machine running the Daemon
    • Instruct the Daemon to extract the archive
  • If a standalone local configuration is defined, instruct the Daemon to create it
  • In all cases:
  • Finally, instruct the Daemon to start the container

<daemon> elements

Description

Mandatory?

Default value

<classpaths>

A list of <classpath>myclasspath</classpath> items, that will be added by the JVM launcher when starting a container.

(thumbs down)

No default

<properties>

A list of properties used to configure the Cargo Daemon.

(thumbs up)

No default

<properties> elements

Description

Mandatory?

Default value

<cargo.daemon.url>

URL to connect with the daemon.

(thumbs up)

No default

<cargo.daemon.handleid>

The handle id to register this container with.

(thumbs up)

No default

<cargo.daemon.autostart>

When set to true, the dameon will automatically restart the container if the daemon notices it is stopped.

(thumbs down)

false

<cargo.daemon.username>Username used when authenticating against the daemon host(thumbs down)admin
<cargo.daemon.password>Password used when authenticating against the daemon host(thumbs down)Empty string

Examples

Orion 2.x

Here's a full example showing how to deploy a WAR, and expanded WAR and an EAR in an Orion 2.x container. Please note that the output and log attribute are optional. The property elements allow you to tune how the container is configured. Here we're telling it to start on port 8180 and to generate the maximum amount of logs in the container output file.

<taskdef resource="cargo.tasks">
  <classpath>
    <pathelement location="path/to/cargo-uberjar.jar"/>
    <pathelement location="path/to/cargo-ant-tasks.jar"/>
  </classpath>
</taskdef>

<cargo containerId="orion2x" home="c:/apps/orion-2.0.3" output="target/output.log"
    log="target/cargo.log" action="start">
  <configuration>
    <property name="cargo.servlet.port" value="8180"/>
    <property name="cargo.logging" value="high"/>
    <deployable type="war" file="path/to/my/simple.war"/>
    <deployable type="war" file="path/to/my/expandedwar/simple"/>
    <deployable type="ear" file="path/to/my/simple.ear"/>
  </configuration>
</cargo>

Loading configuration properties from a file

It is also possible to load the configuration properties from a file - simply use the propertiesFile attribute of the configuration XML element.

Tomcat 5.x

This example gives a walk through of how to get a Cargo Ant build to work with Tomcat 5.x .

Prerequisites
  • It is assumed that Tomcat 5.x is already installed
  • The cargo-core-uberjar.jar and cargo-ant.jar JARs have been downloaded
  • A mimimum knowledge of Ant is required
  • User already has a war target that properly generates a working war file
Steps

Follow the following steps to configure your build.xml :

  • Create a folder under your basedir called cargolib that will hold cargo-core-uberjar.jar and cargo-ant.jar
  • Define a property for cargolib
<property name="cargolib.dir" value="${basedir}/cargolib"/>
  • Define 2 new properties cargo-uberjar and cargo-antjar as shown below:
<property name="cargo-uberjar" value="${cargolib.dir}/cargo-core-uberjar.jar"/>
<property name="cargo-antjar" value="${cargolib.dir}/cargo-ant.jar"/>
  • Add additional properties for defining the following:

    Property

    Description

    tomcat.home

    Installation directory of tomcat5x

    tomcatlog.dir

    This is where our logs are going to be generated

    tomcatconfig.dir

    Cargo needs an empty config folder

    pathtowarfile

    The full path of the war file e.g c:/devtools/myapp/dist/myfile.war

  • Add the following code to your build.xml :

    <taskdef resource="cargo.tasks">
      <classpath>
        <pathelement location="${cargo-uberjar}"/>
        <pathelement location="${cargo-antjar}"/>
      </classpath>
    </taskdef>
    	
    <target name="cargostart" depends="war">
      <delete dir="${tomcatconfig.dir}" />
      <mkdir dir="${tomcatlog.dir}"/>
      <mkdir dir="${tomcatconfig.dir}"/>
      <echo message="Starting Cargo..."/>
      <echo message="Using tomcat.home = ${tomcat.home} "/>
      <echo message="Using war = ${mywarfile} "/>
      <echo message="Jars used = ${cargo-uberjar} , ${cargo-antjar}"/>
    		
      <cargo containerId="tomcat5x" home="${tomcat.home}" output="${tomcatlog.dir}/output.log" 
          log="${tomcatlog.dir}/cargo.log" action="start">
        <configuration home="${tomcatconfig.dir}">
          <property name="cargo.servlet.port" value="8080"/>
          <property name="cargo.logging" value="high"/>
          <deployable type="war" file="${mywarfile}"/>
        </configuration>
      </cargo>
    
    </target>
    

Remote deployment

Here's a full example showing how to deploy a WAR to a remote Tomcat 6.x container.

<taskdef resource="cargo.tasks">
  <classpath>
    <pathelement location="path/to/cargo-uberjar.jar"/>
    <pathelement location="path/to/cargo-ant-tasks.jar"/>
  </classpath>
</taskdef>

<cargo containerId="tomcat6x" action="deploy" type="remote">
  <configuration type="runtime">
    <property name="cargo.hostname" value="production27"/>
    <property name="cargo.servlet.port" value="8080"/>
    <property name="cargo.remote.username" value="admin"/>
    <property name="cargo.remote.password" value=""/>
    <deployable type="war" file="path/to/simple-war.war">
      <property name="context" value="application-context"/>
    </deployable>
  </configuration>
</cargo>

For more details, please check the example in the Remote Container section for the Ant tasks. The Ant tasks support the deployer actions deploy, undeploy and redeploy.