Customizing with Chico

This page describes how to configure a Chico-based webapp for use in a custom website.


Configurable Spring Wiring

Chico-based projects such as Danno and Emmet use Spring dependency injection to configure the various servlets that implement a website. The configuration is represented by Spring XML wiring files that contain various parameters and wire up various "beans" to perform application specific tasks.

Building a Danno or Emmet configuration from scratch would be a daunting task, so the base distributions come Spring wiring files that are intended to implement the common case. These files may be found in the various *.webapp directories in the respective projects; look in the src/main/webapp/WEB-INF directories. In addition, the Danno project includes some "demosite" directories that serve as possible templates for site-specific customization.

Major customizations of Danno and Emmet are likely to require solid of understanding of Spring wiring files, and of the way that Spring IoC, Spring MVC, and Spring Security work. If you are not familiar with Spring, we recommend that you read (at least) the IoC and MVC chapters of the online Spring Framework Reference, and the relevant parts of the Spring Security Reference.

But as we shall see, simple customization can typically be performed by changes to simple Java property files.

Simple property customizations

In many cases, customizing Danno and Emmet to your local site requirements is simply a matter of changing some properties. For example, it is likely that you will need to configure the hostname for your server to be something other than localhost, and you may want to disable Danno's web-based administration APIs.

These customizations and many others can be implemented without editing the standard wiring files by using Chico's property customization mechanisms. These allow you to:

  • provide a value to substitute for a placeholder in the wiring files, or
  • override an existing property in the wiring files with a different value.

Placeholder substitution

Consider the following excerpt from "Danno-common.xml":

    <bean id="dannoProps" class="...">
        <property name="properties">
            <!-- Danno Controller Configuration Properties -->
            <props>
                <prop key="danno.home.url">
                    http://${danno.hostname}/${danno.container}/index.html
                </prop>
                <prop key="danno.logout.url">
                    http://${danno.hostname}/${danno.container}/logout
                </prop>
                ...
            </props>
        </property>
    </bean>

This shows two of the configuration properties for the main Danno "controller"; i.e. danno.home.url and danno.logout.url. (Lets ignore what the configuration properties actually mean, and why they are represented that way, and just focus on the issue of how you would change the property values.)

Notice that these properties have values with embedded ${...} sequences. These sequences are placeholders. When Spring processes the bean wirings specified by the XML file, all property values are scanned for placeholders, and any that are found are replaced with values defined in a substitution.properties file. For example, all occurrences of ${danno.hostname} would be replaced with your site's hostname (or localhost as a default), and all occurrences of ${danno.container} would be replaced by your site's danno container name (or danno as a default.)

So, to configure a specific hostname for your site, you simply need to add an entry to the relevant substitution.properties file. So for example you might have a file that looks like the following:

# These properties are substituted into the properties, aliases 
# and classnames in the Spring wiring files.  For example, the 
# 'hostname' property provides a value to replace the '$\{hostname\}' 
# placeholder.  Note that placeholders in property values are also
# replaced.

hostname=www.example.com
db.hostname=internal.example.com
danno.container=annotations
dannotate.container=annotator

At runtime, the site tailoring mechanism looks for the substitution.properties file on the webapp's Java classpath, so you would normally put the file in the webapp's WEB-INF/classes directory. In fact, that directory will typically contain other substitution properties files that supply the default values for substitutions. For example, a Danno webapp will include a default-danno-substitution.properties file that looks something like this:

# This file should not be edited or overlaid in a "site" project

hostname=localhost
danno.realhostname=${hostname}
danno.hostname=${hostname}
mde.hostname=${hostname}
db.hostname=${hostname}
danno.container=danno
mde.container=mde
tripleStore=sesame

Notice that the properties file above uses placeholders in the substitution values. These will be replaced recursively.

There are two final points to bear in mind:

  1. The mechanism that does placeholder replacement will throw an exception if it cannot find a placeholder's corresponding substitution property.
  2. Placeholders can be used in other places in the Spring wiring files. The ${tripleStore} placeholder in the example above is used in the name of a Spring alias, and if your webapp uses the Chico-specific ContextLoaderListener class you can even use placeholders in the resource names of an <import> element.

Property replacement

Now consider the following excerpt from Danno-common.xml:

    <bean id="dannoProps" class="...">
        <property name="properties">
            <!-- Danno Controller Configuration Properties -->
            <props>
                ...
                <prop key="danno.webAdmin">false</prop>
                ...
            </props>
        </property>
    </bean>

Notice that the value of the danno.webAdmin does not have any placeholders in it, so we cannot use a substitution.properties file to change it. Instead we use a "override.properties" file to replace the entire property value. For example:

# These properties are overrides for properties in the Spring wiring 
# files.  An override takes the form "beanname.propname=value"

dannoProps.danno.webAdmin=true

As above, the current Danno / Dannotate site tailoring mechanism looks for the override.properties file on the Java classpath, so they it needs to be placed in the WAR file's WEB-INF/classes directory.

The property names in the override.properties file are the names of the properties in the relevant XML file, qualified by the name of the Bean that defines the property.

The override.properties file is processed before placeholder substitution, so an override property value that contains a placeholder will be duly expanded. (Indeed, you could in theory use your own placeholders, provided that you also added the relevant properties to the substitution.properties file.)

Unlike placeholder mechanism, there is no hard requirement that you override existing properties. However, you do need to get the bean names correct, and if you do use an override to add a property that the Danno/Dannotate codebase does not understand, the property may be ignored. (It depends on the precise nature of the property.)

Creating site projects with Maven WAR file overlays

On the face of it, it is relatively straight forward to create your own site configurations. You could simply clone a *.webapp and edit it in place to make your changes. However, this approach leads to version control problems. The Chico approach is to use Maven WAR file overlays to overlay a standard configuration with site-specific customizations.

The Maven WAR plugin has the ability to assemble a WAR file from the files in one or more other WAR files. The resulting WAR file contains the files from the first input WAR files "overlaid" with the files from the second WAR file, and so on. The result is finally overlaid with files from the current Maven project. The project POM specifies the WAR projects to be overlaid and their respective overlay order, and also can declare that specific files are excluded. (For full details, refer to the Maven Overlays documentation.)

The recommended procedure is as follows:

  1. Choose one of the standard template modules as the template for your site.
  2. Copy the template module, giving it a new name. This copy will be your site project. If you have copied a tree that you checked out from a source code repository, prune the existing version control directories from the copy; e.g.
         rm -rf `find $PROJ -name .svn`
  3. Edit your site project's pom.xml file, changing at least the groupId, artifactId, name, version and description elements, and any others as required.
  4. Modify the existing files in the site project's src/main tree as required. For example, many simple configuration changes are best made by editing the substitution.properties and override.properties files as described in the previous sections.
  5. Override other configuration files (XML, JSP or whatever), as described in the next section
  6. Use the Maven tool to build and install the base WAR files that your project depends on; e.g. the Danno, Dannotate and/or Emmet WAR files.
  7. Use the Maven tool to build and install your site's WAR file.
  8. Deploy the WAR file, start Tomcat and test your site, repeating until you are satisfied.
  9. Commit your site project to your local version control.

    If you follow this procedure, next time you upgrade or update the base project tree, you should only need to merge changes to the Spring configuration files that you have overridden in your site project.

    (OK, so the last paragraph is a bit optimistic. If the base project's Spring wiring files have changed significantly, you may need to adjust the contents of your site's "substitution.properties" and "override.properties", and other configuration file overrides. However, the task should be more manageable than if you had simply hacked on the Spring wiring files.)

Overriding WAR file content in a custom site project

With Maven WAR file overlays, the WAR file is built by successively layering the filesets from each of the dependent WARs on top of each other, followed finally by any files defined by the current project. So, to replace a standard JSP, Spring wiring file or indeed any other file, you simply need to put the replacement file in the appropriate place in the custom site project's src tree, and Maven will take care of the rest.

The procedure is simply:

  1. Identify the file or files to be replaced in the src tree of the dependent module.
  2. If necessary, create corresponding directories in the site project's src tree.
  3. Copy the files to be overriden across to the corresponding locations in the site tree.
  4. Edit the copied files as required.

    You can also add new content in your custom site, and there is even a way to exclude nominated files and directories from the dependent projects.