Deploying to Tomcat 7 with Maven

The Tomcat7 plugin for Maven has a number of uses. In a previous post, I’ve looked at using it to deploy a build to an embedded Tomcat server for integration testing with Selenium.

A more simple use case is to simply deploy (or undeploy) a built artifact (war) to a Tomcat installation on a local machine or on a remote server.

The following examples are available to download from the Spanners Demo on GitHub.

Deploy a single artifact to localhost Tomcat

The Tomcat 7 plugin is added to the pom as follows:

<!-- Deploy wars to Tomcat 7 with mvn tomcat7:deploy or tomcat7:redeploy -->
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.1</version>
    <configuration>
        <url>http://localhost:8080/manager/text</url>
        <username>admin</username>
        <password>admin</password>
    </configuration>
</plugin>

Note that the URL ends with /manager/text. This is the Tomcat plain text based interface that Maven uses to invoke commands in Tomcat.

The username and password must correspond with a Tomcat user with the ‘manager-script’ role. This user is created in Tomcat by adding the following to the tomcat-users.xml file in the <TOMCAT HOME>\conf directory.

<role rolename="manager-script"/>
<user username="admin" password="admin" roles="manager-script"/>

The Maven artifact can be built and deployed to Tomcat with the following command:

mvn tomcat7:deploy

and removed with the following command:

mvn tomcat7:undeploy

If the war is already running in Tomcat and you want to make a new build and update it, use the redeploy goal:

mvn tomcat7:redeploy

If the war has already been built and is to be deployed without rebuilding:

mvn tomcat7:deploy-only

Removing the username, password and URL from the pom

If multiple team members are working on the same project, it’s not ideal to store usernames and passwords in the Maven pom file. For a start, you may not want other users knowing your top secret password. Even if this isn’t a problem, another team member may use a different username and password to access their Tomcat.

Maven allows server usernames and passwords to be stored on each user’s own machine in the settings.xml which usually lives in ${user.home}/.m2/settings.xml. Note that it is possible to encrypt passwords in settings.xml, but I won’t cover that here.

In settings.xml, a server is configured as follows:

<server>
    <id>tomcat-localhost</id>
    <username>admin</username>
    <password>admin</password>
</server>

Instead of specifying the username and password in the pom, we can specify the server by its id:

<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <configuration>
        <server>tomcat-localhost</server>
        <url>${tomcat.deploy.url}</url>
    </configuration>
</plugin>

In the above example, I’ve also abstracted out the <url> as a Maven property. This allows individual users to override the default setting by using a profile defined in their own settings.xml:

<profiles>
    <profile>
        <id>localOverrides</id>
        <properties>
            <tomcat.deploy.url>http://localhost:8080/manager/text</tomcat.deploy.url>
        </properties>
    </profile>
</profiles>

This would be activated as follows:

mvn tomcat7:deploy -PlocalOverrides

Alternatively, the profile could be marked <activeByDefault>true</activeByDefault>.

Deploying multiple artifacts

The Spanners demo consists of three deployable wars: spanners-mvc (Spring MVC demo), spanners-struts (Struts demo) and spanners-ws (Spring Web Services demo). If the above plugin and config is added to all three POMs, they could all be deployed with a single command.

Better yet the plugin and configuration can be added to the root parent project, spanners-pom, in the <pluginManagement> section. Then each child project only need to refer to the plugin by name. The configuration is inherited from the parent.

<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
</plugin>

Running the following from the project root will deploy all three applications:

mvn tomcat7:deploy

Deploying automatically on builds

It may be desirable to have Maven automatically redeploy the application(s) to a test server on builds. This can be done by binding a Tomcat plugin goal to a Maven execution phase. The following example shows how to automatically deploy all runnable artifacts (wars) to an integration test server when a new build is deployed to the Maven repository. This may be useful in a Continuous Integration (CI) scenario where we want some system running the latest build.

Note here two meanings of the word deploydeploy is a standard Maven lifecycle phase which uploads an artifact to a remote repository for sharing with other developers. The Tomcat 7 plugin also has a deploy goal which uploads and starts the application in Tomcat. In this example, we want Tomcat updated with the latest build whenever we put an updated build in the Maven repository.

<profiles>
    <profile>
        <id>update-itg</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>

                    <!-- Deploy to integration test server on Maven deploy -->
                    <executions>
                        <execution>
                            <id>deploy-to-integrationtest</id>
                            <goals>
                                <goal>redeploy-only</goal>
                            </goals>
                            <phase>deploy</phase>
                            <configuration>
                                <server>integrationtest</server>
                                <url>http://itg.example.com:8080/manager/text</url>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

In this case the plugin is added to a build profile. This allows us to enable or disable it at command time. It’s disabled by default and can be activated by running:

mvn deploy -Pupdate-itg

The plugin redeploy-only goal is bound to the Maven deploy lifecycle phase. When this is run, the application is built, the artifacts (jars, wars and poms) are uploaded to the Maven repository and the updated application is started up on Tomcat, ready for manual or automated integration testing.

Leave a Reply

Your email address will not be published. Required fields are marked *