It seems to work, but for each environment, I have to build(compile) again even though the only difference is the property files that should get updated.
Ideally, I would like to provide PROD the same WAR file that got tested in QA (with property files updated).
Currently, I am manually providing the WAR file with property files "patched" in to the WAR for different environments.
I am sure there is a better way to do this in maven. Currently considering one of the following:
Externalizing the property files altogether and providing them separately.
Including property files for all environments in the WAR and load the relevant ones during startup.
Would love to hear your comments and hopefully find a better way.
Joined: Jun 25, 2007
Thanks for posting the link.
Jrebel is an interesting software. But it does not solve my problem.
It publishes code/property changes for a single container.
I need to deploy to a completely different environments. I understand that using this software makes creating WAR archives redundant. But that is how I am required to provide the release.
Furthermore, I dont see Jrebel plugged into Production servers any time soon.
I think your first approach (Externalizing the property files altogether and providing them separately.) is best. You can even use Maven to package all of the environment property files. As part of your deployment process, you'd need to unjar the correct one and add it to your classpath.
This is a feature that really irks me about Maven. It is "the Maven way" to include your property files inside the jar files and recreate the war for each environment. Big companies don't like different software packages for different environments. Even when you ask in Maven training what to do, the answer is to recreate the jars. Leaving you with something nonstandard to solve the problem.
Its good to know that I am not the only one irked by this missing feature in Maven.
Even though, I have googled this numerous times on previous occasions, yesterday, I was able to get some interesting links.
So far, I have not been able to find a standard maven way around this problem.
I would appreciate if more links/comments/opinions could be added to this post as I feel, this should be a very important feature of a build/deploy system.
I'm not a big fan of the build tool acting as a deploy tool. The whole point of a build tool is to create artifacts that can be deployed anywhere. The job of a deploy tool is to deploy and configure artifacts depending on the configuration of the target system. If you make your build tool act as a deploy tool, then you risk corrupting your build tool with environment specifics.
I can understand the need to automate deployment in continious integeration environments. IMO, the build tool should build the deploy tool, and continious integeration server should call the built deploy tool to deploy runtime artifacts into your environment. You don't need Maven to do something that a simple batch script can do.. and is better at. Heck, go nuts and even use ANT. Keep it out of Maven.
author & internet detective
Agreed. The problem is that "the Maven way" includes property files in the jars which are in the war. Which means the generated war can't just be deployed to different environments using a deploy script. And a deploy script has no business unjarring the war to change things.
Maven doesn't tell you to put environment specific runtime properties in the war. What should go into the maven properties should be the Build time properties. For example, lets say in production, you have a login module that authenticates the user against LDAP. Now, for developers, you really don't want to setup LDAP, and you just want to mock the login module. So, you put the class name of the login module in a property file. You setup the property file to be filtered by maven, default the property to LDAPLoginModule, and allow the developers to override that property to MockLoginModule. When you use LDAPLoginModule, you need the ldap URL etc. these are Runtime properties that shouldn't be internalized in the war. Instead there should be an install module that contains a script that copies the external property file in the correct place within the system.
Yes, this does force you to think about what is a runtime property vs what's a build time property. In the long run that's a good thing. Eventually, all applications reach configuration bloat: there are so many configurable properties that no one can keep track of them. By separating your build time properties from runtime, you start to control them much better. Maven even lets you constrain each build time property to the module that needs the property
I ALWAYS build a single WAR file for development, testing, and production. I do this because it prevents me from deploying the wrong WAR for the wrong environment and because it assures me that the code I'm debugging is the same as the code that's malfunctioning on the production server.
My configuration information is all external. Since most of my webapps run under Tomcat, I usually put the anchor information for environmentally-specific items in an external Tomcat Context definition. That information includes (as needed) database connection pools, data directory paths, locations of any properties files, etc.
An IDE is no substitute for an Intelligent Developer.