Test-driven development in an SOA environment: Part 2: Continuous integration with WebSphere Process Server

Part 1 of this series focused on using Cactus to write test cases for SCA data maps before writing the SCA business processes in IBM® WebSphere® Integration Developer. Part 2 looks at using CruiseControl as the continuous integration server to monitor the SCA artifacts in the CVS repository and run the test cases on IBM WebSphere Process Server whenever there are changes. This content is part of the IBM WebSphere Developer Technical Journal.


Donald Vines (dhvines@us.ibm.com), Executive IT Architect, IBM

Donald Vines is currently an Executive IT Architect at IBM responsible for the WebSphere migration practice within North America.

developerWorks Contributing author

10 December 2008

Also available in Chinese


Continuous integration was made popular by Agile software development, which is now an industry-recognized best practice for many software development methodologies. The major features of continuous integration are two-fold:

  • A one-step build process that tests the entire application, not just a single project. The build process checks out all of the code, builds the entire application, runs all of the unit tests, and reports the results to the developers.
  • A scheduled build process that runs at regular intervals; for example, whenever the code changes. If there are any problems in the build, they can be immediately found and corrected.

Continuous integration reduces the time that it takes to develop SOA applications. When you make a change, you don’t have to run all of the tests across all of the services in the entire system before committing your changes. You can test your service and commit the changes, then let the continuous integration server run all of the tests on other services. If there is a problem, then you will be quickly notified and can immediately address the problem.

Continuous integration also makes finding and fixing problems in SOA applications easier. When a problem occurs, you only need to look at the changes that were made during the last build interval to fix it. In addition, builds are done automatically as changes are made, so when a problem occurs it does not have time to grow into a larger problem.

Part 1 of this series on test-driven development in an SOA environment showed you how to write unit tests for SOA applications. This article demonstrates the usage of a continuous integration server for testing Service Component Architecture (SCA) applications running on IBM WebSphere Process Server. This continuous integration server is built from the following open source projects:

Along with those open source projects, this article uses the sample application from Part 1 to demonstrate automatically building and testing SOA applications. This sample application was developed with IBM WebSphere Integration Developer V6.1 (hereafter referred to as Integration Developer). The remainder of this article documents this process:

  1. Create the source code repository: A source code repository is created to store the sample application for team development.
  2. Check the application into the repository: The sample application is checked into the source code repository so that it is available to the continuous integration server.
  3. Start WebSphere Process Server: WebSphere Process Server V6.1 is started so that it can deploy the application and run the tests on behalf of the continuous integration server.
  4. Start the continuous integration server: The continuous integration server is started so that it can poll the repository for changes to the application. Whenever it detects changes, it builds and tests the application, and reports any problems to the developers.

Create the source code repository

In any continuous integration environment, you need to establish a central server for your version control system that maintains your WebSphere Process Server applications. This server must be accessible by all team members as well as the continuous integration server. Using this central repository, team members will check in their SCA components and test cases, and the continuous integration server will check them out to do the builds.

For the purpose of this article, CVSNT is referenced as the version control system because it is freely available and easy to obtain. If you use ClearCase, you can substitute that for CVS (see Resources).

In this section, you will see how to set up the version control system and create the repository used to maintain your WebSphere Process Server applications and test cases. Perform these steps on the machine you use as the central version control server:

  1. Install CVSNT.

    Download CSVNT Server and install it as directed by the installation wizard. Choose a Typical installation. When completed, restart your system to implement the changes.

  2. Create the CVS repository.

    Decide where you want your repository to be located on the file system. The repository is the root directory where your files (the archived versions of your files) will be maintained by CVS. The repository directory name cannot contain spaces, so use something such as c:\cvsrepo or a similar path. You can use the CVSNT Control Program to create the repository:

    1. Select Start => Programs => CVSNT => CVSNT Control Program.
    2. Select the About tab and stop the CVSNT service and lock service.
    3. Select Add to add a new repository.
    4. Browse to the path for your repository. If the directory does not exist, use the New Folder button to create the folder structure for your new repository. Create a repository (for example, c:\cvsrepo) and select OK to add this repository.
    5. If the repository is new, you will be prompted to create and initialize it. Reply Yes to create and initialize this new repository.
    6. Select the About tab and start the CVSNT service and lock service.
  3. Secure the CVS repository.

    There are many ways to secure access to the CVS repository. Although there are more secure approaches, use the pserver protocol here because it is easy to use and easy to configure. If you want to use a more secure protocol, refer to the CVS manual in Resources.

    To configure the pserver protocol, you must identify the administrator for this CVS repository. To do that, create a file named passwd in the CVSRoot directory under your repository. For example, if the CVS repository is under c:\csvrepo then this file would be in c:\cvsrepo\CVSROOT. This file should contain a single line, which is the name of the user who is currently logged in. If the current logged in user is admin then this file will look like this:


    Stop and restart the CVSNT service and lock service.

  4. Test the CVS connection.

    Open a console window and enter:

    set CVSROOT=:pserver:admin@localhost:/cvsrepo
    cvs login

    You will then be prompted to enter the password.

Check the application into the repository

For demonstration purposes, you will use the sample application that was developed in Part 1 of this series. To do that, you need to integrate Integration Developer with CVS and check in the Integration Developer projects into CVS. Once in CVS then the continuous integration server can check the projects out whenever there is a change, run the build, and execute the tests.

  1. Configure Integration Developer to access the CVS repository.

    Integration Developer provides built-in support for using a CVS repository for version control of the SCA components and artifacts (see Resources) that make up a WebSphere Process Server application. To check the SCA artifacts in to CVS from within Integration Developer, you must configure Integration Developer to access the CVS repository:

    1. In Integration Developer, select Window => Open Perspective => Other.
    2. Select the CVS Repository Exploring perspective. Right-click and select New => Repository Location.
    3. Enter the name of the Host machine running the CVSNT service.
    4. Enter the path on the machine where the repository is located. For example, if the repository is located on the server at c:\cvsrepo, then the repository location would be \cvsrepo.
    5. Enter the CVS user ID for the username and the password; this should be your local account information.
    6. Make sure the pserver is selected for Connection Type and that the default port is selected.

    After this information is entered, Integration Developer will prompt you for the password, verify access to the repository, and, assuming that you are authorized, you will be permitted to check in the SOA application, including the SCA module, SCA library, and Web test cases to CVS.

  2. Check in the Integration Developer projects.

    Obtain a copy of the sample application, which is a project interchange file you can download from Part 1. After you import the project interchange file into Integration Developer and verify the installation by running the unit tests, you can check the Integration Developer projects into CVS:

    1. Open the Business Integration perspective. You should see three projects:
      • L_AddressCleansingService
      • T_AddressCleansingService
      • T_AddressCleansingServiceJUnitWeb.
    2. Right-click on a project and select Team => Share Project...
    3. Select the repository type; in this example it is CVS, but it could also be ClearCase.
    4. Add an optional comment for version tracking.

    Perform steps b through d for each project, then all files will be uploaded to the CVS repository, and the sample application will be available for check out by the continuous integration server.

Start WebSphere Process Server

Before setting up the continuous integration server, make sure that WebSphere Process Server V6.1 is running. An instance of WebSphere Process Server is required to deploy the SCA module and run the test cases as directed by the continuous integration server.

For the purpose of this article, the instance of WebSphere Process Server that is included with Integration Developer is used because it was already installed. If you prefer, you can use a standalone instance of WebSphere Process Server to run the builds rather than use Integration Developer for this purpose. In either case, an instance of WebSphere Process Server must be running. This is required so that the continuous integration server can build and test the SCA module.

Start the continuous integration server

Several open source continuous integration servers are available, such as CruiseControl, AntHill, Hudson, Luntbuild, and Apache Continuum. CruiseControl is used here for the purpose of this article.

  1. Download and install a continuous integration server.

    Obtain and install the binary distribution of CruiseControl according to the download instructions. At the time of this writing, the current release is version 2.7.3. When installed, the server files will be unzipped into a folder, such as d:\cruise.

  2. Create the working directories.

    Now you need to create working directories on the integration server machine. These working directories will be where CruiseControl runs the builds and stores the results. These should be kept separate from the CruiseControl installation directory. Listing 1 shows the directory structure for the continuous integration server. These directories are included in the download file included with this article.

    Listing 1. Directory structure
      contains the Cruise configuration file and a script to start the Cruise server
              contains this project’ build.xml file and a runbuild.bat script
    		  contains the inputs to the build script, e.g. SCA artifacts
    		  contains the outputs from the build script, e.g. test results
              contains time stamped sub-directories with published build artifacts
              contains the status.txt file indicating the build status

    You will need to understand these working directories so you can write the build script and configure CruiseControl to build your project. Listing 1 provides quick descriptions. The \builds directory is where all of the integration builds are performed. Off of the \builds directory, there are three sub-directories:

    • The \projects directory contains a subdirectory for each project that is to be built by the continuous integration server. Each of those subdirectories contains:
      • build.xml file that will be run by the continuous integration server.
      • \source directory that contains the SCA artifacts that will be checked out from CVS.
      • \target directory that will contain the results of the build.
    • The \artifacts directory also contains a subdirectory for each project. Each of those subdirectories contains multiple time-stamped subdirectories, one for each successful build. The time-stamped subdirectories contain the published build results. In this case, it will contain the contents of the project’s \target directory (Listing 1).
    • The \logs directory also contains a subdirectory per project. Inside that subdirectory is a status.txt file that indicates the current build status; for example, whether a build is in progress or waiting to be run.
  3. Write the build script.
    1. First, you need to manually checkout the CVS modules that are required to build your project into the project’s \source directory. For the purpose of this article, the required CVS modules are:
      • L_AddressCleansingService: the SCA library under test.
      • T_AddressCleansingService: the SCA module used to test the library.
      • T_AddressCleansingServiceJUnitWeb: the Cactus test cases for testing the library.

      Check out the modules into the \projects\L_AddressCleansingService\source directory. After they are checked out, CruiseControl will monitor those modules in CVS for changes and schedule a build if required. You will not need to manually check them out again.

      To help you check out the CVS modules, a runbuild.bat file is provided in the \projects\L_AddressCleansingService directory. Make sure the environment is set correctly in the runbuild.bat file. Open a console window and type runbuild checkout.

    2. Next, you need to write the Ant build script, which CruiseControl will run to build your project. An example is provided in the \projects\L_AddressCleansingService directory called build.xml. This build script is called by CruiseControl whenever it detects a change and needs to build the project. When the build runs, it will:

      A clean build is created each time by destroying the \source and \target directories and then obtaining the modules from CVS. This avoids potential problems from incremental builds.

    Following are definitions of the major targets of the build script, listed above, and the default target (all), which calls the major targets in the above sequence. (The Ant build script is available in the download file.)

    • Target: all is the default Ant target called by CruiseControl when it needs to run a build. It has dependencies to a number of other targets that are run in this sequence: clean, init, checkout, build, install, start, test, stop, and uninstall.
      Listing 2. Target: all
         depends="clean, init, checkout, build, install, start, test, 
      		stop, uninstall">
    • Target: clean cleans up from the previous build by deleting the \source directory and the \target directory. This deletes the source code and class files that were used in the previous build. It ensures this build will start from a clean slate.
      Listing 3. Target: clean
      <target name="clean">
           <delete dir="${source.dir}"/>
           <delete dir="${target.dir}"/>
    • Target: init sets up the environment that is required for running this build. Create the \source directory and the \target directory. It establishes the working directory for this build.
      Listing 4. Target: init
      <target name="init">
          <mkdir dir="${source.dir}"/>
          <mkdir dir="${target.dir}"/>
    • Target: checkout checks out the CVS modules that are required to build this project. That is, it checks out a fresh copy of the CVS modules into the \source subdirectory.
      Listing 5. Target: checkout
      <target name="checkout">
          command="-q co -d source/${test.module.name} ${test.module.name}">
          command="-q co -d source/${test.webapp.name} ${test.webapp.name}">
          command="-q co -d source/${library.name} ${library.name}">      
    • Target: build builds the SCA module for WebSphere Process Server. It first creates a .zip file that contains the SCA module and its dependencies. It then generates the EAR file using the IBM serviceDeploy task.
      Listing 6. Target: build
      <target name="build">
    • Target: install installs the SCA module to WebSphere Process Server.
      Listing 7. Target: install
        <target name="install">
    • Target: start starts the SCA module on WebSphere Process Server.
      Listing 8. Target: start
        <target name="start">
              application="${test.module.name}App" >
    • Target: test runs the Cactus test cases on WebSphere Process Server and sends the output to XML files in the project’s \test-results directory so that the test results can be displayed by the continuous integration server (see Define the logs directory). To do that, it first compiles the test cases then uses JUnit to run those test cases.
      Listing 9. Target: test
      <target name="runTest">
        <mkdir dir="${target.dir}/test-classes"/>
            <path refid="compile.class.path"/>
          <include name="**/*Test.java" />
        <mkdir dir="${target.dir}/test-results"/>
        <junit fork="yes">
            <path refid="test.class.path"/>
          <formatter type="brief" usefile="false" />
          <formatter type="xml" /> 
          <batchtest todir="${target.dir}/test-results">
    • Target: stop stops the SCA module on WebSphere Process Server.
      Listing 10. Target: stop
        <target name="stop">
              application="${test.module.name}App" >
    • Target: uninstall uninstalls the SCA module from WebSphere Process Server.
      Listing 11. Target: uninstall
        <target name="uninstall">
              application="${test.module.name}App" >
  4. Configure CruiseControl to build your project.

    Cruise Control is configured using a configuration XML file. This file controls the build loop, and tells CruiseControl how and when it should run your build. The configuration file for this example is the config.xml file, which is contained in the \builds directory and described below one section at a time. A copy of config.xml is available in the download file included with this article.

    1. Define the project.

      The first few lines of the config.xml file define the project:

      Listing 12. config.xml
         <project name="L_AddressCleansingService" buildafterfailed="false">

      The <project> element defines the projects that CruiseControl is responsible for building. There can be multiple project elements in this file, each with a unique name. In this <project> element, the value of buildafterfailed is set to false so that the build will not be attempted again if it fails and there are no subsequent changes to the source files in CVS since that build.

    2. Listen for build events

      Next, define listeners that are notified of events during the build process:

      Listing 13. Define listeners

      In this configuration file, the <currentbuildstatuslistener> element is specified to write the current status of the build to the \logs\L_AddressCleansingService\status.txt file. This status indicates whether CruiseControl is attempting a build or is waiting to attempt a build. In this manner, the current build status will be available via the CruiseControl Web application.

    3. Check for changes.

      Define how CruiseControl checks for changes to determine if a build is required:

      Listing 14. Checking for changes
      <modificationset quietperiod="30">
         <cvs localworkingcopy="${source.dir}/${test.module.name}"/>
         <cvs localworkingcopy="${source.dir}/${test.webapp.name}"/>
         <cvs localworkingcopy="${source.dir}/${library.name}"/>

      The <modificationset> element specifies what CVS modules are examined for changes to determine if a build is necessary. In the above <modificationset> element above, a quietperiod of 30 indicates that the CVS repository must be quiet for 30 seconds before a build is attempted. This gives developers an opportunity to check in all of their changes before a build is attempted.

      Three <cvs> elements with the localworkingcopy attribute point to the local copy of the CVS modules that are required to build the project. The <cvs> element enables CruiseControl to locate the CVS repository and check for changes. It does not do the check out; that is done by the build script (see Target: checkout).

      In addition to CVS, there is also a <clearcase> element for ClearCase users.

    4. Define the build interval.

      Define the build interval and the build script to be called:

      Listing 15. Define build interval
      <schedule interval="60">
         <ant anthome="${ant.home}" 

      The <schedule> element specifies the build interval. In this example, the build interval is set to 60 seconds. This tells CruiseControl to check the CVS repository every 60 seconds for changes to the files. If there are changes, then a build will occur (see Check for changes); if not CruiseControl will check again in 60 seconds. The <ant> element tells CruiseControl the location of the Ant script and the target to call whenever it runs a build. In this case, CruiseControl will run the all target in the \projects\L_AddressCleansingService\build.xml file (see Target: all).

    5. Define the logs directory

      Define the location of the CruiseControl logs and log the JUnit test results:

      Listing 16 Define log location
      <log dir="${logs.dir}/${project.name}">
         <merge dir="${target.dir}/test-results"/>

      The <log> element specifies the location of the log files. CruiseControl creates a log file each time it attempts a build in the \logs\L_AddressCleansingService directory.

      In addition to the log file entries that CruiseControl creates, you also want to log the test results from the JUnit test cases. To do that, use the <merge> element with the directory attribute pointing to the location where JUnit test results were written as XML by the build script (see Target: test).

    6. Publish the build artifacts.

      Publish the build artifacts that you want to keep such as the EAR file:

      Listing 17. Publish build artifacts
               dir= "${target.dir}"

      The <artifactspublisher> element specifies how to publish certain build artifacts, such as the EAR file that was generated. In this example, you are publishing all of the items that are found in the \target directory to the \artifacts directory. It actually creates a subdirectory under the \artifacts directory with the same name as the timestamp of the build. This enables CruiseControl to provide access to historical build artifacts.

    7. Start the build loop.

      Finally, you can start the CruiseControl build loop. To do that, a runcruise.bat file is provided in the \builds directory. Before running it, make sure that your environment is set correctly in that file. You can then start the build loop by typing runcruise.bat in a console window.

      When CruiseControl starts, it reads the configuration file, attempts to run a build, and then checks the CVS repository for modifications. The first time it attempts a build on your project, it may not detect modifications, but it will still force a build. After the first build, it will only schedule a build if there are modifications. You should see messages similar to the following in your console:

      Listing 18. Messages from build
      projectName = [L_AddressCleansingService]
      using settings from config file [D:\builds\config.xml]
      No previously serialized project found 
      	[D:\builds\L_AddressCleansingService.ser] forcing a build.
      Project L_AddressCleansingService starting
      Project L_AddressCleansingService:  checking for modifications
      Project L_AddressCleansingService:  No modifications found, 
                     build not necessary.
      Project L_AddressCleansingService:  Building anyway, since 
                     build was explicitly forced.

      Next, the all target in the Ant build.xml file will be called by CruiseControl. That Ant target has dependencies to other targets, such as clean, init, checkout, and so forth. The dependent targets will be run in their specified order, and then the all target will run. You should see output similar to the following in the console. Make sure that your unit tests were run correctly.

      Listing 19. Target dependencies
      Project L_AddressCleansingService:  now building
      Buildfile: .\projects\L_AddressCleansingService\build.xml
      ccAntProgress -- clean
      [delete] Deleting directory 
      [delete] Deleting 
        directory D:\builds\projects\L_AddressCleansingService\target
      ccAntProgress -- init
      [mkdir] Created 
         dir: D:\builds\projects\L_AddressCleansingService\source
      [mkdir] Created 
         dir: D:\builds\projects\L_AddressCleansingService\target
      ccAntProgress -- checkout
      [cvs] U source/T_AddressCleansingService/.classpath
      [cvs] U source/T_AddressCleansingService/.project
      [cvs] U source/T_AddressCleansingService/.runtime
      [cvs] U source/T_AddressCleansingService/sca.module
      ccAntProgress -- build
      [zip] Building zip: 
      [servicedeploy] Initializing workspace 
      [servicedeploy] Building project L_AddressCleansingService
      [servicedeploy] Building project T_AddressCleansingServiceEJB
      [servicedeploy] Building project T_AddressCleansingServiceJUnitWeb
      [servicedeploy] Building project T_AddressCleansingServiceApp
      [servicedeploy] Exporting application 
      [servicedeploy] Deployment has completed
      [servicedeploy] Waiting for background jobs
      [servicedeploy] Deleting workspace
      ccAntProgress -- install
      [wsInstallApp] Installing Application 
      [wsInstallApp] Installed Application 
      ccAntProgress -- start
      [wsStartApp] Starting Application [T_AddressCleansingServiceApp]...
      [wsStartApp] Started Application [T_AddressCleansingServiceApp]
      ccAntProgress -- test
      [mkdir] Created dir: D:\builds\projects\L_AddressCleansingService\target\
      [javac] Compiling 1 source file to 
      [mkdir] Created dir: D:\builds\projects\L_AddressCleansingService\target\
      [junit] Testsuite: 
      [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 1.578 sec
      ccAntProgress -- stop
      [wsStopApp] Stopping Application [T_AddressCleansingServiceApp]...
      [wsStopApp] Stopped Application [T_AddressCleansingServiceApp]
      ccAntProgress -- uninstall
      [wsUninstallApp] Uninstalling Application [T_AddressCleansingServiceApp]...
      [wsUninstallApp] Uninstalled Application [T_AddressCleansingServiceApp]
      ccAntProgress -- all

      After CruiseControl runs a build, it merges the test results in the log file and publishes the build artifacts. It then goes to sleep and waits for the next time to build. When it awakens, it checks the CVS repository for modifications and, if it finds any, it runs another build; otherwise it goes to sleep and waits for the next time to build.

      Listing 20. Running a build
      Project L_AddressCleansingService: merging accumulated log files
      Project L_AddressCleansingService: publishing build results
      Project L_AddressCleansingService: idle
      Project L_AddressCleansingService: next build in 1 minutes
      Project L_AddressCleansingService: waiting for next time to build
      Project L_AddressCleansingService: No modifications found, 
         build not necessary.
      Project L_AddressCleansingService: idle
      Project L_AddressCleansingService: next build in 1 minutes
      Project L_AddressCleansingService: waiting for next time to build
  5. Track the status of the build

    CruiseControl starts an instance of Jetty and a Web application that you can use to track the status of the build. The Web application’s URL is http://<host>:8080/cruisecontrol, where <host> is the machine where CruiseControl is running. Thus, to view the current status of the build, all you have to do is open a browser and navigate to that URL. A Web page will display the status of your project’s build as well as the build status of all other projects. You can click on a project name to see a build results page like Figure 1..

    Figure 1. View the status of the build
    Figure 1. View the status of the build

    Another way to view the status of the build is by receiving e-mails. You can do this by adding the <email> element to the set of <publishers> in the config.xml file (see Publish the build artifacts).

    Listing 21. E-mail notifications
       <always address="dhvines@us.ibm.com"/>
       <failure address="dhvines@us.ibm.com"/>

    In this example, one address will always receive e-mails of the build status, and another e-mail address will only receive e-mails of failures. The e-mail has a link to the build results page (Figure 1). You can even send notifications to the users who committed the changes by using the <htmlemail> publisher.


This two-part article discussed test-driven development in an SOA environment. In Part 1, you learned how to write test cases for SCA data maps before developing SCA business processes with WebSphere Integration Developer, and in Part 2, you learned how to set up a continuous integration server for testing the SOA applications on WebSphere Process Server.

With this continuous integration server, you learned how to poll the CVS repository for changes to the SOA applications. If changes were detected, then the continuous integration server would check all the code out of CVS, build the SCA modules, install them to WebSphere Process Server, run the unit tests, and record the build results.

You can view the build results anytime by visiting a URL to the CruiseControl Web application or by receiving e-mail notifications. If a bug is found in the SOA application, then an error report can be sent by e-mail to the team members who committed the changes so they can immediately take action.

Continuous integration makes sure that your service (and all services that are dependent upon yours) gets tested whenever there are changes. If test failures occur, you can quickly fix them since you only need to investigate the changes that were made since the last build. This enables you to keep your SOA applications releasable at all times.


Sample codePart2ContinuousIntegrationDownload.zip5 KB



developerWorks: Sign in

Required fields are indicated with an asterisk (*).

Need an IBM ID?
Forgot your IBM ID?

Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.


All information submitted is secure.

Dig deeper into Business process management on developerWorks

Zone=Business process management, WebSphere, SOA and web services
ArticleTitle=Test-driven development in an SOA environment: Part 2: Continuous integration with WebSphere Process Server