     [file shared-setup.texi not included]

Assumptions
***********

In this document, I use the term SCM for Software Configuration Management system to encompass both PVCS and CVS.  The build script works with both PVCS and CVS (and may be enhanced to support other SCM systems in the future).

The build file is named "nextelapp-build.xml" (you will most likely copy it or link it to "build.xml" to avoid the -Dbasename and -f arguments to ant/ws_ant).

This document uses the word "module" to mean a J2EE ear module, a J2EE web module, or a J2EE ejb-jar module.  Note that I call an ear a module, even though I think that an ear is not a module in the J2EE sense. To "check out" a module, is to check out a CVS module or a PVCS directory branch corresponding the ear/war/ejb-jar module. A CVS module is the highest level grouping within a single CVS repository. The PVCS directory corresponding to a module is a top-level folder within a PVCS project.

The deployment tasks require you to either own the was instance, or to have sudo privileges to run 'wsadmin.sh' as the instance owner. (The setup section explains how to set up your WAS environment).

Setup
*****

Upgrade the ant libraries in $WAS_HOME/lib.
     [file ant-upgrade.texi not included]

See the top of your nextelapp-build.xml file to see what version of nextelanttasks is required (if it isn't mentioned, then you want the latest). Grab this file from http://admc.com/blaine/howtos/lib and put it into $WAS_HOME/lib.

Every module which you use from SCM must have a file named module.properties right in the main module directory.

     [file modprops.texi not included]

Builds must be run from this directory (i.e., your $PWD must be the directory containing, or to contain, the -web, -ear, etc., directories).

You need access to nextelapp-build.xml.  If you don't have access to a local copy, then download it from http://admc.com/blaine/howtos/nextelapp-build.xml. Your $PWD must contain a copy (or link) to 'nextelapp-build.xml' (wherever the latter may reside). (If you wish, you can supply the arguments "-f .../path/to/nextelapp-build.xml -Dbasedir=." to ws_ant/ant. In that case, there is no need for the build.xml file/link).

(You should probably compare the version at the top of your nextelapp-build.xml file with that at http://admc.com/blaine/howtos/nextelapp-build.xml).

$PWD must contain a file or link named 'env.properties'. See http://admc.com/blaine/howtos/env.properties) for an example, but you will have to change the property values for your own environment.

If you are using an alternative was instance, then you need to set up your OS environment as instructed below.

If you are using ant, as opposed to ws_ant, you will have to set the env variable $WAS_HOME.

SCM Setup
---------

To use PVCS, you have to set all of the properties in the appropriate block of the the template env.properties file. To use CVS, just set the property cvsRoot to the CVS repository root.

To use labels/tags, use the cvs.tag* settings, as described in the Labels/Tags section of this document.

Deployment Setup
----------------

If you want to use the deploy or redeploy target(s), you need to follow the instructions in the sample env.properties file in the DEPLOYMENT SETTINGS section.

ONE-TIME BUILD DIRECTORY SETUP EXAMPLE
--------------------------------------

In this example, nextelapp-build.xml lives in /app/iws/was (like it does on our development servers).

     mkdir $HOME/myproj
     cd $HOME/myproj
     ln -s /somewhere/leadgen-env.properties env.properties
     ln -s /app/iws/was/nextelapp-build.xml build.xml

It is highly desirable to use a sym-link to a common location for nextelapp-build.xml (as opposed to using a copy), so that you will automatically have access to bug fixes and feature enhancements.

PREPARATION FOR DEPLOYERS USING AN ALTERNATE WAS INSTANCE
---------------------------------------------------------

     export WAS_HOME=/some/directory
     . /path/to/instance/home/bin/setupCmdLine.sh

Raw Ant Setup
*************

If your server is resource-challenged, then use Ant instead of ws_ant.

The ant distribution must be set up as documented in the Setup section above. If you are on one of the following servers, then the Ant distribution at /usr/local/ant is all set up and ready to use.

  * nhqsnpr1

  * ditto

To use Ant instead of ws_ant, make sure that $WAS_HOME is already set, and then

 1. Set JAVA_HOME to $WAS_HOME/java (and export it).

 2. Put the directory containing the ant program very early in your search path, like

              PATH="/usr/local/ant/bin:$PATH"

     (If you are on nhqsnpr1 or ditto, you can cut and paste this exact command).

 3. Use ant wherever you were using ws_ant before.

Behavior
********

The build script is very efficient in that it will only reassemble jar/war/ears when necessary, and it will only compile when necessary.

In some cases, you may want to force a re-compilation even though this build script doesn't think it is necessary. This should be a very rare case, since this script is very conservative in that it requires a re-compilation even if a class-path element (like an external jar) has been updated. To force compilation, touch individual .java files, use the clean target, or remove the compile.state file in the module directory.

The ant javac task also has its own ideas about what needs to be recompiled.  If you see the "Compiling class files..." message, but message about how many source files are being compiled, then you will need to use the clean task or touch source files, because the javac task does not check classpath dependencies when deciding whether a source file needs to be re-compiled.

Another item which has to be done manually is removal of web utility libraries, i.e. web libraries that live in the WebContent/WEB-INF/lib subdirectory of a module. These jar/war files are updated from SCM and/or by development modules in your work area, but if you no longer need a library, the build file does not remove the files (even if you use the clean target). The reason for this is, there is no easily maintainable way for the ant build file to distinguish whether jars/wars in the directory are from an outside source (in which case they should not be removed).

See the descriptions for the clean and obliterate targets below.

Labels/Tags
***********

This section describes the use and strategy of using SCM labels/tags with our builds. So that I don't have to keep writing label/tag, I shall hereafter just use the word tag, understanding that what I say applies with equal force to both CVS tags and PVCS labels.

Checkouts are all performed using the tag(s) specified in your env.properties file. When creating a jop, you should set cvs.tag, and you should not set any other cvs.tag.* settings-- definitely do not set them to null (which means the tip/head tag). All artifacts used to build the jop should be checked out with the tag identified by cvs.tag. In addition to the source code of your development modules, all depended-upon artifacts in depended-upon development and depended-upon binary modules must be tagged with the this tag.

For typical development, you will want the head (a.k.a. tip) version of your development module artifacts, a tagged version of depended-upon binary modules, and either one or the other for depended-upon development modules. To accomplish this, don't set cvs.tag at all (or set it to nothing-- which is the default); set cvs.tag.bins to the highest available tag compatible with your dev modules; and, for those depended-upon development modules for which you want a frozen version, set cvs.tag.force.*.

Syntax
******

This is a list of external targets.  The build file has many other internal-use targets.

Since ant output often scrolls away, I usually invoke tee off the output to a log file like this.

     ws_ant ANY ARGUMENTS 2>&1 | tee build.log

For example

     ws_ant co jop 2>&1 | tee build.log

ws_ant -projecthelp
     Lists all available (external) targets.

ws_ant
     Default action.  Invokes the "ear" target.  See below.

ws_ant co

     IF A MODULE HAS PREVIOUSLY BEEN CHECKED OUT WITHIN THIS DIRECTORY

     Check out all *-jar, *-ear, *-web, *-ejb modules that are currently in this directory (it would also check out outside modules as specified in the configuration files of the present modules, but in nearly all cases, they will already reside here too). The checked out files will replace your current files. Replaced files are saved as .ORIGINALNAME.safe.

     IF NO MODULE HAS PREVIOUSLY BEEN CHECKED OUT TO THIS DIRECTORY

     You will be prompted for the module name.

ws_ant [-Dbin=true] -Dmodule=webmodule-web co

     Check out or refresh the given module. In this example, ant would check out the module "webmodule-web" from SCM. (For PVCS, it will look for the module as a top-level folder within all available PVCS projects).

     If you specify the module parameter, then you must also supply the "bin" parameter if you want to check out the module as a "binary" instead of a "development" module. (I.e., when you supply "-Dmodule=...", it will be checked out as a development module by default).

     [TODO:  the -Dbin=... parameter should be set automatically if the module has previously been checked out to this directory.]

ws_ant [-Dretain=true] ear

     Build an ear file from the ear module that is rooted in the $PWD. If there is no ear module in the $PWD, a syntax message will be given. Note that you can not supply the ear module name, since this target is only capable of building from the single -ear module in the $PWD.

     This target depends on the ejb-jar and war targets.

     If retain is set to true, then a backup will be retained for each ejb jar file before stubs and skeletons are added.

ws_ant [-Dmodule=webmodule-web] war
     Assemble war file(s) from war module(s).

     IF A MODULE NAME IS SUPPLIED

     Build a .war file from the given development web module rooted in the $PWD.

     This target depends on the compile target of the same module.

     IF A MODULE NAME IS NOT SUPPLIED

     Build a .war file from each development web module rooted in the $PWD. This just runs the IF A MODULE NAME IS SUPPLIED procedure for each such module.

ws_ant [-Dmodule=javamodule-jar] jar
     Assemble jar file(s) from Java module(s).

     IF A MODULE NAME IS SUPPLIED

     Build a .jar file from the given development Java module rooted in the $PWD.

     This target depends on the compile target of the same module.

     IF A MODULE NAME IS NOT SUPPLIED

     Build a .jar file from each development Java module rooted in the $PWD. This just runs the IF A MODULE NAME IS SUPPLIED procedure for each such module.

ws_ant [-Dmodule=ejbmodule-ejb] [-Dretain=true]  ejb-jar

     Assembles ejb jar file(s), including deployment stub and skeleton classes, from ejb-jar module(s).

     IF A MODULE NAME IS SUPPLIED

     Build an ejb jar file from the given development ejb jar module rooted in the $PWD. Stub and skeleton classes are compiled and put into the ejb jar.

     This target depends on the compile target of the same module.

     IF A MODULE NAME IS NOT SUPPLIED

     Build an ejb jar file from each ejb module rooted in the $PWD. This just runs the IF A MODULE NAME IS SUPPLIED procedure for each such module.

     As you will be warned when the procedure runs, you need to watch for errors during the ejbdeploy process (which creates stubs and skeletons), since errors will not be noticed by the build process (because IBM's ejbdeploy.sh does not return a meaningful status).

     If retain is set to true, then a backup will be retained for the ejb jar file before stubs and skeletons are added.

ws_ant [-Dearfile=/path/to/a/file.ear] deploy

     Deploy the ear file of the ear module rooted in this directory to the WAS/DM server indicated by the was.soap.* properties in your env.properties file.

     The env.properties file must specify the target WAS node, and may supply the target Java server within that node.

     The deployment will fail if the WAS server already has an application deployed with the same name as this ear application.

     If you supply the -Dearfile argument, then no build is done and no dependencies are checked--- the indicated ear is just deployed. (This is useful in many cases, including installing an ear extracted from a jop file). If you do not supply the -Dearfile argument, then this target will depend on the ear target.

     If you use the nextel jacl script (set in env.properties), the ear will be deployed according to Nextel JNDI naming conventions. If you set deploy.postcommand in the env.properties file, that command will be executed if and after deployment to the WAS server. The most immediate purpose of deploy.postcommand is to run a script to set up the common war resources for the deployed app.

ws_ant [-Dearfile=/path/to/a/file.ear] redeploy

     Deploy the ear file of the ear module rooted in this directory to the WAS/DM server indicated by the was.soap.* properties in your env.properties file. The deployment will fail if the WAS server does not already have an application deployed with the same name as this ear application.

     The env.properties file must specify the target WAS node, and may supply the target Java server within that node.

     If you supply the -Dearfile argument, then no build is done and no dependencies are checked--- the indicated ear is just deployed. (This is useful in many cases, including installing an ear extracted from a jop file). If you do not supply the -Dearfile argument, then this target will depend on the ear target.

     If you use the nextel jacl script (set in env.properties), the ear will be deployed according to Nextel JNDI naming conventions. If you set deploy.postcommand in the env.properties file, that command will be executed if and after deployment to the WAS server. The most immediate purpose of deploy.postcommand is to run a script to set up the common war resources for the deployed app.

ws_ant [-Dmodule=webmodule-web] compile

     IF A MODULE NAME IS SUPPLIED

     First, recurse through all development modules that this module depends on (as specified in this module's config file). This same target is invoked on those targets in the specified order. Then compile all of the java files within the given module rooted in the $PWD. Due to the recursion involved, this target must do time-stamp comparisons to avoid recompiling modules that don't need it.

     IF A MODULE NAME IS NOT SUPPLIED

     Build an ejb jar file from each ejb module rooted in the $PWD. This just runs the IF A MODULE NAME IS SUPPLIED procedure for each such module. Due to the iteration involved, this target must do time-stamp comparisons to avoid recompiling modules that don't need it.

ws_ant [-Dmodule=webmodule-web] clean
     Remove all derived files.

     You can supply "jop" as a module name to remove the "jop" subdirectory, even though "jop" is not a real module name. (The jop directory is a staging area used during jop creation. The contents are not removed automatically, in order to prevent unnecessary work the next time a jop is created).

ws_ant [-Dmodule=webmodule-web] jop
     Build an ear (unless there is already one up-to-date), check out the jop resources (scripts and samples) from SCM, and generate a jop file.

     This target no longer depends on the co target, so you will need to run ws_ant co jop if you want to check out all artifacts from SCM and build a jop from that.

     This target depends on the ear target.

ws_ant obliterate
     This is like a super clean. clean removes only derived files, not artifacts checked out from SCM. obliterate removes derived files and all artifacts checked out from SCM. You may want to run this to eliminate any possibility that something hanging around from an old check-out or an old build are unintentionally effecting your build. (To do anything useful, you will have to use the co target after obliterate).

ws_ant validate
     Have WAS validate the ear file. Not implemented yet.

     This target depends on the ear target.

ws_ant api
     Generate (or re-generate) JavaDoc API for all source code. The generated docs are written to the api subdirectory.

ws_ant xmlvalidate
     Validate that the descriptor files are valid XML and conform to their respective DTDs. Not implemented yet.

Nextel Task Library
*******************

Our custom ant tasks are in the library nextelanttasks-X.jar, where X is a version number.  This library can be obtained from http://admc.com/blaine/howtos/lib.  It should be placed at the same place as your other ant jar files.

To use these tasks, your build file should have a line at the top like

     <taskdef resource='com/nextel/ant/taskdef.properties'/>

You can safely ignore this section unless you plan to use or modify these tasks in an ant build file.

At this time, none of the tasks permit bodies nor nested sub elements. Therefore, the tasks will always be used like

         <taskname... />

Never like

         <taskname... > other stuff </taskname>

Custom Tasks
------------

<metaextract>
     Extracts the value from the given attribute from the manifest file in the given module.

     attributes

     property
          The property in which to store the extracted value.

     module
          The -ear/-web/-jar/-ejb module in which the manifest file resides.

     attribute
          The manifest attribute to extract.

<fileatt>
     Determines the given attribute for a directory or file. This task returns a meaningful value only on UNIX. On Windows, it will return an empty string (although it still validates that the file or directory exists).

     attributes

     property
          The property in which to store the file attribute value.

     file
          Path to the file or directory

     attribute
          The file attribute desired.  Currently only owner and group are supported.

<genincludes>
     Using the input string, generates a string suitable for use as an ant include attribute for Nextel/WSAD-specific setups. This assumes the required Nextel directory/module layout.

     attributes

     inlist
          The string to work from.

     mode
          Indicates the purpose for the generated string. By default, an include list for a development module is created. Allowable values are bin for a binary modules, weblib for a web utility library list, and state for the compile state files.

     attribute
          The manifest attribute to extract.

<parentfind>
     I'm too tired to describe this now.

     attributes

     grandparent
          Grandparent directory (parent of the desired output directory).

     child
          Child directory that you want to know about.

     property
          The property in which to store the result.