What is the most minimal example of deploying a war to multiple tomcat servers using maven that can be written?
I\'ve tried the following URLs and asked the mailing
This is quite a late answer to an old question, but I am pretty sure people will be interested in it. I just achieved to run multiple deployments using maven and ant tasks. The secret is to use a macrodef (or 2 for me as I hot deploy my apps in jetty and need to transfer a war and a xml file) and using a ant property file :
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<tasks>
<taskdef name="scp"
classname="org.apache.tools.ant.taskdefs.optional.ssh.Scp"
classpath="/usr/local/java/ant/lib/ant-jsch.jar:/usr/local/java/ant/lib/jsch-0.1.45.jar" />
<macrodef name="deploy">
<attribute name="server" default="NOT SET" />
<attribute name="file" default="NOT SET" />
<attribute name="todir" default="NOT SET" />
<attribute name="port" default="NOT SET" />
<attribute name="passphrase" default="NOT SET" />
<attribute name="keyfile" default="NOT SET" />
<sequential>
<echo message="Deploying to @{server}" />
<echo message="Deploying @{file} to @{todir}" />
<scp
file="@{file}" todir="@{todir}"
port="@{port}" passphrase="@{passphrase}"
keyfile="@{keyfile}" />
</sequential>
</macrodef>
<macrodef name="deploy-app">
<attribute name="config" default="NOT SET" />
<sequential>
<property file="deploy.properties"/>
<echo message="Deploying to @{config}" />
<deploy server="${@{config}.jetty.server.host}"
file="${project.build.directory}/${project.build.finalName}.${project.packaging}"
todir="${@{config}.jetty.server.user}@${@{config}.jetty.server.host}:${@{config}.jetty.server.baseDir}/${@{config}.jetty.server.webappsDir}"
port="${@{config}.jetty.server.port}"
passphrase="${@{config}.jetty.server.passphrase}"
keyfile="/home/steff/.ssh/id_rsa"/>
<deploy server="${@{config}.jetty.server.host}"
file="${project.build.finalName}.xml"
todir="${@{config}.jetty.server.user}@${@{config}.jetty.server.host}:${@{config}.jetty.server.baseDir}/${@{config}.jetty.server.contextDir}"
port="${@{config}.jetty.server.port}"
passphrase="${@{config}.jetty.server.passphrase}"
keyfile="/home/steff/.ssh/id_rsa"/>
</sequential>
</macrodef>
<deploy-app config="home"/>
<deploy-app config="wap"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
Then you property file needs to be something like :
home.jetty.server.user=
home.jetty.server.port=
home.jetty.server.host=
home.jetty.server.baseDir=
home.jetty.server.webappsDir=
home.jetty.server.contextDir=
home.jetty.server.passphrase=
wap.jetty.server.user=
wap.jetty.server.port=
wap.jetty.server.host=
wap.jetty.server.baseDir=
wap.jetty.server.webappsDir=
wap.jetty.server.contextDir=
wap.jetty.server.passphrase=
etc... on a block of option per server config used by
<deploy-app config="<config>"/>
The trick is that macrodef attribute using @{} as precedence over property evaluation ${} in ant.
This answer is for Jetty and for a slightly different situation, but you might find it useful anyway.
On a previous project we used Jetty, so I wrote a simple Jetty deployer module that would periodically scan the maven repository and download and deploy new artifacts as soon as they became available. This ran well on a small cluster of staging and development machines.
You can find the code at Google Code in the Polar Rose Jetty Maven Deployer project.
Note that we only did this for development and staging servers. In my opinion production apps should never ever be upgraded automatically.
With regards to using multiple profiles, the lifecycle seemed to duplicate certain steps - e.g. the number of tests doubled when using profiles activated by variables. We found that using the catalina-ant library was much more effective ;) and its more "minimal". Use "executions" element to attach the "run" goal to a lifecycle phase to streamline it, or run after package: mvn package antrun:run
You could get a bit more fancy with the ant-contrib library, and create a for loop with a list of servers, but here's a static configuration for 2 hard coded server urls.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<configuration>
<target>
<taskdef name="deploy" classname="org.apache.catalina.ant.DeployTask"/>
<deploy url="http://tc-app-01:8080/manager" username="manager" password="pass"
path="/app-path" war="file:${project.build.directory}/${project.build.finalName}.${project.packaging}" update="true"/>
<deploy url="http://tc-app-02:8080/manager" username="manager" password="pass"
path="/app-path" war="file:${project.build.directory}/${project.build.finalName}.${project.packaging}" update="true"/>
</target>
</configuration>
<dependencies>
<dependency>
<groupId>tomcat</groupId>
<artifactId>catalina-ant</artifactId>
<version>6.0.29</version>
</dependency>
</dependencies>
</plugin>
The specific version of catalina-ant used above was manually deployed to our distributed maven repository, it can be found in the lib directory of tomcat distribution.
Maybe the "most minimal" solution isn't minimal at all. If you have problems with doing that in maven itself, try using ant: create two different deploy tasks (one per server) and another task which has them as dependencies. There are several examples how to deploy to a tomcat server using ant. Just google them. Done this, you need to integrate the new ant tasks into maven which isn't difficult at all using the antrun plugin.
The idea of Markus Lux can be also applied with a Maven2 solution, with the profiles management:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
</plugin>
</plugins>
...
</build>
<profiles>
<profile>
<id>env-foo1</id>
<!-- Activated when -Denv=foo1 is given as parameter. -->
<activation>
<property>
<name>env</name>
<value>foo1</value>
</property>
</activation>
<properties>
<deploy.env>xxx</deploy.env>
<tomcat.manager>http://foo1/manager</tomcat.manager>
<tomcat.manager.username>foo</tomcat.manager.username>
<tomcat.manager.password>bar</tomcat.manager.password>
</properties>
</profile>
<profile>
<id>env-foo2</id>
<!-- Activated when -Denv=foo2 is given as parameter. -->
<activation>
<property>
<name>env</name>
<value>foo2</value>
</property>
</activation>
<properties>
<deploy.env>dev</deploy.env>
<tomcat.manager>http://foo2/manager</tomcat.manager>
<tomcat.manager.username>foo</tomcat.manager.username>
<tomcat.manager.password>bar</tomcat.manager.password>
</properties>
</profile>
...
</profiles>
Then, you will just need to run X times the mvn command, with the adequate parameter (-Denv=foo1, -Denv=foo2,...)
In addition to that, you can enhance this solution by using the Matrix feature of the Hudson Continuous Integration server. I gave a short explanation about this feature here.
Basically, you just define a "normal" Maven2 job in Hudson, and with the Matrix feature, you can ask Hudson to run this job several times, one per environment. In others words, you create your Hudson job, and then you define the "environment axis" with all possible value for the env parameter:
Hudson will then build the application with the mvn command and with the parameter -Denv=foo1.Once this build is finished, it will build the same application but with the parameter -Denv=foo2, and so on...
This way, Hudson will deploy your application in every environments...
I hope my solution will help you to reach your goals...