Interfacing a build
Overview
Dependending on the age and size of your organization you may need to support a number of build processes. Indeed, each build may even use its own build tool. Each build tool has its own way of being configured, and its own way of being invoked (including any required command parameters).

This document walks you through an example that shows you how to encapsulate your build tool so it can be incorporated into the build and deployment process.
This document assumes you have familiarized yourself with basic concepts and have setup ProjectBuilder.
Introducing Builders
Before diving right in, it is helpful to start by first introducing one of the framework base library modules, Builder. A Builder interfaces with an underlying build tool to coordinate the build life cycle for a given application component or components. A Builder provides a consistent interface to the rest of the framework, and hides the variation of build tool functionality and control. A Builder defines a set of standard commands that are used to define the life cycle the framework expects, and also defines a set of attributes needed to parameterize the calls to the underlying tools.
The following illustration shows a user calling the runBuildScript command on SimpleAntBuilder, which in turn, invokes the command ant -f build.xml. SimpleAntBuilder is a Builder, and as such, possesses the command, runBuildScript, one of several standard commands available in any Builder.

As a subtype of Builder, SimpleAntBuilder can override generic Builder commands. To be a special Builder interfacing Ant, SimpleAntBuilder overrides the runBuildScript command to use its own implementation.
As mentioned earlier, the role of a Builder is to coordinate the build life cycle for application components. This not only includes invoking a build tool (which may drive a great deal of actions such as analysis, doc generation, unit testing, etc.), but before that checks out source code (perhaps a specific branch or tag), and after the build tool has completed, takes the build artifacts and puts them into a repository for later deployment. All these actions are driven from a command workflow, Build.

Builders also have a relationship to another framework base type, Package. A Package represents any kind of build artifact that will be used during deployment. Because application architecture determines the format of the release archive, the Package type, provides a set of hook commands that subtypes can override in order to create and extract the archive. The Package command provides a number of standard commands that do not need to be overriden, as well. These commands take care of putting an artifact into the repository, registering it, and retrieving it. Builders, in effect, are producers of Packages.

Preparing simple's application source
In our example, we will automate a very trivial build process for our "simple" project. Of course, your existing applications will already be in a source repository and have an existing build procedure. The next steps will resemble what one would need to do for a brand new application source tree.
Create a source tree
All the application source files will reside in the src/ subdirectory of simple:
mkdir -p $HOME/simple/src mkdir -p $HOME/simple/src/jsp mkdir -p $HOME/simple/src/WEB-INF
Our example will build a trivial webapp.There will be two main source files: a JSP and a web.xml.
Edit $HOME/simple/src/jsp/index.jsp
<html>
<head>
<title>Simple</title>
</head>
<body>
<p>Hello! The time is now <%= new java.util.Date() %></p>
</body>
</html>
Edit $HOME/simple/src/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
'-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN'
'http://java.sun.com/dtd/web-app_2_3.dtd'>
<web-app>
<servlet>
<servlet-name>Home Page</servlet-name>
<jsp-file>/index.jsp</jsp-file>
</servlet>
</web-app>
Create a build.xml
Our example application build needs an Ant build file to build and package the release artifact.
Edit $HOME/simple/src/build.xml with the following content:
<project name="simple" default="all">
<target name="all">
<mkdir dir="${targetdir}"/>
<war destfile="${targetdir}/simple-${buildstamp}.war" webxml="${basedir}/WEB-INF/web.xml">
<fileset dir="${basedir}/jsp"/>
</war>
</target>
</project>
Later you'll see that the Builder commands will set the embedded properties: basedir, targetdir and buildstamp.
Create a CVS repo
The source files will be maintained in a local CVS source code repository. Run the following commands to create the instance and import the files:
export CVSROOT=$HOME/simple/cvsroot; # local CVS repo path cvs -d $CVSROOT init; # create the repository cd $HOME/simple/src; # change directory and import the sources cvs import -m "Importing Simple example" src tutorial start; cd ..; rm -r $HOME/simple/src; # remove the original copy. cvs co src; # check out the src dir
Noteworthy settings
Reviewing the steps taken in preparing the simple application's source tree a few noteworthy details should be highlighted:
| Setting | Example | Description |
|---|---|---|
| SCM connection | $HOME/simple/cvsroot | path to the source in the source code repository. (used by scmCheckout) |
| SCM module | src | module to checkout of the repository (used by scmCheckout) |
| source base directory | $HOME/simple/src | directory where checked out source resides (used by scmCheckout and runBuildScript) |
| build file path | src/build.xml | the build file to invoke (used by runBuildScript) |
Each of these setting details will be recorded in the type defintion declared in the next section.
A Builder for Ant
With a bit of familiarity with Builders and Packages, we are ready to proceed with actually defining a simple Builder. This section will show you how to make SimpleAntBuilder, a Builder subtype that will interface with Ant.
The class diagram below shows the inheritance hierarchy of the SimpleAntBuilder type. It inherits a number of commands from its super types but will override runBuildScript.

There is a typical type development cycle used when introducing a new type. The process is broken down into several routine steps:
- Define the type
- Define an instance of the type
- Test a type command
- Repeat
Two tools will be used during the process. ProjectBuilder to create model artifacts and a text editor to edit type.xml, the type definition file.
Define the SimpleAntBuilder Type
Create the type
Use ProjectBuilder's create-type command to initialize the SimpleAntBuilder type. You can run create-type without a full set of arguments and it will prompt you for the remaining needed input (input is in bold):
ctl -p default -m ProjectBuilder -c create-type -- -supertype Builder Name of type: SimpleAntBuilder Description of type: A simple Builder to interface with Ant Directory where module files will be created: [/ctier/ctl/src] /ctier/ctl/src Creating module definition files in directory: /ctier/ctl/src ... Initializing type module from template dir: /ctier/ctl/depots/default/modules/ProjectBuilder/templates/boilerplate ... Created dir: /ctier/ctl/src/modules/SimpleAntBuilder Copying 1 file to /ctier/ctl/src/modules/SimpleAntBuilder Creating directory structure... Created dir: /ctier/ctl/src/modules/SimpleAntBuilder/bin Created dir: /ctier/ctl/src/modules/SimpleAntBuilder/commands Created dir: /ctier/ctl/src/modules/SimpleAntBuilder/objects Created dir: /ctier/ctl/src/modules/SimpleAntBuilder/templates Copying /ctier/ctl/depots/default/modules/ProjectBuilder/templates/types/Managed-Entity to /ctier/ctl/src/modules/SimpleAntBuilder ... Initializing type module from template dir: /ctier/ctl/depots/default/modules/ProjectBuilder/templates/types/Managed-Entity ... Copying 2 files to /ctier/ctl/src/modules/SimpleAntBuilder Define commands and attributes in this file: /ctier/ctl/src/modules/SimpleAntBuilder/type.xml
A new directory called "SimpleAntBuilder" will be created in the basedir $CTIER_ROOT/ctl/src and populated with various files and subdirectories. The last line refers you to the type.xml file that contains the initial type definition for SimpleAntBuilder. A snippet is shown below:
<type
name="SimpleAntBuilder"
role="concrete"
uniqueInstances="true">
<!-- description of the Type -->
<description>A simple Builder to interface with Ant</description>
<!-- supertype/typereference: defines the supertype of the current Type -->
<supertype>
<typereference name="Builder"/>
</supertype>
...
Open the $CTIER_ROOT/ctl/src/modules/SimpleAntBuilder/type.xml file in your favorite text editor.
Define attribute defaults
Attribute defaults are used to provide default values used to parameterize commands. These appear as entity.attribute.<attribute-name> properties and these properties are often used to default command option values. Cut and paste the following fragment into the type.xml replacing the <attributes> ... </attributes> content already there. Ensure that you have made the content a sub-element of <type>.
<attributes>
<attribute name="basedir" type-property="deployment-basedir"/>
<attribute name="targetdir" type-property="deployment-install-root"/>
<attribute-default name="scmBinding" value="cvs"/>
<attribute-default name="scmLabel" value=""/>
<attribute-default name="scmConnection" value="${user.home}/simple/cvsroot"/>
<attribute-default name="scmModule" value="src"/>
<attribute-default name="importMin" value="1"/>
<attribute-default name="importMax" value="1"/>
<attribute-default name="packageExtension" value="war"/>
<attribute-default name="packageFilebase" value="simple"/>
<attribute-default name="packageInstallroot" value="${user.home}/simple/tomcat/webapps"/>
<attribute-default name="packageType" value="war"/>
<attribute-default name="buildFile" value="${user.home}/simple/src/build.xml"/>
<attribute-default name="buildTarget" value="all"/>
</attributes>
Define the runBuildScript command
The initial type.xml produced by create-type has a number of comments that show command definition examples. To define a command, you use the <command> tag. Cut and paste the following fragment into the type.xml replacing the <commands>... </commands> content already there. Ensure that you have made the content a sub-element of <type>.
<commands>
<command name="runBuildScript"
description="invokes the Ant build"
command-type="Command"
daemonized="false" >
<!-- ** for unix use "sh" -->
<execution-string>sh</execution-string>
<argument-string>ant -Dbasedir=${opts.basedir} -Dbuildstamp=${opts.buildstamp} -Dtargetdir=${opts.targetdir} -f ${opts.buildfile} ${opts.target}</argument-string>
<!-- ** for windows use "cmd.exe" -->
<!--execution-string>cmd.exe</execution-string-->
<opts>
<opt parameter="basedir" description="directory where build resources reside"
required="false" property="opts.basedir" type="string"
defaultproperty="entity.attribute.basedir"/>
<opt parameter="targetdir" description="directory build artifacts will be written"
required="false" property="opts.targetdir" type="string"
defaultproperty="entity.attribute.targetdir"/>
<opt parameter="buildstamp" description="build identifier"
required="false" property="opts.buildstamp" type="string"
defaultproperty="entity.attribute.buildstamp"/>
<opt parameter="buildfile" description="build file to execute"
required="false" property="opts.buildfile" type="string"
defaultproperty="entity.attribute.buildFile"/>
<opt parameter="target" description="build target to evaluate"
required="false" property="opts.target" type="string"
defaultproperty="entity.attribute.buildTarget"/>
</opts>
</command>
</commands>
The XML above, defines the runBuildScript command as a bash script, supplying the execution-string and argument-string parameters. Several command options are also defined. These tags support passing command line arguments. It turns out that these are the same command options defined by the Builder base type so we are showing how SimpleAntBuilder is maintaining the same command syntax.
The example script code shown above uses Ant property references of the form, opts.<param-name>. The CTL task, get-opts, parses the command line and sets these properties. These properties can then be referenced by the command.
1. source $CTL_BASE/etc/profile; # this sets ANT_HOME
2. PATH=$PATH:$ANT_HOME/bin
Build the type
Use the ProjectBuilder's build-type command to build the SimpleAntBuilder type. Specify the optional arguments -upload and -deploy to also upload the model artifact to Workbench, and then deploy it back to your working context.
ctl -p default -m ProjectBuilder -c build-type -- -type SimpleAntBuilder -upload -deploy Base directory where module source files reside [/ctier/ctl/src] /ctier/ctl/src Building type using the buildmodule.xml via classloader converting type.xml for module: SimpleAntBuilder packaging module: SimpleAntBuilder Building jar: /ctier/ctl/target/SimpleAntBuilder-1.jar uploading SimpleAntBuilder module jar in /ctier/ctl/target to server ... processing files in directory: /ctier/ctl/target Uploading jar: /ctier/ctl/target/SimpleAntBuilder-1.jar to server: localhost ... deploying new build of SimpleAntBuilder module to local installation ... Getting: http://localhost:8080/webdav/default/publish/modules/SimpleAntBuilder-head.jar To: /home/tutorial/ctl_base/var/SimpleAntBuilder-head.jar Created dir: /home/tutorial/ctl_base/depots/simple/modules/SimpleAntBuilder Expanding: /home/tutorial/ctl_base/var/SimpleAntBuilder-head.jar into /home/tutorial/ctl_base/depots/simple/modules/SimpleAntBuilder Getting: http://localhost:8080/webdav/default/publish/modules/Builder-3.jar To: /home/tutorial/ctl_base/var/Builder-3.jar Expanding: /home/tutorial/ctl_base/var/Builder-3.jar into /home/tutorial/ctl_base/depots/simple/modules/Builder
The SimpleAntBuilder type has now been loaded into the server and is now part of the greater project model. If you like, go to Workbench and view the type there. If you click on the "Commands" tab, you should see the runBuildScript command defined.

Define the SimpleAntBuilder Object
With the SimpleAntBuilder type defined, all that is left before we can test it, is to create an instance of it. To do that save the XML content below into a file and load it via the load-objects command.
File listing: simpleAntbuilder.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project PUBLIC "-//ControlTier Software Inc.//DTD Project Document 1.0//EN"
"project.dtd">
<project>
<deployment
name="tutorial" type="SimpleAntBuilder"
description="A simple Builder to interface with Ant"
basedir="${user.home}/simple/src"
installRoot="${user.home}/simple/target"
>
<!--
**
** References where the builder is hosted:
** (replace localhost with the name of your node)
-->
<referrers replace="false">
<resource type="Node" name="localhost"/>
</referrers>
</deployment>
</project>
Load the data
ctl -p default -m ProjectBuilder -c load-objects -- \ -filename simpleAntbuilder.xml
Install the builder
ctl-depot -a install "Install" command running for object: (SimpleAntBuilder) tutorial
The load-objects command takes the input from the XML file and registers an instance of SimpleAntBuilder in the project model. The ctl-depot command deploys it to the CTL instance. You can run the Get-Properties command to look at the information about the new object:
ctl -p default -t SimpleAntBuilder -o tutorial -c Get-Properties -- -print [MULTI_LINE] # tutorial [SimpleAntBuilder] # A simple Builder to interface with Ant ## Attributes ## * basedir: "/Users/ctier/simple/src" * buildFile: "/Users/ctier/simple/src/build.xml" * buildTarget: "all" * importMax: "1" * importMin: "1" * packageExtension: "war" * packageFilebase: "simple" * packageInstallroot: "/Users/ctier/simple/tomcat/webapps" * packageType: "war" * scmBinding: "cvs" * scmConnection: "/Users/ctier/simple/cvsroot" * scmLabel: "" * scmModule: "src" * targetdir: "/Users/ctier/simple/target" ## Dependencies ## ### Parent Dependencies ### 1. strongbad [Node] ### Child Dependencies ### - - - [/MULTI_LINE]
If you go to Workbench, and navigate back to the SimpleAntBuilder type, you will see the new object in the "Objects" tab.

The SimpleAntBuilder object is now ready for use.
Test the runBuildScript command
The SimpleAntBuilder type has been defined and an instance of it has been created and deployed to your working CTL project. You are ready to try the command. Run it with arguments like so:
ctl -p default -t SimpleAntBuilder -o tutorial -c runBuildScript -- -buildstamp 123
Buildfile: /Users/ctier/simple/src/build.xml
all:
[war] Building war: /Users/ctier/simple/target/simple-123.war
BUILD SUCCESSFUL
As defined, runBuildScript invokes the ant -f build.xml command string, passing in the basedir, targetdir and buildstamp. The trivial build results in the creation of a simple release archive, a war file: $HOME/simple/target/simple-123.war.
The Build life cycle command
The runBuildScript command is just one part of the over all build life cycle, implemented in the standard Builder workflow, Build.
To drive the whole build cycle, run the Builder's Build workflow command:
ctl -p default -t SimpleAntBuilder -o tutorial -c Build -- -buildstamp 123 Start: "Run the build cycle." commands: scmCheckout,setBuildstamp,runBuildScript,repoImport ... begin workflow command (1/4) -> "scmCheckout -buildstamp 123" cvs checkout: Updating src ... begin workflow command (2/4) -> "setBuildstamp -buildstamp 123" ... ... begin workflow command (3/4) -> "runBuildScript -buildstamp 123" ... ... begin workflow command (4/4) -> "repoImport -buildstamp 123" ... ... Puted 1 file to http://localhost:8080/jackrabbit/repository/workbench/pkgs/default/war/wars/simple-123.war ... Completed: execution time: 13.656 sec
Build begins by running the scmCheckout command which runs the CVS checkout of simple's src directory. It then runs the runBuildScript command you ran directly earlier. After that completes, Build runs repoImport. The repoImport command looks in the target directory for matching artifacts and then puts them into the repository, recording information about the package in the model. Go to the toplevel "Packages" tab in Workbench and navigate to the "war" type to view a new instance created by the Builder.
Next step: Deployment
With a Builder subtype created, to invoke simple's build process, the next step is to deploy the built artifact.


