Wednesday, November 21, 2012

Using Puppet to Manage Java Application Deployment

Deployment of a Java application can be done in a different ways. We can do

  • Build one jar with all exploded dependent jars and your application. You don't have to worry about your classpath.
  • Build a tarball. It is much easier using Maven assembly and Maven AppAssembly plugin to build a tarball/zip to include all dependent jars and the wrapper scripts for running application or service. AppAssembly generate the classpath in the wrapper scripts.
  • Build a war and deploy it to the container.

All above methods have the same issue: you will repeatedly deploy the same jars again and again. One of my project uses a lot of third-party libraries, Spring, Drools, Quartz, EclipseLink and Apache CXF. The whole zip file is about 67MB with all transitive dependent jars, but my application is actually less than 1MB. Every time I have to build and store such large files, and include all dependent jars without any change. Even the hard drive is much cheaper today, doing like this is still not a good practice.

It is easy to deploy my application jar and replace the old jar only each time if I don't update any dependency. Otherwise, it is still inconvenient because you have to change multiple jars.

The ideal way is to deploy the application jar and dependent jars in a directory other than the application directory on the target server, and build the classpath each time when a new version or dependency change is deployed. There are the following advantages:

  • Dependent jars only needs to be deployed once.
  • Different applications can share the same dependencies.
  • Multiple versions exist on the target server. It is much easier to rollback to the old version.
  • You save a lot of space and network traffic

You probably get the answer: Maven. Using maven, maven dependency plugin, and maven local repository, you can simply and easily implement such a system.

I have a working puppet module can do the followings:

  • setup maven from tarball;
  • setup maven settings.xml, local repository, and you maven repository on the intranet;
  • resolve the dependencies of a maven artifact: download jars into the local repository;
  • setup symlinks of dependent jars into a directory so that you don't have different copies for different applications;
  • generate a file having the classpath.

I will publish it to github once I get the time.

You can find similar puppet modules in github, like puppet-nexus and puppet-maven. They just copy the specified jars to a directory.

1 comment:

  1. Hi Ben

    What you are talking about is exactly what I'm trying to accomplish. I'm new to Puppet so I'm looking for code that could give me a kickstart. Did you publish it to github?