Issue
I must confess I'm new to maven world after years of living in the world of monstrous debuild/ant/makefile chimeric constructions. I just don't have yet that very feeling which helps seasoned developer to choose right decisions, and it's looks like there are plenty different ways in maven.
So, I have a simple project containing of web-app. I want basically following:
- deploy to development Tomcat (I'm using tomcat:deploy), then do nothing.
- deploy to production Tomcat, but before deployment update git repo, add tagged commit and upgrade build version.
For distinguishing between development and production I've created profiles, dev
and prod
. The dev
profile is activated by default. When I want to deploy something to production, I just type mvn -P prod tomcat:deploy
I've read about release plugin, as well as about buildnumber plugin. But I'm just not sure I'm going the right way.
So, the question is - what is the most succint, self-contained and "mavenish" way to resolve the task I'm asking about.
Solution
Shabunk, as I was commented out, Maven is driving you on the best way to do what you want, inheriting from years of developpers experience.
I would explain what I would (and what I myself really) do.
So you're right to use Maven Release Plugin, plus another one (cargo for instance) You're trying to do two differents things :
- Identifying a unique version, which means tagging it, and updating pom for a new version
- Deploying your app (no matter which environnement it is)
Maven Release Plugin
Consider that your own process is maybe ligher than other dev teams are used to. I mean that there is more steps between unit testing and production deployment in larger teams (Q&A, user acceptance, non regression campains). It seems that you make a shortcut linking tag and production deployement. If you want to deploy your webapp on different environnements (integration, user acceptannce, performance, preprod, and so on) you had to identify your version and had to be able to build it again (sure and "repeatable").
That what maven-release-plugin is intended to. It helps you to verify that your source code is clean (all files under source control, with no modification), can compile and pass all tests phases. Then, it deals with pom version and tagging, and finish by storing it for later use in you Maven enterprise repository.
You have many configurations to set up (ditributionManagement, SCM, maven plugin release configuration). But once it is in place, releasing version stand in one simple command line :
mvn release:prepare release:perform
If you want some examples, I can give you some.
<scm>
<!-- Base URL repository -->
<url>scm:svn:http://svn.myorg.corp/svn/repository/</url>
<!-- Developper URL (from trunk or branche) -->
<developerConnection>scm:svn:http://svn.myorg.corp/svn/repository/trunk/project1</developerConnection>
<connection>scm:svn:http://svn.myorg.corp/svn/repository/trunk/project1</connection>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.6</version>
<configuration>
<username>${from.settings.xml.user}</username>
<password>${from.settings.xml.password}</password>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.2.2</version>
<configuration>
<tagBase>http://svn.myorg.corp/svn/repository/tags/</tagBase>
<scmCommentPrefix>[DEV#SCM]</scmCommentPrefix>
</configuration>
</plugin>
</plugins>
[...]
</build>
<distributionManagement>
<repository>
<id>enterprise_repo</id>
<name>Enteprise Repository on Artifactory - Stable versions</name> <url>http://repo.corp:8080/artifactory/prj-xxx-releases</url>
</repository>
<snapshotRepository>
<id>enterprise_repo</id>
<name>Enteprise Repository on Artifactory - DEV versions</name>
<url>http://repo.corp:8080/artifactory/prj-xxx-snapshots</url>
</snapshotRepository>
<site>
<id>corporate_site</id>
<name>Corporate public site</name>
<!-- must add wagon plugin that support this protocol -->
<url>ftp://...</url>
</site>
</distributionManagement>
Deployement
Once again, you may have multiple environnements on which you want to test your app against. There is many plugins that allow you to send and deploy your war : the general cargo-plugin, or more specific ones tomcat-plugin, glassfish-plugin, ... Plugins are giving you the hability to do what you want. Then, configuration can be performed in many ways.
Full Maven way : The full integrated way with Maven is to use Profile and maybe Filters. Profiles let describe properites and behaviour, as you seem to know. Filters are kind of .properties grouping a set of variable that will be used to replace patterns in you xml configuration file into the war (for instance, db connection). It's not the one I use because I find it less flexible than externalizing files. But no matter
Maven with its ecosystem: The way I prefer is to build my apps with Maven and Jenkins (or Continous Integration tool). This is why I'm agree with Aaron when he says that you had to konw limitations of your tools. Using Jenkins, I run every hours/day my application against Unit Tests, generatio Q&A reports, documentation, ... I have a release build that help me to produce all I want to deliver it (to my test team or my customer), and I provide some information to my jobs to deploy it onto different environnements (using maven profiles or jenkins built-in configuration).
It works really fine for me, and I'm pretty sure this is the right way to do.
[EDIT]
Deployment
Once again, deployment mean different phases of Lifecycle.
Local / Dev environnement
I'd never use tomcat:deploy until now, but only because I'd prefer using jetty as light web container (and well integrated with maven). But I'm pretty sure that every kinf of configuration would fit your needs here.
Continuous Integration Environnement In an continous integration environnement, I usually copy the war directly with Jenkins (exporting *.war on the desired machine). The way I do depends on many things :
- if CI soft is on the same (physical|virtual) server than your app server (Tomcat, Jboss, Weblogic, Glassfish, ...), or distant one => copy time will outstand server refresh time and will produce unsafe deployement (generally corrupted archives)
- if server is supporting hot reloading (exploded war in web-apps for Tomcat) or at least aware of file system modifications (full war in /deploy for JBoss)
- if you need to stop your server before, ...
Most of time, it's a simple copy. If I can't, I use some integrated maven plugins (like jahia:deploy plugin for the famous CMS : www.jahia.com), or just cargo plugin : http://cargo.codehaus.org/Maven2+plugin. I don't have any example, but it's really easy to find some on internet because this configuration is often recommanded.
Q&A / Acceptance / Production environnement
For those kind of environnements, which often (as far I as I saw in my job) deals with Service Level Agreement, we (I or admin team) wrote some specific scripts. I'm sure you will be desapointed, but as I mentionned, I don't rely on Maven for everything, and for deployement in particular. IMHO, this is one limit of this tool. You can maybe rely on cargo plugin, or specific ones, but releasing a version, or building one don't match (in time sequence) with real deployement. Even more, I didn't find any plugin that allow me easily to deploy on multiple instances ... and even worth you had to shutdown instances in a specific order (SLA's needs). That said, I didn't mentionned external properties, or SQL scripts, or anything else. They are additional reasons to rely on a dedicated tool.
So, generally, we wrote our own ant / sell scripts. If somebody else have better solutions, I'm obviously interrested in !
I hope I was clear enough.
Regards.
Answered By - Jean-Rémy Revy
Answer Checked By - Timothy Miller (JavaFixing Admin)