Maven - Separating Deployment & Project - java

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

Related

Jenkins building for different environments

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.

Eclipse and maven dependency during development

I do have own developed Java library (MyLib), which I later publish on private Maven repository and have it as Maven dependency in another webapp project (MyWebapp). If I have both projects - MyLib and MyWebapp at the same time opened in Eclipse - is there a way somehow to configure MyWebapp so, that local changes made to MyLib would be directly added to MyWebapp while building/deploying it? The issue is that during development it is not really comfortable always to make some changes in MyLib, make a build, deploy to Maven repository and then make a MyWebapp build, deploy it and only then I can see how the changes are affecting the webapp project...
I would like to reduce the overhead while developing and willing to see how changes are working out. Of course when it comes to real releases the above described flow does really make sense and works great.
Thanks!
There is no simple "just tick this option" solution, unfortunately. You can chose between these options:
Convert MyLib into a Maven module and add it to the sources of MyWebapp. This, of course, will make it harder later to reuse the library alone.
Stop deploying the application. If you look at the classpath in Eclipse, m2e should have added the dependency as a project from the workspace (instead of depending on the JAR in the repository). If not: There is an option for this.
The next step is to create another project which depends on Jetty and MyWebapp. Create a Java application in there (i.e. a file with main()) which creates a Jetty server and configure it to use the current classpath. That way, you can start the webapp just like any other Java application without deploying - Jetty will simply load classes from the classpath that m2e assembled.

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 .

Making a Java Web Application build in one step

Step two of "The Joel Test: 12 Steps to Better Code" states "Can you make a build in one step?". My answer to this is currently no. My application is structured as follows:
+
+-MyApp // this is just a vanilla Java Application
+-MyWebApp // this Dynamic Java Web Application (deployed Tomcat and launches
// a thread contained in MyApp)
+-MyCommonStuff // these are common classes shared between MyApp and MyWebApp
// Ex. Database access code & business classes
In order to build and deploy my software I perform the following steps:
1. Checkout MyApp, MyWebApp, MyCommonStuff from svn
2. build MyCommonStuff.jar and copy to a "libs" directory
3. build MyApp and copy to a "libs" directory
4. build MyWebApp.war (Ant build.xml file specifies where MyApp.jar and MyCommonStuff.jar are located)
5. The deploy portion of build.xml used Tomcat deployment tasks to deploy to a tomcat server.
My question is does the Joel rule above apply to this scenario. i.e. should there be a "master" build script which executes steps 1. to 5.?
Should the script just be a normal #/bin/sh script or are there tools I can leverage. My preference would be stick to using Ant and linux console commands.
Thanks
You can (and should) use maven2. It supports everything required (via plugins). You just need to conform to its directory conventions.
In addition I'd suggest a Continous Integration Engine, which will take your maven configuration and execute and deploy everything. Hudson and TeamCity are good options.
An alternative to Maven, if you just want to use Ant, is Ivy. This is just a dependency manager, a bit like Maven but without all the other stuff Maven does.
I would suggest using one of the two. If you have a project with dependencies like this, you're going to make it so much easier for yourself if you store them in a central repository and use a dependency manager to include them!
You should do a global Ant script, calling all little ant parts through the Ant ant task.
Edit after reading other answers : you should also use maven. But if Maven is really overkill, and you just want to launch the whole build in one step, use a global build.xml

Categories

Resources