Create a Project Distribution - BloomReach Experience - Open Source CMS

This article covers a Hippo CMS version 10. There's an updated version available that covers our most recent release.

10-12-2015

Create a Project Distribution

Introduction

Goal

Package your project as a distribution that is ready to be deployed in a Tomcat installation in an environment.

Background

At the end of a development iteration you need to be able to package your project and deploy it to a test, an acceptance and eventually a production server. If you have set up your project with the Hippo archetype, creating a project distribution for Tomcat works out of the box. This page explains how to create such a distribution.

Deployment Diagram

Below is a diagram that depicts the structure of the deployment we are aiming at.

(Legend: blue = Hippo out-of-the-box, light grey = third party, red = environment-specific)

  • Apache Tomcat container
    ​Two war files are deployed in the Tomcat container (${catalina.base}/webapps/):
    • Hippo CMS
      cms.war contains both the CMS authoring application and the content repository, as well as the repository bootstrap data packaged as jar files. The bootstrap data is used to bootstrap the content repository during the first deployment, and optionally on subsequent deployments depending on the deployment settings
    • Hippo Site
      site.war contains the delivery application (HST jars) as well as a repository connector which provides access to the content repository through the Hippo API jars in the shared classloader (see below).
  • Common classloader
    ${catalina.base}/common/lib/ is the location of container-wide artifacts. These will be loaded by Tomcat's common classloader.

  • Shared Classloader
    ${catalina.base}/shared/lib is the location where Tomcat's shared classloader will load artifacts from. This classloader is shared between all deployed web applications and enables communication between them. For instance, because the site application communicates with the repository that is running inside the cms application, the interface to the repository (i.e. hippo-repository-api) must be shared between them.
  • Configuration Directory
    Finally ${catalina.base}/conf is where environment-specific configuration can be put. For example, a development environment will typically use a different database configuration than a production environment and so the project distribution might not deliver the configuration settings specific to the production environment. Those can be configured here.
The distribution directory structure is designed as a generic 'baseline' and works out-of-the-box when unpacking the distribution in a default Tomcat installation.
However please note that common libraries (in common) and environment-specific configuration (in conf) are typically configured at container level (e.g. see Configure the Application Server (Apache Tomcat on Linux)). When deploying a distribution in such an environment only the webapps and shared directories (blue in the diagram above) should be unpacked. The deployment instructions reflect this.

Creating a Project Distribution

If you open your project's primary POM file and scroll to the profile section, you will find a profile with the id 'dist' there. This profile configures the Maven Assembly Plugin that is used to create a distribution of your project. To create a distribution run the following commands:

mvn clean verify
mvn -P dist

A tar.gz distribution file has now been created in the target directory of the main project. Let's inspect the contents of that file:

$ tar -tvf target/myhippoproject-1.01.00-SNAPSHOT-distribution.tar.gz 
-rw-r--r--  0 johndoe  staff 83573784  4 Aug 17:05 webapps/cms.war
-rw-r--r--  0 johndoe  staff 28133110  4 Aug 17:05 webapps/site.war
-rw-r--r--  0 johndoe  staff     5353 15 Jul 04:46 conf/log4j.xml
-rw-r--r--  0 johndoe  staff     5016 15 Jul 04:46 conf/log4j.dtd
-rw-r--r--  0 johndoe  staff      853 15 Jul 04:46 conf/context.xml
-rw-r--r--  0 johndoe  staff    15649 11 Mar 09:55 common/lib/geronimo-jta_1.1_spec-1.1.jar
-rw-r--r--  0 johndoe  staff    69246 11 Mar 09:55 common/lib/jcr-2.0.jar
-rw-r--r--  0 johndoe  staff   521157 11 Mar 09:55 common/lib/mail-1.4.7.jar
-rw-r--r--  0 johndoe  staff     8869 11 Mar 09:56 shared/lib/slf4j-log4j12-1.7.6.jar
-rw-r--r--  0 johndoe  staff    28688 11 Mar 09:56 shared/lib/slf4j-api-1.7.6.jar
-rw-r--r--  0 johndoe  staff   489884 11 Mar 09:56 shared/lib/log4j-1.2.17.jar
-rw-r--r--  0 johndoe  staff    16515 11 Mar 09:56 shared/lib/jcl-over-slf4j-1.7.6.jar
-rw-r--r--  0 johndoe  staff    31115 14 Jul 06:59 shared/lib/hippo-cms7-commons-2.0.0.jar
-rw-r--r--  0 johndoe  staff    32641 14 Jul 06:59 shared/lib/hippo-services-2.0.0.jar
-rw-r--r--  0 johndoe  staff   119955 14 Jul 06:59 shared/lib/hippo-repository-api-3.0.0.jar
-rw-r--r--  0 johndoe  staff    23963 14 Jul 06:59 shared/lib/hippo-repository-builtin-3.0.0.jar

There are two web applications packaged as war files inside a directory called webapps, a bunch of libraries in a directory called shared/lib, another set in a directory called common/lib, and some configuration files such as a log4j descriptor and a Tomcat context descriptor in the conf directory. This in fact is the directory layout Tomcat uses to load the different artifacts your project delivers. Simply unpacking this distribution in the root directory of a Tomcat installation will put these artifacts in the correct locations.

Customization

Internally the Maven Assembly Plugin is configured by an assembly descriptor. This descriptor is located at src/main/assembly/distribution.xml.

Currently this file looks like this:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
  <id>distribution</id>
  <formats>
    <format>tar.gz</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <files>
    <file>
      <source>cms/target/cms.war</source>
      <outputDirectory>/webapps</outputDirectory>
      <destName>cms.war</destName>
    </file>
    <file>
      <source>site/target/site.war</source>
      <outputDirectory>/webapps</outputDirectory>
      <destName>site.war</destName>
    </file>
    <file>
      <source>conf/log4j-prod.xml</source>
      <outputDirectory>/conf</outputDirectory>
      <destName>log4j.xml</destName>
    </file>
    <file>
      <source>conf/log4j.dtd</source>
      <outputDirectory>/conf</outputDirectory>
      <destName>log4j.dtd</destName>
    </file>
    <file>
      <source>conf/context.xml</source>
      <outputDirectory>/conf</outputDirectory>
      <destName>context.xml</destName>
    </file>
  </files>
  <dependencySets>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <outputDirectory>/common/lib</outputDirectory>
      <scope>provided</scope>
      <includes>
        <include>javax.jcr:jcr</include>
        <include>org.apache.geronimo.specs:geronimo-jta_1.1_spec</include>
        <include>javax.mail:mail</include>
      </includes>
    </dependencySet>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <outputDirectory>/shared/lib</outputDirectory>
      <scope>provided</scope>
      <includes>
        <include>org.onehippo.cms7:hippo-cms7-commons</include>
        <include>org.onehippo.cms7:hippo-services</include>
        <include>org.onehippo.cms7:hippo-repository-api</include>
        <include>org.onehippo.cms7:hippo-repository-builtin</include>
        <include>org.slf4j:slf4j-api</include>
        <include>org.slf4j:jcl-over-slf4j</include>
        <include>org.slf4j:slf4j-log4j12</include>
        <include>log4j:log4j</include>
      </includes>
    </dependencySet>
  </dependencySets>
</assembly>

If you have custom needs, such as an additional web application or a shared library you want packaged, modify this descriptor to your liking. Most cases should be self-explanatory by looking at the contents of the provided descriptor. For instance, to package an additional shared artifact you would add an <include> element with the groupId:artifactId coordinates of that artifact next to the ones that are already defined inside the dependency set. Make sure that it is in fact defined as a provided-scoped dependency in your POM or the assembly plugin won't be able to resolve the artifact.

Another common use case involves having to package a container-wide artifact for deployment to ${catalina.base}/common/lib, so that it will be loaded by Tomcat's common class loader. This is for instance the case with JDBC drivers that you want to configure as a JNDI DataSource in Tomcat. You can achieve this by adding an additional dependency set with the output directory common/lib. Here is an example that packages the MySQL driver:

    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <outputDirectory>/common/lib</outputDirectory>
      <scope>provided</scope>
      <includes>
        <include>mysql:mysql-connector-java</include>
      </includes>
    </dependencySet>

Again, your projects primary POM descriptor must define this artifact as a provided dependency.

If you have requirements beyond this, refer to the Maven Assembly Plugin descriptor documentation here.

Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?