 | Level: Introductory Sheldon Wosnick (swosnick@ca.ibm.com), Software Developer, IBM WebSphere Studio Application Developer, IBM Toronto Lab
26 Jun 2002 This article demonstrates how to set up the Cactus framework within Application Developer, and shows how Cactus works with Application Developer's WebSphere Test Environment and server tools.
What is Cactus? 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.
Introduction to the tutorial 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.
Prerequisites 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.
Walk through the tutorial 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 called com.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
lib folder 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's lib
directory 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.jar
cactus.jar
commons-httpclient-20020421.jar
junit.jar
log4j-1.2rc1.jar
- Create (or import the file from the downloadable file below)
a
cactus.properties file 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.properties file 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 of cactus_test when we create and
configure the Web project to contain the server-side test case, we need to
specify this as the contextURL value in the cactus.properties
file. This will only be required on the client side. Import this to the root
of the Cactus client project.
- Create a new
log_client.properties file (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 in listings.txt in
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
EJBServletTestCase
in a package of your choosing. In this tutorial, I used the package com.ibm.swosnick.test.
See Listing 2 for the complete source. This class extends the Cactus ServletTestCase
and implements the setUp() 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
EJBServletTestCase
are 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 infamous sayHelloWorld()
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 the cactus.properties as part of the
Cactus contextURL), and then click Finish.
- Edit the
web.xml file 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 complete
web.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\lib
folder in the Web application from the Cactus distribution.
aspectjrt.jar
cactus.jar
junit.jar
log4j-1.2rc.jar
- Create or import a
log_server.properties file to the WEB-INF\classes
folder. This is the server-side equivalent of the log_client.properties
file 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
lib folder 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 the WEB-INF\lib
folder 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.log file, 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 |
 |
Conclusion 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.
Download | Name | Size | Download method |
|---|
| HelloWorldCactus.zip | 56 KB | FTP | HTTP |
Resources
About the author  | 
|  | 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. |
Rate this page
|  |