Jenkins building for different environments - java

I currently have a Jenkins instance installed on a Development box. This builds fine and deploys to our development environment without any issues.
During the build process my project makes use of a single properties file containing details such as a database connection URL (Details such as these will obviously vary depending on the environment I'm pointing to).
What I would like to know is what is the best way to configure my project so that when I want to release to Production the WAR file built by Jenkins contains the Production properties instead of Development?
(Note I am also using Maven in my project).

I know 3 options:
We have used maven.-profiles for that in the past, but they have the disadvantage, that the release-plugin of maven doesn't work with profiles, so we had to change the versions manually and were unable to deploy the artifacts in a remote repository like nexus.
Another Option is mavens assembly-plugin. That can be used together with the release-plugin, as far as I know.
We decided to write a simple tool that changes the war-files after the maven-build process. It runs in a seperate Jenkins-Job. The Idea is, that building and configuring are two seperate steps. The Artifacts comming out of maven are always in a default-configuration. And if we need the configuration for the production release we start a jenkins job that does the configuration of the war-files.

You can create different maven profiles, like dev, prod, then in the profile setting, use/filter the corresponding resource files like .../(dev|test|prod)/project.properties And in Jenkins, when you build for different platform, build with -Pdev or -Pprod to get the war for the right target.
You may want to check maven profile, maven resource filtering for detailed configuration.
something not related, connect Database via jndi if possible.

Related

Switch between development and production in a java webapp

My team develops a Vaadin web application. When we are giving a release for production, we have to manually make several changes in few files before building the war file. For an example, we have to change log4j settings in log4j2.xml and set vaadin productionMode to true in web.xml.
We are using Intellij IDEA for development. We build the webapp using Maven
Is there a better way to keep two build modes so that we can easily switch between production and development mode?
If your intention is to generate different deliverables of each one of your environments, a posible solution is to use Maven profiles.
http://maven.apache.org/guides/introduction/introduction-to-profiles.html
If you define different profiles with a different set of resources for each one, say 'AVE', 'UAT', 'NFT', whatever, you can then call Maven with a designated profile in order to generate the application you need
mvn clean deploy -P AVE
mvn clean deploy -P UAT
etc.
If you don't want to keep different versions of your *.properties and web.xml and maintain all of them (which would be a burden and quite error-prone), you can also use profiles, but combine it with filtering (http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html) in order to keep only 1 copy of each properties, web.xml, etc. in your code. This way you can have some properties like 'productionMode' you mention depending on properties defined in the AVE, UAT, NFT, etc. profiles in your pom.xml.

Maven global plugin configuration

I'd like to have a plugin configuration that will not exist inside the pom.xml file (and also in any project files).
What I want to do is to have a plugin that will be used only by me on my workstation. Specifically, I want to deploy my project onto the Tomcat 7 container and for this I want to use Apache Tomcat Maven Plugin, but since different developers may want to use different servers or entire ways of deployment I don't want to put this configuration into the pom.xml.
Is it possible in Maven to have such global/user-specific plugin configuration?
There are several workarounds that I can think of.
in the pom.xml a specific set for where you define your way of deployment.
ex: mvn goal -P{PROFILE_NAME}
you can just put the plugin normally in pom.xml and just don't push the changes on the repository, so it won't be available for other developers.
But the assumption seems kind of wrong, if you many developers want to work on the same project they should use the same container for deployment for persistence or if you really want to do it like this, I think the cleanest way would be for every developer to use maven profiles. And in your local settings.xml (USER_HOME/.m2/settings.xml)
just set the profile as default:
(...)
<activeProfiles>
<activeProfile>{YOUR_USER_PROFILE}</activeProfile>
</activeProfiles>
(...)
so you don't need to always specify at command line when running mvn your user profile.

Maven - Separating Deployment & Project

What is the 'best practice' way of separating Maven deployment configuration from the build config?
I have a war project, that is built by Jenkins. I'd like Jenkins to deploy this to Elastic Beanstalk, but alas the best solution available at the moment is to use the beanstalk-maven-plugin.
I'm not sure it makes sense for the POM.xml to include information about deployment; after all, at build time that .war could end up anywhere.
In this situation, is there some way of using Maven modules to store the beanstalk-maven-plugin config in a separate POM to that of the actual software project?
I think you have to solutions.
Just add the beanstalk-maven-plugin definition to your regular pom.xml. The configuration can be stored in separate properties file or provided via system properties in command line (-D option). Add beanstalk goal to command line of maven in Jenkins. So, each build will be deployed on beanstalk. Alternatively you can define yet another project in Jenkins that just runs the deployment without compilation. You can run this deployment project on scheduled basis or via projects dependencies in Jankins.
Create yet another maven project. It will just run beanstalk plugin. I personally do not see serious advantages to do this.
I think about three things:
a. I'm not sure (I'm admit I was a bit busy trying to come up with 0.2.7-RC7), but I think the Elastic Beanstalk Configuration Files are supported in Java.
So it perhaps could be a good idea to separate (I admit managing config in Beanstalker is Boring)
b. Another option is using war overlays in maven-war-plugin's overlay feature, and create a war which depends on your other war.
In my personal case, if you ask, I do have a separate deployment profile in Maven, and that feature often come in handy

Using maven to produce production ready output

I have a muti-module maven project, and I created a new module that depends on 3 other modules. (I already have a web app maven module that produces a .war file, now I need this)
This module's output is a .jar, and it has a few resources also which are:
spring context xml file
properties file
Now I want to produce a production ready folder so I can upload it to my server. I am hoping maven can do this for me.
I need the following layout:
myjar.jar
/libs/ (the 3 other maven modules that are dependancies)
/resources
Also, there are some generic dependancies that my parent pom.xml have like slf4j/log4j/ that I also need to package.
It would be cool if I could add a switch to mvn that will produce this like:
mvn clean install production
I plan on running this on my server via the command line.
I think what you are looking for is a Maven Assembly:
https://maven.apache.org/plugins/maven-assembly-plugin/
You can use profiles to disable the generation of the assembly by default (can speed up the development process).
#puce is right in that you may be best to use the Assembly Plugin. What you can't do easily is add another lifecycle 'production' to maven. If you have time you could write a plugin to do this, but you might be better off using a profile called 'production' or 'prod-deploy' to enable the coping into place on the server.
mvn clean install -Pprod-deploy
One thing to remember with maven is that it is very good at building projects in using it's conventions, but it is pretty bad at actually script things to happen out side of the build lifecycle.
I have on several occasions used external scripting tools such as ant/python/bash and groovy to first run the build using mvn then to script the deployment in a more natural language.
The intention of Maven is building not deployment in the sense to production. For this purpose i would recommend things like Chef or Puppet. From a technial point of view it's of course possible to handle such things via Maven. What also possible to build on CI solution like Jenkins. Furthermore it's possible to run a script from Jenkins to do the deployment on production.

Releasing from development into production in maven

I'm confused about the use of maven in development and production environments - I'm sure it's something simple that I'm missing. Grateful for any help..
I set up maven inside eclipse on my local machine and wrote some software. I really like how it's made things like including dependent jars very easy.
So that's my development environment. But now I want to release the project to production on a remote server. I've searched the documentation, but I can't figure out how it's supposed to work or what the maven best practice is.. Are you supposed to:
a) Also be running maven on your production environment, and upload all your files to your production environment and rebuild your project there? (Something in me baulks at the idea of rebuilding 'released' code on the production server, so I'm fairly sure this isn't right..)
b) use mvn:package to create your jar file and then copy that up to production? (But then what of all those nice dependencies? Isn't there a danger that your tested code is now going to be running against different versions of the dependent jars in the production environment, possibly breaking your code? Or missing a jar..?)
c) Something else that I'm not figuring out..
Thanks in advance for any help!
You're supposed to have your code under version control (and you never "upload" files to another machine, you "download" them from the Version Control System if required).
You're supposed to package your code in a format (a WAR, an EAR, another kind of bundle) that can be deployed on the production environment for execution. Such bundles typically include the dependencies. To build more complex bundles, the Maven Assembly Plugin can help.
Maven generated artifacts (JARs, WARs, whatever) should be shared via a remote repository (and thus deployed - I mean mvn deploy here - to this remote repository). A remote repository can be a simple file system served via a web server or a more advanced solution like Nexus.
Development is usually done using SNAPSHOT dependencies (e.g. 1.0-SNAPSHOT). At release time, you're supposed to change the version into a "fixed" version (e.g. 1.0) and some other bits from your pom.xml, run the build to check that everything is ok, commit the modified pom.xml, create a tag in the VCS, promote the versions to a new SNAPSHOT (e.g. 1.1-SNAPSHOT) in the pom.xml, commit the new pom.xml in the VCS. The entire process require some work but this can be automated using the Maven Release Plugin.
On the production environment, get the artifacts to be deployed from the remote repository and deploy them (some projects automate the deployment to the production server using Maven but that's another story).
Of course, there are variations around this (deployment to production is most of time company specific) but the general idea is there.
You need to look into the Maven Assembly Plugin and the Maven Release Plugin.
When building artifact you usually state what scope the dependency has. In default scope it should be packaged in your archive. If you do not want it, use scope "provided" - in such case you have to prepare runtime environment providing the dependency. It's generaaly a bad idea to rebuild a package only for deployment.
As for deploying, you can use maven's antrun plugin to copy files locally or via scp .

Categories

Resources