CS11 Advanced Java - Lab 4

This week you will be focusing on putting some more advanced software development tools and techniques into place. This means that you won't really be writing any code, but there will still be plenty of stuff to do.

You should start this week's work in a ~/cs11/advjava/lab4tmp directory. DO NOT USE lab4 YET. (The reason for this will become clear; you will create the actual lab4 directory in a subsequent step.) Just like last week, copy your files over to this directory, since you will be using them again.

Build Process Automation

We only have a few .java files so far, but already it's becoming a bit of a hassle to compile your sources, compile your tests, generate your API documentation, run the tests and look at the results, and so forth. Fortunately, we can automate all of these tasks, so that building the project becomes a breeze.

We will be using the Ant build tool. It is widely used for many Java projects, and has a tremendous range of features and capabilities. Furthermore, Ant is designed to run on different platforms without needing to reconfigure your build file; for example, it can convert between "/" and "\" characters based on the operating system it is running on. Ant is available on the CS cluster for you to use, or you can download it and install it on your own computer.

Project Layout

Once you begin to automate your build process, it is important to think carefully about directory structure. Ant projects tend to have directories like these:

src
This is where your project source code goes. Test code should not go into this directory!
test
This is where test code should go. Just like with the src directory, no project sources should go into this directory; only test code.
lib
This is where you can put external libraries (JAR-files) that are necessary for running your program, or for running tests against your program. (For example, the TestNG JAR-file will go in here.)
res
This is where you can put additional resources that your program depends on, such as images, locale-specific translations of user-interface strings, and so forth.
doc
This is where you should put any documentation for your project, such as design documentation, user manuals, release notes, lists of bugs (if you aren't using an external bug-tracking program), and so forth. (You probably won't have any files to put into a doc directory at this point.)
build

This is a directory created by your build script, and all files created by the build process go into this directory. This makes it easy to implement the "clean up" build target, because you can just blow away this entire directory.

The build directory will have subdirectories like this:

Restructure your code to follow a directory structure like the one outlined above. For now, you will create the src, test, and lib directories, and move your files into the appropriate directories. If you have any (non-Javadoc) documentation files, you can put them in a doc directory. Similarly, if you have images or any other resources, you can put them into a res directory.

Note that you shouldn't have any .class files under your src or test directories, and you shouldn't have any Javadoc-generated documentation anywhere either. These will all be generated by the build script, and will go under the build directory when the build process executes.

The build.xml File

You can start with an example build.xml file this week. (I usually keep a template build.xml file around, and I use it as the basis for each new project.) Download this example-build.xml file put it into your lab4 directory, and rename it to build.xml.

Go ahead and read through this file, so you can familiarize yourself with the way it works. The most important detail is that all important directories are specified as Ant properties at the top of the file, and subdirectories are specified in terms of the parent-directory properties. For example, we have the buildDir property, and then we have the buildClassesDir subdirectory defined in terms of that property.

Complete these tasks to get your build process going:

  1. Edit the project name and description in this build.xml file. The project name could be as simple as "boggle". Make sure the description gives a general idea both of what the project does, and how to perform a simple build.

    You can see the result of your work by running "ant -projecthelp" at the command-line.

  2. Add a clean target to your Ant file, which deletes the build-directory and all its contents. Make sure to set the target's description to something useful. (Hint: see the delete Ant-task. This target should be very simple.)

    You should make a backup copy of your work before trying out this build target!

  3. Add a javadoc target to your Ant file, which uses the javadoc Ant-task to generate API documentation into the directory referenced by the javaDocDir property. Again, provide a good description of the target. Make sure you specify all directories by using Ant properties; don't hard-code directories into your task, since they almost invariably change.

    (You can include or exclude your test classes in your Javadocs. I generally tend to exclude test code from my Javadocs, since it tends to clutter up this resource intended for helping developers understand things.)

    Here are some more details for your javadoc target:

Once you have completed these tasks, verify that you can compile your program and generate API documentation for it, by running your various tasks. For example:

    ant clean
    ant compile
    ant clean compile javadoc

Using TestNG with Ant

Because TestNG is a relatively new tool, Ant doesn't include any tasks for running TestNG tests! But this is okay, since Ant has a way to add extra task-definitions to a project's build-file. You can use the <taskdef> tag for this purpose.

Add these lines to your build.xml file, after the paths and before the "Build Targets":

    <taskdef resource="testngtasks"
             classpath="path/to/testng.jar" />

As usual, make sure you use Ant properties to specify the directory to the TestNG JAR-file.

Once you do this, you should have a <testng> task to use in your project. Documentation for this task is available on the TestNG website. Get your unit-tests running under your build process by completing these tasks:

  1. Add a new build-target called compile-tests. You can start by duplicating the compile task for this. However, make sure to make these changes:

  2. Add a new test target to your Ant file, which runs all unit-tests using the testng task. As usual, make sure to set the target's description to something useful. Here are some more details for you to complete this target:

Once you have gotten your compile-tests and test targets completed, give them a run and see how they do. If everything works properly, you should be able to go to your build/results directory and see a simple HTML report of your unit tests.

Wrapping Up the Build Automation

Once all of your build targets are working, uncomment the full build-target, and change the default target of your project to be the full target. This way when you run ant with no arguments, it will run the full target and all of its dependencies.

Version Control with Subversion

Now that you have your project laid out in a much better structure, and now that you have an automated build process, you can set up a source-code repository to manage your project's sources. You have done the majority of the layout work above, so the remaining steps should be relatively simple.

  1. Create a brand new Subversion repository using the svnadmin create command:
        svnadmin create ~/cs11/advjava/svnrepo
    This will create a new Subversion repository in the svnrepo subdirectory of your CS11 Advanced C++ directory structure. Use this repository location so that we can also look at your repository.
  2. Next, you need to import all of your source files into the Subversion repository. You already have your files laid out in a reasonably good structure from the previous steps, but you should be sure to eliminate all build artifacts (i.e. ant clean), as well as editor-droppings like *~, etc.
  3. Once your files are ready for import, use the svn import command as shown in class. Remember that Subversion refers to repositories by URL, so you will need to use a file:// URL for this. (You could also import to a remote repository using a svn+ssh:// URL, but you will have to figure that out yourself.) You can run this command, from your lab4tmp directory:

        svn import file:///home/<username>/cs11/advjava/svnrepo/boggle

    (Replace <username> with your own username, of course...)

    This will recursively import all files in your local directory, into the repository. Note the name "boggle" at the end of the repository URL; this imports your project's sources into a "boggle" project within the repository.

    Don't delete any local files until you have verified that the import process completed successfully! You don't want to lose your hard work.

    If Subversion complains about not being able to find an editor, you can shut it up by typing something like export EDITOR=vi before running your Subversion commands. (Replace vi with your preferred text editor, of course.)

  4. Importing files from a directory does not automatically make that directory a working copy! So, after importing, you need to check out the repository's files into a local directory. This will also allow you to verify that your import worked properly. Create a new ~/cs11/advjava/lab4 directory, and do your checkout inside of this directory. Something like this:

        svn checkout file:///home/<username>/cs11/advjava/svnrepo/boggle

    This will create a local directory boggle, containing the files you just imported. Check to make sure all the files you expected, actually showed up! Once you are sure everything is good, then you can go ahead and delete the lab4tmp directory.

Once these steps are completed, you can go ahead and edit your working copy of the project without mangling the (hopefully) pristine source code in your repository. You can build it, test it, and make sure everything works properly before committing your work back to the repository.

As mentioned in class, you can issue an svn commit without specifying the repository URL because Subversion creates little .svn files in your working copy, that hold relevant details like which repository the files are from. (You can see them by typing "ls -a" in any directory of your working copy.)

If you want to work remotely, you can use a repository URL something like this:

    svn+ssh://<username>@cs.caltech.edu/home/<username>/cs11/advjava/svnrepo

This will cause the svn client to use the ssh client to establish a connection to the CS cluster, and access your repository. Secure and easy!

Remember that you can use svn help and svnadmin help for getting more information on what Subversion commands are available, and for looking at the details of specific commands.


Extra Credit!

Here are some fun tasks for you to try, if you want to learn more about Ant and Subversion.
Copyright (C) 2008, California Institute of Technology. All rights reserved.
Last updated April 29, 2008.