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

Create and deploy a project distribution 

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 6 works out of the box. This page explains how to create such a distribution, and how, once created, you can deploy this distribution to an existing Tomcat 6 installation.

Deployment diagram

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

 

http://www.onehippo.org/binaries/ninecolumn/content/gallery/connect/library/diagram5.jpg

${catalina.base}/common/lib/ will be the location of container-wide artifacts that must be pre-installed manually before deploying the project distribution. These will be loaded by Tomcat's common class loader.

${catalina.base}/shared/lib will be the location where Tomcat's shared class loader will load artifacts from. The shared class loader is common to all deployed web applications and enables communication between them. For instance, because the site application talks to the repository that is running inside the cms application, the interface to the repository (i.e. hippo-repository-api) must be shared between them.

Finally ${catalina.base}/conf is where installation-specific configuration can be put. For example, a development environment will typically use a different database setup 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.

Creating a project distribution

If you open your root project's POM descriptor 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 install
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/gettingstarted-1.01.00-distribution.tar.gz
-rw-r--r-- 0/0        51314902 2011-05-01 12:16:30 webapps/cms.war
-rw-r--r-- 0/0        24134018 2011-05-01 12:16:42 webapps/site.war
-rw-r--r-- 0/0            5144 2011-05-01 12:33:15 conf/log4j.xml
-rw-r--r-- 0/0            5002 2011-05-01 08:56:52 conf/log4j.dtd
-rw-r--r-- 0/0          367444 2009-03-04 20:19:25 shared/lib/log4j-1.2.14.jar
-rw-r--r-- 0/0           65237 2011-04-30 12:13:09 shared/lib/hippo-repository-api-2.19.04-SNAPSHOT.jar
-rw-r--r-- 0/0           10650 2011-04-30 12:16:23 shared/lib/hippo-cms-sso-2.19.04-SNAPSHOT.jar
-rw-r--r-- 0/0           16812 2011-04-30 12:14:29 shared/lib/hippo-repository-builtin-2.19.04-SNAPSHOT.jar
-rw-r--r-- 0/0           10952 2011-04-30 12:22:29 shared/lib/hippo-addon-publication-workflow-common-2.19.04-SNAPSHOT.jar
-rw-r--r-- 0/0          113072 2011-04-30 12:38:04 shared/lib/hst-api-2.21.02-SNAPSHOT.jar
-rw-r--r-- 0/0          113825 2011-04-30 12:38:15 shared/lib/hst-commons-2.21.02-SNAPSHOT.jar

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

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.xml</source>
      <outputDirectory>/conf</outputDirectory>
      <destName>log4j.xml</destName>
    </file>
    <file>
      <source>conf/log4j.dtd</source>
      <outputDirectory>/conf</outputDirectory>
      <destName>log4j.dtd</destName>
    </file>
  </files>
  <dependencySets>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <outputDirectory>/shared/lib</outputDirectory>
      <scope>provided</scope>
      <includes>
        <include>org.onehippo.cms7:hippo-repository-api</include>
        <include>org.onehippo.cms7:hippo-repository-builtin</include>
        <include>org.onehippo.cms7:hippo-cms-sso</include>
        <include>org.onehippo.cms7:hippo-addon-publication-workflow-common</include>
        <include>org.onehippo.cms7.hst:hst-api</include>
        <include>org.onehippo.cms7.hst:hst-commons</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 suit your needs. 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 project POM must define this artifact as a provided dependency.

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

Deploying your project to a Tomcat 6 installation

Deploying the project distribution to Tomcat involves two simple steps: unpacking the distribution inside the root directory of the Tomcat 6 installation and tweaking Tomcat's default catalina.properties file. However, before you can do this, you need to ensure that the Tomcat installation you are going to deploy to has the required container-wide artifacts installed.

Setting up Tomcat

Note that from Hippo project archetype version 1.03.04 onward the common libraries are also packaged with the distribution so you don't need to install them by hand. You will still need to tweak the catalina.properties file however, as described below.

Assuming you have installed the Tomcat 6 stock distribution such as can be downloaded from here, you will have to download the following artifacts and install them in ${catalina.base}/common/lib:

javax.jcr:jcr:2.0:jar
javax.jdo:jdo2-api:2.3-eb:jar
org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1:jar
javax.mail:mail:1.4.3:jar

Also, Tomcat 6 no longer defines common/lib as a location from where the common class loader loads libraries. You will need to configure this.

Open conf/catalina.properties and add the following paths to the common.loader property:

,${catalina.base}/common/classes,${catalina.base}/common/lib/*.jar

Installing the distribution.

Now you are ready to unpack the distribution. On the command line open a terminal and change directories to your ${catalina.base} directory. Then run the command:

tar -xvf myhippoproject-1.01.00-distribution.tar.gz

You will see the contents of the distribution being extracted to the correct locations.

Next you will need to tweak the file conf/catalina.properties. The stock distribution of Tomcat 6 no longer defines a shared classloader so you need to configure it.

Open conf/catalina.properties and use the following settings:

shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar

Tweaking the Tomcat startup settings.

Lastly, it is necessary to let your application know where to find any environment-specific configuration files it needs. Although both the CMS and the HST site ship with pre-packaged configuration files, both of these will typically need to be overridden.

The repository that comes with the CMS war is configured by a file called repository.xml. This is the place where you would specify for example the database settings the repository is to use. Put your custom repository.xml inside ${catalina.base}/conf and start up Tomcat by passing in the system property -Drepo.config=file:${CATALINA_BASE}/conf/repository.xml.

Overriding the HST site configuration is slightly different. For specifying the HST config properties file you must use the context parameter hst-config-properties. You have two options available here: put it in the web.xml descriptor as a <context-param> element, or provide a Tomcat context.xml file inside the ${catalina.base}/conf directory and specify the parameter there. The latter is the preferred method because then your customization won't be overwritten the next time you update the project distribution.

Finally, as we saw earlier, the project distribution includes a log4j configuration file. To let log4j know the location of this file, start up Tomcat with the system property -Dlog4j.configuration=file:${CATALINA_BASE}/conf/log4j.xml

The most convenient way to pass these properties to Tomcat is to create the file ${catalina.base}/bin/setenv.sh. This file is automatically invoked by Tomcat's startup script before starting the container. Here is an example of what that file might look like:

JAVA_HOME=/usr/java/jre1.6.0

REP_OPTS="-Drepo.upgrade=false -Drepo.config=file:${CATALINA_BASE}/conf/repository.xml"
L4J_OPTS="-Dlog4j.configuration=file:${CATALINA_BASE}/conf/log4j.xml"
JVM_OPTS="-server -Xmx512m -Xms128m -XX:PermSize=128m"

CATALINA_OPTS="${JVM_OPTS} ${REP_OPTS} ${L4J_OPTS}"

Notice the permsize JVM setting. Experience has shown that you need to set it at least to 128 MB or you will run out of memory very soon!

JVM Proxy Configuration

If the JVM is configured with a proxy host, make sure that localhost is excluded;

-Dhttp.proxyHost=proxy.mydomain -Dhttp.proxyPort=8080 -Dhttp.nonProxyHosts=127.0.0.1

One last suggestion.

The Tomcat 6 stock distribution ships with several web applications already installed. These include an example web application, a web application that contains Tomcat documentation, and manager applications. Unless you have a need for any of these, we suggest removing them in order to reduce the memory footprint of Tomcat. The web applications you can remove safely are all other applications besides your own: i.e. docs, examples, host-manager, manager, and ROOT.