Cactus is an open source sub-project in the Apache Software Foundation's Jakarta Project. It is a simple framework for unit testing server-side JavaTM code (that is, servlets, EJBs, Tag Libs, Filters, etc.); the purpose behind Cactus is to "lower the cost of writing tests for server-side code" (see the Project Description in the Apache Cactus documentation). Cactus supports so-called white box testing of server-side code; it extends and uses JUnit, which is a regression testing framework. JUnit, originally written by Erich Gamma and Kent Beck, is available separately at JUnit. JUnit comes packaged with the Cactus distribution, so there is no need to download additional copies. The above link is provided for those who seek more detailed information about JUnit.
Although I will not demonstrate this here, Cactus' Ant support helps facilitate automated testing. The Ant support is a powerful feature and one that differentiates between Cactus and JUnit. Cactus was designed and implemented from the beginning to support integration unit testing, a compromise between code logic unit testing and function unit testing, something that the IBM ® WebSphere® Studio Application Developer (hereafter referred to as Application Developer) unit test tools were also designed in part to provide.
The essential value proposition of Cactus is similar to the philosophy of the unit test server tools in Application Developer; that is, Cactus lets you implement an in-container strategy (including the notions of in-process and within a single JVM instance) in order to unit test components within the actual container in which they will be deployed in production. Most unit test environments that I am aware of use an out-of-container strategy, but both the server tools and the Cactus framework test components running in WebSphere Application Server itself (that is, it is not an artificial approximation). This is just one way in which Cactus surpasses what you could do with JUnit alone.
It is necessary to test from within the application server container for accurate test results. This is the case because no matter how good a test environment is, a server-side component is likely to run slightly differently in production mode (that is, in the real, production-level run-time environment). This could be due to a large number of factors, for example, the specific Java JVM used at run time, the other components interacting in unpredictable ways, the stress or load on the component, or the component logic using differing code paths. When you use the EJB Test Client, you are testing your code in the container in which it is running. If anything undesirable happens, you will notice it. The same can be said about Cactus at a simpler level.
The tutorial below demonstrates how to unit test the methods in EJBs that are running in IBM WebSphere Studio Application Developer using Open Source Apache Software Foundation's Cactus framework (see the Apache Cactus Web site).
By walking through this tutorial, you will see that Cactus fits well with Application Developer's WebSphere unit test environment and server tools as an additional way to provide unit testing support for J2EE components, such as EJBs, servlets, JSPs, and Filters. You will learn, step-by-step, how to set up the environment. As with all configurations and setups, there are likely other ways to set up the Cactus framework to work within Application Developer; I simply share with you one that works for me using Application Developer Version 4.03.
As has been my style in previous tutorials that I have written on testing and debugging in Application Developer, I will not cover the specifics of developing Java, J2EE applications, or complex Cactus unit test cases. Instead, the tutorial's goal is simply to demonstrate that it is fairly straightforward to get started using Cactus in Application Developer and that there is a certain synergy obtained when Cactus is combined with Application Developer (by "synergy," I am referring to the idea that the combined power or whole is greater than the sum of the individual parts).
What can be said of this particular open source project, and which is demonstrated in reference to Apache Cactus, can also be said for a variety of freeware and open source tools and frameworks that are available for building on top of Application Developer.
I will not go into great detail about the Cactus framework because you can easily read about this yourself at the Apache Cactus Web site. Please see my earlier tutorials that walk you through the details of creating and unit testing J2EE applications in Application Developer. The first one, Developing and Testing a Complete "Hello World" J2EE Application with WebSphere Studio Application Developer, shows you how to create and test EJBs. The second article, Developing and Testing a Complete J2EE Application with WebSphere Studio Application Developer -- Part 2: Running on WebSphere Application Server, shows you how to deploy and test a J2EE application on WebSphere Application Server.
To walk through this tutorial, you need WebSphere Studio Application Developer, Version 4.0x (even a trial version will suffice) and the Cactus binaries distribution. This tutorial was developed and tested using the final release of Cactus Version 1.3. The binaries can be downloaded from the Index page.
Not all of the source code and configuration information is
specified in the body of this article. Listings for all of the source code,
scripts, and configuration files are available in listings.txt
in the downloadable file below.
In this tutorial, you will perform the following tasks:
- Download and unzip the Cactus distribution files
- Write a simple stateless session EJB with some simple business methods
- Create and set up a Java project to contain the client-side test case code to run
- Create and set up a Web project to contain the Cactus in-container test cases
- Copy the test case from the client project to the Web project
- Set up the Java build paths for the Web project
- Set up the Java build paths for the client project
- Run your test cases in Cactus within the WebSphere Application Server container
Once all of the J2EE-specific resources are completed, you will have a J2EE View that resembles Figure 1:
Figure 1. The complete J2EE View of what you will create

The following steps cover how to develop the EJB, set up the Cactus framework, write your test case, and unit test with the test case that you will create. In this tutorial, we will focus especially on the development and integration of Cactus and a Cactus test case.
Step 1. Download and unzip the Cactus distribution files
Go to the Apache Web site to download a copy of the Cactus 1.3 binaries to your development machine. After you download the file (note that the file is less than 2Mb), use an archiving tool to unzip the archive to a convenient location on the file system.
Step 2. Write a simple stateless session EJB with some simple business methods
In this step, you will create a simple session EJB, which will serve as a simple EJB example to test. We will create and use a simple stateless session bean because it is easy to understand and develop.
- From Application Developer's J2EE perspective, use the EJB Project Creation
wizard to create an EJB project in the default EAR module. Select File
=> New => Project from the menu bar to launch the New Project wizard.
Select the EJB project from the list, and create a new EJB project called
HelloWorldEJB. Accept the default values, and click Finish. - Select the HelloWorldEJB project (this should already be selected
by default), and then create a new session EJB by selecting New => Enterprise
Bean. Call the EJB
HelloWorld, and create it in a package name of your choosing. In this example, I use a package calledcom.ibm.swosnick.ejb.test.
Figure 2. Creating a simple stateless session bean
- Add the following three business methods to the HelloWorldBean and then
promote them to the remote interface. Feel free to change the implementation
to suit your needs. See Listing 1 in the download file below
for the code snippet.
public String sayHelloWorld() { return "Hello World!"; } public String sayHelloWorld(String firstName) { return "Hello World " + firstName + "!"; } public String sayHelloWorld(String firstName, int age) { return "Hello World " + firstName + ", you are " + age + " years old!"; } - Right-click the EJB project and select Generate deploy and RMIC code
from the pop-up menu. Select the HelloWorld check box when prompted.
Ensure that the JNDI name for the session bean will be the same name you will
later use when doing up a lookup of the home interface.
- Open the EJB JAR file using the EJB Extension Editor and change the name
in the binding. In my example, I am using an JNDI name of
ejb/HelloWorld. Figure 3 below demonstrates where you need to specify the JNDI name that you will use later from your test case servlet.
Figure 3. Setting the JNDI name for the session bean
- Once you have completed all of the steps for writing and implementing your
simple EJB, you should have an EJB project that looks like Figure 4.
Figure 4. Completed EJB project with RMIC and deploy code
Step 3. Create and set up a Java project to contain the client-side test case code to run
In this tutorial, the Cactus concepts were implemented in a way that will make it easier for beginners to follow and to see "visually" what is happening. Everything is contained within the Application Developer workspace. This makes it possible to move the workspace around or share it with others who may not have the Cactus libraries on the file system. It is, admittedly, a trivial test case for a trivial EJB, but again, the emphasis of this tutorial is on the Cactus framework itself.
In this implementation, you will import various Cactus JAR files to the projects in the workspace and then add these (internal) JAR files to the build classpath rather than simply add them to the build classpath as external JAR files where they were unzipped or may be residing. This gives you a good idea of which JAR files need to be available on the build path and the run-time classpath. I have also chosen to use a separate Java client project to run against the test cases in a Web project (WAR module) which itself is running in the same application server as the EJB. This is the "in-container" strategy at work -- the relationship of the WAR module to the EJB module. To create the client project, complete the following.
- If you have not yet done so, download a copy of the Cactus 1.3 final release
binaries and unzip the archive.
- Create a new Java project called
Cactus Client Project. - To make the Cactus JAR files available on the classpath for the client side,
create a
libfolder in this project and import the JAR files as files (note that you want to import the JAR file itself, not the individual classes in the JAR file) from the Cactus distribution'slibdirectory into Application Developer's workspace. This should be performed from the Navigator perspective; you need to specify a "folder import" with a "selected types" of*.jar, and then specify the following five JAR files, which you will subsequently add to the build path: aspectjrt.jarcactus.jarcommons-httpclient-20020421.jarjunit.jarlog4j-1.2rc1.jar- Create (or import the file from the downloadable file below)
a
cactus.propertiesfile as part of the Cactus Client Project as depicted in Figure 5 below. This file specifies the servlet redirector name and the context URL of the Web project:cactus.contextURL = http://localhost:8080/cactus_test cactus.servletRedirectorName = ServletRedirector cactus.enableLogging = true
A
cactus.propertiesfile edited as above is ready to import and is provided for you in the download file. Since we will be using a Web context root ofcactus_testwhen we create and configure the Web project to contain the server-side test case, we need to specify this as the contextURL value in thecactus.propertiesfile. This will only be required on the client side. Import this to the root of the Cactus client project. - Create a new
log_client.propertiesfile (or import the file from the downloadable file below) as part of the Cactus Client Project (see Figure 5), assuming that you want to enable client and server logging support using Log4j. You do not need to enable logging, but here, I demonstrate which configuration and JAR files you need in the classpath should you decide to use it. See Listing 3 inlistings.txtin the download file for the complete configuration source. Likewise, import this into the main project folder. - Now, create your Cactus test case; this needs to exist physically in both
the client and the server projects (the reasoning behind this is explained
later). First, create a new Java class called
EJBServletTestCasein a package of your choosing. In this tutorial, I used the packagecom.ibm.swosnick.test. See Listing 2 for the complete source. This class extends the Cactus ServletTestCase and implements thesetUp()method; this method is used to call the standard boilerplate code to set up the JNDI initial context and to retrieve a reference to the home interface. A lookup is performed using the JNDI name that you earlier bound into the EJB. The Cactus framework will invoke this automatically for you when you run the test case from the client. - The other parts of the
EJBServletTestCaseare self-explanatory and contain the actual test methods. For more information on how this works, refer to the Cactus Javadocs and their documentation. In this example, you will expose three test methods that test each of the three overloaded varieties of the infamoussayHelloWorld()method in the EJB. In this method, you have the option of performing any number of assertions from the JUnit framework to determine if a given condition or a given state is what you expect. For example, there is a test method like the following with some simple assertions:public void testHelloWorld2() throws Exception { String message = helloWorld.sayHelloWorld("Sheldon"); System.out.println("Message returned: " + message); assertNotNull(message); assertEquals(message, "Hello World Sheldon!"); } - Once this project is built (note that we still need to set the classpaths
which we will do subsequently), it should resemble Figure 5 below.
Figure 5. The completed client-side project with the test case deployed on the client
Step 4. Create and set up a Web project to contain the Cactus in-container test cases
In this step, you will create the Web project, which will contain the in-container test case to test invoke test methods on the EJB from the Web module which resides in the same EAR module. Although the WAR module runs in a Web container and the EJB in an EJB container, both containers run in the single application server which executes in a single JVM process. In this sense, the application server process itself is the common container for the Web and EJB containers.
- In the Application Developer J2EE perspective, select New => Web Project,
and use the Create Web Project wizard to create a Web project in the default
EAR module. Call the project
Cactus Testing Web Project. - Set the context root for the Web application to
cactus_test(this is what you used in thecactus.propertiesas part of the Cactus contextURL), and then click Finish. - Edit the
web.xmlfile that is generated when you first created the Web project using Application Developer's XML editor. These edits add the servlet redirector used by Cactus to redirect the call to the EJB. See Listing 4 in the download file below for the completeweb.xml. The important sections in this configuration are where you specify the servlet and the servlet mapping for the Web application:<servlet> <servlet-name>ServletRedirector</servlet-name> <servlet-class>org.apache.cactus.server.ServletTestRedirector </servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletRedirector</servlet-name> <url-pattern>/ServletRedirector</URL-pattern> </servlet-mapping> - To keep things simple, import as files the following JAR files to the
WEB-INF\libfolder in the Web application from the Cactus distribution. aspectjrt.jarcactus.jarjunit.jarlog4j-1.2rc.jar- Create or import a
log_server.propertiesfile to theWEB-INF\classesfolder. This is the server-side equivalent of thelog_client.propertiesfile that you earlier added. See Listing 5 in the download file for the configuration.
Step 5. Copy the identical test case from the client project to the Web project
From the navigator view, copy the EJBServletTestCase.java
source from the client Java project to the Web project's source
folder. There, it will be compiled automatically by default, and the corresponding
class file will be created in the WEB-INF\classes folder from where
the application server will be able to load it at run time.
You may be wondering why you have been instructed to copy the identical test case source code from the client project to the server project. The reason is that this supports how the tutorial is implementing the Cactus architecture for Application Developer. The Cactus framework was apparently designed in a such a way that you could: 1) maintain two classes of the same name but with slightly different implementations between the client and the server, or 2) have the test case be present on both the server side and on the client side. The chief contributor to the project, Vincent Massol, has indicated to me on some earlier exchanges that when they designed Cactus, they had to make a choice. For each test case that the user writes, should the user have to write all of the text methods in two classes or write the text methods in one class only, but have this class get instantiated twice (on the server side and one on the client side, although each side is not calling the same methods). Massol indicated that they chose the second solution to reduce the overhead associated with having to create new test cases (the compromise is that it would be a bit more complex to understand the mechanism, but certainly it would improve the ease of use).
Therefore, as Massol has indicated, when a user makes modifications
to one file, he or she also needs to make the same modifications to the other
file. Or, you can consider them as two different files but with the same name:
the client-side test case, which would contain beginXXX()
and endXXX() methods, and the server-side test
cases, which would contain the testXXX() methods.
That is, all of the beginXXX() and endXXX()
methods from JUnit are executed on the client side and the testXXX()
methods are executed on the server side. Furthermore, according to Massol, "there
is no real hard requirements to have the same class duplicated twice. It could
be two classes (that is, different and exclusive content) but be named the same."
The simple way that I have documented -- that is, implementing Cactus in Application
Developer to utilize the framework within a client project and a server Web
project (WAR module) -- was not what Cactus was originally intended for, but,
as Massol concludes when I bounced the idea off of him, "It is a solution if
it works for you....The only issue is when you have to write a test case, you
have to write two classes, but [Application Developer] may make this so trivial
so that is it not an issue at all. Also, I agree that [Application Developer]
makes it more clear (especially for newcomers) by separating into two projects."
In my particular implementation, the EJBServletTestCase
test case class has to be in two places -- on the client and server side --
as it is run from two places. A JUnit testrunner will run the beginXXXX
and endXXXX methods of a test case on the client
side, and then the second identical copy of the class will be used by the server
to run the setup, testXXXX, and tearDown
methods on the server. So, in other words, to use my strategy, simply write
one test case class, and then always deploy to both the client and the server.
Once you understand these architectural decisions and follow this rule of thumb,
it is very easy to create powerful test cases for your server-side components.
Once this project is built (note that we still need to set the classpaths here as well), it should resemble Figure 6 below.
Figure 6. The completed Web project

Step 6. Set up the Java build paths for the Web project
Since the code references a number of classes in the Cactus
distribution as well as the EJB code, you must add these references to the build
classpath. Since you previously imported the JAR files into the WEB-INF\lib
folder and the test case to the source folder (which builds to the WEB-INF\classes
folder), then the JAR files are automatically added to the build path. You do,
however, have to resolve the references to the EJB.
First, add the HelloWorldEJB project to the build path because you reference EJB code in the servlet test case.Right-click the project, and launch the properties dialog. Go to the Java Build Path, and click the Projects tab. Then, select the HelloWorldEJB project as shown in Figure 7 below.
Figure 7. Set up the projects build path for the Web project

As already mentioned, since you added the JAR files to the
WEB-INF\lib folder, then they are now on the build path. See Figure
8.
Figure 8. JAR files automatically added to the build path for the Web project

Step 7. Set up the Java build paths for the client project
- Perform the equivalent step for the client project to make the EJB project
available on the build path.
Figure 9. Set up the projects build path for the client project
- Since the code references a number of classes in the Cactus distribution,
you must add these references to the build classpath. Since you previously
imported the JAR files into a
libfolder that you created, it is a simple matter to add these JAR files to the classpath. This is still required in a Java project even if you import a JAR file to the project (which is different than if you import the JAR file to theWEB-INF\libfolder of a Web project). Right-click the project, and launch the properties dialog. Go to the Java Build Path, and click the Libraries tab. Then, click the Add JARs button to add each of the JAR files that you imported. See the Application Developer documentation if you need more help with this.
Figure 10. Set up the libraries and JAR file build paths for the client project

Step 8. Run your test cases in Cactus within the WebSphere Application Server container
The Eclipse Release 2.0 preview currently supports an integrated way of launching JUnit test cases; Eclipse.org provides some information on plugins designed for Eclipse Release 1.0 which Application Developer 4.03 is based on. (Note that if you wish, you can run the the test case class which contains a main() and invokes the JUnit junit.swingui.TestRunner.main method. This is the method I describe here which does not depend on other plugins being present for Application Developer 4.03.)
- First, create a WebSphere Application Server 4.0 unit test server project,
server instance, and server configuration. Add the DefaultEAR to it. To do
this, select File => New => Project from the menu bar to launch the
New Project wizard. Select Server from the left pane, and then select
Server Project from the right pane. Give the server project any name
you like. Then, click Finish. Once you do so, you will be switched
into the Server perspective. Select the server project that you just created,
and right-click to bring up a drop-down menu. Select New => Server and
Server Configuration; the Create a New Server and Server Configuration
wizard opens. Name the server anything you like, and select WebSphere v.4.0
Unit Test Environment as the server type from the drop-down menu. Accept
the remaining default values, and click Finish.
- Start the server in non-debug mode, which allows for more efficiency since
you will not be doing any debugging. The easiest way to do this is from the
Server view in the Server perspective; simply click the running person icon
to start the server.
- In the Cactus client project, select the EJBServletTestCase class
and then click the running person icon on the toolbar. As mentioned, this
will call the JUnit TestRunnner. Once the tests on the EJB are executed without
failure, the TestRunner should look like Figure 11 below. The example provided
should not generate a failure, so you should not expect any failures in the
result. You may want to introduce intentional points of failure to see what
happens.
Figure 11. The JUnit TestRunner running the test case class
- The console will switch to the JUnit TestRunner process and the server console
output will not be visible. Once all three tests that you defined have been
executed, switch back to the server process in the process tab, and take a
look at the console output. It should have output indicating that the ServletRedirector
servlet was initialized. The Strings returned from invoking the three EJB
methods should be printed out as well.
Figure 12. Running the main class of the test case from the client project
- The output to the
cactus_client.logfile, typically written to the root of the Application Developer installation, should resemble the following if the test case ran successfully.21:03:01,879 [TestRunner-Thread] DEBUG test.EJBServletTestCase - ------------- Test: testHelloWorld1 21:03:02,189 [TestRunner-Thread] DEBUG test.EJBServletTestCase - ------------- Test: testHelloWorld2 21:03:02,279 [TestRunner-Thread] DEBUG test.EJBServletTestCase - ------------- Test: testHelloWorld3
This article described the steps you can take to build a simple J2EE application that consists of an EJB and a Web module within the same WebSphere Application Server server container instance. The article also discussed the integration of Apache Foundation's Cactus framework that provides a simple in-container strategy for unit testing J2EE components. Other open source frameworks and tools may be similarly integrated and used to extend the built-in tools in WebSphere Studio Application Developer or to augment them in some way. Hopefully, the tutorial demonstrated how to do this for the the Apache Cactus project. It is left to the reader's imagination to discover how other open source tools and frameworks can benefit from a similar synergy between WebSphere Studio Application Developer and open source.
| Name | Size | Download method |
|---|---|---|
| HelloWorldCactus.zip | 56 KB | FTP |
Information about download methods
- Sheldon Wosnick,
Developing and Testing a Complete "Hello World" J2EE Application with WebSphere
Studio Application Developer, IBM WebSphere Developer Technical Journal,
WebSphere Developer Domain, October 2001.
- Sheldon Wosnick,
Developing and Testing a Complete J2EE Application with WebSphere Studio Application
Developer -- Part 2: Running on WebSphere Application Server, IBM WebSphere
Developer Technical Journal, WebSphere Developer Domain, November/December
2001.
- Apache Cactus home
page

Sheldon Wosnick is a software developer on the IBM WebSphere Studio Application Developer, Server Tools team at the IBM Toronto Lab. With his teammates, he is currently responsible for the entire server run time and unit test environment for Application Developer. Previously, he was a member of the VisualAge for Java WebSphere Tools team. Sometimes fondly known as the "run time guy," he designed and integrated the WebSphere Test Environment and the Apache Tomcat Test Environment for VisualAge for Java, two very popular features in VisualAge for Java. You can reach Sheldon at swosnick@ca.ibm.com.





