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.
-
Yes, using the release plugin is the recommended way. You can use the buildnumber plugin if you want the buildnumber in some document, e.g. CHANGES.txt
The original question asked for "the best practice" to do production deploys with Maven. I expected to get more than one "best practice" and offered the bounty to see different solutions and learn from them. I do not care if they are pure maven solutions or if they utilize different tools.
Parallel to this thread I did also some researching and would like to post here the different approaches I am seeing. I tried 1) and 3), they are pure maven and regardless what Aaron is saying, they are working also.
In my current project I have a development environment, a test environment, a staging environment and a production environment. From my maven pom I would like to work with the development environment and deploy only to the test environment. I see the following approaches with maven pom:
When working with this approach the deliverable (the war file) has to be rebuilded for different environments. This forced me to offer the bounty because I didn't like that.
This also generated different artefacts for different platforms. But instead of rebuilding the war file it will be unpacked/patched/repacked (for the war overlay) or build and packed with different settings (assembly plugin). I didn't like this solution either.
Specify the complete build with installation and also include the cargo plugin doing a remote deployment but not connect it to any phase. So I always work with the development environment but when I explicitely call the cargo plugin it deploys the war from the repository to a container (the test environment). I can even use profiles to distinguish between different containers just for the deployment via cargo.
In all solutions I am using integration test (surefire plugin), version plugin and release plugin for building the war. For the deployment I am implementing approach number 3 following the arguments from https://stackoverflow.com/a/1151870/734687 (a post which expresses very good what I also prefer).
Since the application has to work unchanged in all environment you have to distinguish the different settings on runtime and that can be very complicated. Our operational team wants to have settings per application outside the container so I support an environment var which points me to the proper directory but is optional. If nothing is set then I use the development settings inside the war. See a Spring sample here:
The properties in the META-INF/spring dir are loaded always. Additionaly I integrate properties from the file system which can override the properties above. If no properties are found this will not trigger an exeception because I set
ignoreResourceNotFound
. If the propertypicservice.configdir
is set it directs me to an directory, if not than I provided a default value with:
. The-
says that I want to have no value which is the current directory.For logging I have a similar solution. You can find very interesting articles about properties file handling with Spring at following links:
I found an interesting presentation about this topic, see Automated Deployment with Maven and friends.
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 :
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 :
If you want some examples, I can give you some.
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 :
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.
I think the simplest way to accomplish what you've specified (if I understood well) is to configure Maven Release Plugin as follows:
For dev deployments proceed as you're doing:
mvn tomcat:deploy -P dev
(ifdev
is active by default remove the-P dev
argument).When releasing proceed in two steps as Maven Release Plugin expects:
This goal will increase the version and tag as you want (and more). Notice that you will also need to specify what SCM Maven should use by configuring this tag in the POM:
SCM plugin supports a wide variety of SCM managers and protocols (you might be interested in
git:http
orgit:https
).And then
This will use the profile
prod
and simply run the goaltomcat:deploy
, exactly what you configured.I hope this is what you needed. Regards.
The Mavenized solution is not to use Maven when you have an exception to the common case. Maven is all about common cases. Exceptions are handled elsewhere which means the POM (should) never contain any surprises.
Since you need a custom deployment process, write a shell script or an Ant
build.xml
which does the necessary steps and uses Maven in the process to do the deployment.That way, each tool does what it can do best.
[EDIT] Note to all the downvoters out there: Unless you have an argument, your down vote means nothing. Maven is a tool. Like all tools, it has limits. The core Maven philosophy is to avoid exceptions. Ant is all about corner cases, Maven is about main stream. From the "What is Maven?" page:
(my emphasis) So yes, there are things for which Maven isn't the best solution for. If the standard release process works for you, use the release plugin.
But when it doesn't, then look elsewhere instead of falling for the "everything looks like a nail" mind trap.
One of the major personal development steps is to understand your own limits and the limits of the tools that you work with. When a tool isn't suitable for a job, try a different tool instead of trying to warp reality. Your live will be happier.
maybe phing its another tool to solve your problem, its simple, and u can make custom processes
Phing website