Using ProjectBuilder
From ControlTier
Contents |
Overview
- Watch a short screencast on how to get started!
ProjectBuilder is a Builder used to manage Project Content for users that prefer to maintain the project as a set of text-based source files maintained in an SCM repository. You can use ProjectBuilder to define types and build module libraries, load resource data, even generate a Forrest documentation site.
For type and module development, ProjectBuilder supports a typical edit, build, test methodology familiar to most developers wherein, a set of source files maintained in a source code repository are developed using familiar text editing tools, and ProjectBuilder builds and deploys them, so that the results can be distributed and used.
Note:
- The Workbench application still serves as a useful tool along side ProjectBuilder. Since it manages the active model for the project, it allows a user to get an integrated view of the types and resource model. Besides offering a visualization layer to the active model, Workbench can also assist in the code development process. A developer can let Workbench do some code generation and then copy those generated files back into the source directory.
The diagram below shows ProjectBuilder in the context of an SCM repository and the ControlTier server. By issuing the Build command to the ProjectBuilder resource, a developer drives the project build life cycle: sources for model artifacts are checked out of the SCM, they are compiled, packaged and uploaded to the server, and finally are deployed to a working context where the artifacts can be used.
ProjectBuilder is designed to support iterative development, where there are cycles of revision to the types and resource model of the project.
Since resource definition dominates the project development process, you will become most familiar with ProjectBuilder's load-resources command. This command reads an XML file containing resource definitions and processes it into a set of CTL resource definitions.
The project development cycle is undertaken in several rough steps:
- Choose or create a project. (See: Project setup)
- Source directory structure created. The ProjectBuilder commands work relative to this base directory.
- Define resources. Each type module can contain files that define type instances. resources can be defined in XML (project.xml) and uploaded to the server via load-resources.
- Optionally, create and build a type. Types can be defined in XML (type.xml) and built, uploaded to the server and locally deployed via the build-type command.
- Build the whole project. Process all the type and resource definitions using the
Buildworkflow command.
Setting up
With the essential terms and concepts out of the way, this section turns to a practical discussion about setting up ProjectBuilder to develop an example project. The setup begins after the ControlTier server and client software have been installed and you can login to Workbench.
Note
- Specific user input is shown in bold. The "\" (backslash) character is used for line continuation.
Choose or create a project
For these examples, let us assume we'll create a project called "demo".
Note
- Your ControlTier installation may already have the "demo" project created.
See the Project setup page for instructions to create the project.
Establish Source Structure
Project source files should be organized in a standard structure. Below is a diagram showing the typical convention:
src | |--doc ;# Populated by the ProjectBuilder "generate-forrest-docs" command |--jobs ;# Job sources go here |--modules ;# Module sources go here and are organized by Type name `--resources ;# resource definition files reside here (see Resource Naming Convention below)
Make the directory hierarchy:
mkdir -p $HOME/tutorial/src mkdir $HOME/tutorial/src/doc mkdir $HOME/tutorial/src/jobs; mkdir $HOME/tutorial/src/modules; mkdir $HOME/tutorial/src/resources; mkdir -p $HOME/tutorial/target;
Once completed you should have a structure like so:
tutorial |-- src | |-- doc | |-- jobs | |-- modules | `-- resources `-- target
Resource Naming Convention Tips
- It is a good idea to establish an resource naming convention early on. See: Resource naming convention
ProjectBuilder Directories
Most of the ProjectBuilder commands work relative to a directory that contains the source files of the project. This directory is referred to as basedir. A second directory must be identified where the ProjectBuilder's build artifacts will be written. That directory is referred to as targetdir.
Setup the SCM repo
Setup for the SCM involves:
- creating (or choosing) the repository
- importing the sources
- cleanup and checkout
This example uses cvs for the source code repository.
- Note: If the CVS binary is not available on your machine, you can download and install the CVS package. Several binaries for different OS and architectures, as well as source code can be found at www.nongnu.org/cvs. Once installed, be sure to add it to your
PATHenvironment variable.
The source files will be maintained in a local CVS repository. Run the following commands to create the CVS instance and import the sources created above:
export CVSROOT=$HOME/tutorial/cvsroot; # local CVS repo path cvs -d $CVSROOT init; # create the repository cd $HOME/tutorial/src; # change directory and import the sources cvs import -m "Importing tutorial example" src tutorial start; cd ..; rm -r $HOME/tutorial/src; # remove the original copy. cvs co src; # check out the src dir
Define the ProjectBuilder resource
There are important details about the ProjectBuilder that you can define in an XML file, details like the directories mentioned above, source code management configuration, build setup, etc.
The file listing below describes the ProjectBuilder resource using this XML format. Cut and paste its
content and save it in $HOME/tutorial/src/resources/ProjectBuilder.tutorial.xml.
File listing: $HOME/tutorial/src/resources/ProjectBuilder.tutorial.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project PUBLIC "-//ControlTier Software Inc.//DTD Project Document 1.0//EN" "project.dtd">
<project>
<!--
**
** Builder settings definitions go here:
**
-->
<setting type="BuilderScmModule" name="tutorial"
description="The tutorial project source module"
settingValue="src"/>
<setting type="BuilderScmBinding" name="tutorial"
description="This is configured to use CVS"
settingValue="cvs"/>
<setting type="BuilderScmConnection" name="tutorial"
description="The project source repository connection string"
settingValue="${user.home}/tutorial/cvsroot"/>
<setting type="BuilderBuildstamp" name="tutorial"
description="The initial buildstamp value"
settingValue="0"/>
<!--
**
** Define the tutorial ProjectBuilder deployment :
**
-->
<deployment
name="tutorial" type="ProjectBuilder"
description="A ProjectBuilder to maintain the project"
basedir="${user.home}/tutorial/src"
installRoot="${user.home}/tutorial/target"
>
<!--
**
** References where the ProjectBuilder is hosted:
** (replace strongbad with the name of your node)
-->
<referrers replace="false">
<resource type="Node" name="strongbad"/>
</referrers>
<!--
**
** Setting references go here:
**
-->
<resources replace="true">
<resource type="BuilderBuildstamp" name="tutorial"/>
<resource type="BuilderScmBinding" name="tutorial"/>
<resource type="BuilderScmModule" name="tutorial"/>
<resource type="BuilderScmConnection" name="tutorial"/>
</resources>
</deployment>
</project>
Now load the definition using load-resources as shown below.
ctl -p demo -m ProjectBuilder -c load-resources -- \ -filename $HOME/tutorial/src/resources/ProjectBuilder.tutorial.xml
You have just run one of the most common ProjectBuilder commands used to maintain projects!
As a best practice, add and commit this file to the SCM:
cd $HOME/tutorial/src/resources cvs add ProjectBuilder.tutorial.xml cvs commit -m "new ProjectBuilder definition" ProjectBuilder.tutorial.xml
Define a job
Part of any project, will be the definition of various jobs. This is done in XML via job.xml.
The listing below describes a very trivial example that calls the who command.
Save the content to: $HOME/tutorial/src/jobs/job.xml
File listing: $HOME/tutorial/src/jobs/job.xml
<joblist>
<job>
<name>who's logged in?</name>
<description>Run the unix who command</description>
<additional/>
<group>sysadm/users</group>
<context>
<depot>demo3</depot>
</context>
<exec>who</exec>
<dispatch>
<threadcount>1</threadcount>
<keepgoing>true</keepgoing>
</dispatch>
</job>
</joblist>
Add and commit this file to the SCM:
cd $HOME/tutorial/src/jobs cvs add job.xml cvs commit -m "new job definition" job.xml
Define a type
You might develop your own custom types to override or add to one of the existing ones supplied in the ControlTier solution library.
Though not shown here you would use create-type to define a new one.
The create-type command generates sources files into the "modules" directory: basedir/modules/type.
If you choose to create types, be sure you add them to the SCM repository, as well.
See: First CTL module for examples on creating your own custom type.
Install the ProjectBuilder resource
With the initial project source files created and the ProjectBuilder instance defined, you are ready to install the ProjectBuilder resource to CTL so you can run the ProjectBuilder commands.
Use the "install" action in ctl-project as shown below to install the ProjectBuilder resource:
ctl-project -p demo -a install . . . "Install" command running for resource: (ProjectBuilder) tutorial
The ctl-project command installs all the resources assigned to this Node.
You can now run its commands via the shell like so: ctl -p demo -t ProjectBuilder -r tutorial -c command
Noteworthy settings
Reviewing the steps taken in preparing this source tree a few noteworthy details should be highlighted:
| Setting | Example | Description |
|---|---|---|
| SCM connection | $HOME/tutorial/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 (aka basedir) | $HOME/tutorial/src | directory where checked out source resides (used by scmCheckout and runBuildScript) |
The project build cycle
The ProjectBuilder Build command runs the normal Builder command workflow that includes the runBuildScript
command to invoke the build tool, build file and build target. ProjectBuilder provides a basic build that will process the source artifacts you maintain under basedir.
ProjectBuilder contains an Ant build.xml file that defines the following targets:
- clean: Cleans out any files in the targetdir directory
- types: Runs the
build-librarycommand to build all types in basedir/modules and uploads them as a library to the server - docs: Runs the
generate-forrest-docscommand to generate Forrest documentation for the types found in basedir/modules - resources: Runs the
load-resourcescommand for all matching files under basedir/resources loading them into the server - jobs: Runs the
load-jobscommand for all matching files under basedir/jobs and loading them into the server - all: Runs all the targets named above in the order given.
ProjectBuilder is configured by default to call the "all" target which ensures all the targets are called. You can customize the project build cycle, by creating your own build.xml file and specify your own buildTarget.
ProjectBuilder build tool configuration is done via these settings:
- BuilderBuildFile: This setting defines a path to the build file to be invoked by
runBuildScript - ProjectBuilderBuildTarget: This setting defines the target to execute
Customized build
ProjectBuilder defines defaults for the build.xml and target but you can specify your own in the project.xml you use to define your ProjectBuilder resource. Below is an XML snippet for the needed Setting definitions:
<setting type="BuilderBuildFile" name="tutorial" description="The path to the build file" settingValue="/path/to/my/ProjectBuilder/build.xml"/> <setting type="ProjectBuilderBuildTarget" name="tutorial" description="The build target to call" settingValue="all"/>
Run the Build cycle
The project build cycle is driven by the Build workflow command. This command goes through the normal set of steps: checking out the project sources, recording the buildstamp, calling the build script and then import the produced artifacts to the repository.
The example below shows the Build command called with "123" as the specified buildstamp:
ctl -p demo -t ProjectBuilder -r tutorial -c Build -- -buildstamp 123
You should see output like below. The output messages show each step of the workflow command:
Start: "Run the build cycle." commands: scmCheckout,setBuildstamp,runBuildScript,repoImport
begin workflow command (1/4) -> "scmCheckout -buildstamp 123" ...
scmCheckout parameters: {basedir="/Users/alexh/tutorial/src", connection="/Users/alexh/tutorial/cvsroot", module="src", label="", scmcommand="checkout" }
cvs -d/Users/alexh/tutorial/cvsroot checkout src
[command.timer.Builder.scmCheckout: 0.093 sec]
end workflow command (1/4) -> "scmCheckout -buildstamp 123"
begin workflow command (2/4) -> "setBuildstamp -buildstamp 123" ...
Using provided buildstamp "123"
[command.timer.Builder.setBuildstamp: 0.235 sec]
end workflow command (2/4) -> "setBuildstamp -buildstamp 123"
begin workflow command (3/4) -> "runBuildScript -buildstamp 123" ...
runBuildScript parameters: {basedir="/Users/alexh/tutorial/src", targetdir="/Users/alexh/tutorial/target", buildstamp="123", buildfile="/Users/alexh/ctier/ctl/projects/demo/modules/ProjectBuilder/lib/build.xml", target="all" }
Cleaning targetdir: /Users/alexh/tutorial/target
Deleting directory /Users/alexh/tutorial/target
Created dir: /Users/alexh/tutorial/target
Building type library ...
Building library from modules in opts.basedir: /Users/alexh/tutorial/src/modules
setting property seed.build.name to tutorial-seed
Created dir: /Users/alexh/tutorial/target/modules
processing modules in directory: /Users/alexh/tutorial/src/modules
converting type.xml for module: blah
generating handlers...
packaging module: blah
Copying 1 file to /Users/alexh/tutorial/src/modules/blah
Copying 1 file to /Users/alexh/tutorial/src/modules/blah
Deleting: /Users/alexh/tutorial/src/modules/blah/module.properties.temp
Building jar: /Users/alexh/tutorial/target/modules/blah-1.jar
seed.build.name=tutorial-seed
generating tutorial-seed.jar
Building jar: /Users/alexh/tutorial/target/tutorial-seed.jar
Uploading module jar: "/Users/alexh/tutorial/target/tutorial-seed.jar" ...
Imported types defined in library: /Users/alexh/tutorial/target/tutorial-seed.jar
Building docs ...
Defaulting filtersfile to: /Users/alexh/ctier/ctl/projects/demo/modules/ProjectBuilder/type.properties
opts{docbase=/Users/alexh/tutorial/src/doc, targetdir=/Users/alexh/tutorial/target, forresthome=/usr/local/apache-forrest-0.8}
.
.
.
Building zip: /Users/alexh/tutorial/target/site.zip
Site generation completed. Visit file:////Users/alexh/tutorial/src/doc/build/site/index.html
Loading resources located in /Users/alexh/tutorial/src/resources...
Loading "/Users/alexh/tutorial/src/resources/ProjectBuilder.tutorial.xml" ...
.
.
.
Executing batch update ...
Loading jobs located in /Users/alexh/tutorial/src/jobs...
Succeeded creating/updating 1 Jobs:
1: who's logged in? [1] </jobcenter/scheduledExecution/show/1>
end workflow command (3/4) -> "runBuildScript -buildstamp 123"
begin workflow command (4/4) -> "repoImport -buildstamp 123" ...
.
.
.
Uploading: tutorial-seed.jar
Puted 1 file to http://strongbad:8080/jackrabbit/repository/controltier/projects/pkgs/demo/jar/jars/tutorial-seed-123.jar
.
.
.
Completed: execution time: 50.366 sec
Some of the output was left out for the sake of brevity but you should see output messages corresponding to each build target described in the section above.
Summary
ProjectBuilder supports users that want to maintain their project content using a set of text-based source files and a typical build life cycle methodology.
ProjectBuilder provides a Build life cycle that supports processing and loading of the normal ControlTier artifacts: types, resources, and jobs.
You can extend the build process by defining your own build.xml file and configuring your ProjectBuilder resource to use it. You can also subtype ProjectBuilder and define new commands and even define a different build life cycle process by overriding the Build workflow command.
| ||||||||||||||
