|
|
Step 5: coding the test client
n EJB on its own is no use; we will need at least a
simple client to use its services. A user of EJBs may be another EJB, and
ordinary JavaBean, a JSP page, and applet, or a stand-alone application. In
this example, for simplicity, we will code a simple application. This
application will create an object of class Interest, and execute its one
method.
I should point out straight away that the test client I
will present below does not illustrate how you should code this sort of thing
in practice; I've done it this way to show exactly what's going on. In reality,
you will probably want to separate out the RMI-specific stuff into a separate
class to divide the important functionality from the technical details. This
class is sometimes called a `stub'. Some EJB products will generate stubs
automatically; jBoss doesn't do this, so you'll have to code the stubs yourself
(it isn't difficult).
Here is the test client:
Test client: InterestClient.java
import javax.naming.*;
import com.web_tomorrow.interest.*;
import java.util.Hashtable;
import javax.rmi.PortableRemoteObject;
import com.web_tomorrow.interest.*;
/**
This simple application tests the `Interest' Enterprise JavaBean which is
implemented in the package `com.web_tomorrow.interest'. For this to work, the
Bean must be deployed on an EJB server.
IMPORTANT If you want to test this in a real client-server
configuration, this class goes on the client; the URL of the naming provider
specifed in the class must be changed from `localhost:1099' to the URL of the
naming service on the server
*/
class InterestClient
{
/**
This method does all the work. It creates an instance of the Interest EJB on
the EJB server, and calls its `calculateCompoundInterest()' method, then prints
the result of the calculation.
*/
public static void main(String[] args)
{
// Set up the naming provider; this may not always be necessary, depending
// on how your Java system is configured.
System.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
System.setProperty("java.naming.provider.url",
"localhost:1099");
// Enclosing the whole process in a single `try' block is not an ideal way
// to do exception handling, but I don't want to clutter the program up
// with catch blocks
try
{
// Get a naming context
InitialContext jndiContext = new InitialContext();
System.out.println("Got context");
// Get a reference to the Interest Bean
Object ref = jndiContext.lookup("interest/Interest");
System.out.println("Got reference");
// Get a reference from this to the Bean's Home interface
InterestHome home = (InterestHome)
PortableRemoteObject.narrow (ref, InterestHome.class);
// Create an Interest object from the Home interface
Interest interest = home.create();
// call the calculateCompoundInterest() method to do the calculation
System.out.println
("Interest on 1000 units, at 10% per period, compounded over 2 periods is:");
System.out.println (interest.calculateCompoundInterest (1000, 0.10, 2));
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}
It's important to understand that in reality this client will be running on a
different computer to the Bean server. For testing you will probably run them
on the same computer, but it will still be using a network connection. So the
first part of the program indicates how to find the server.
System.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
System.setProperty("java.naming.provider.url",
"localhost:1099");
There are several other ways to do this, which you may see described in other
articles. In this case, the server is on the same machine as the client
(`localhost') and the default naming port is `1099' for jBoss (other servers
may use different port numbers). If you run the client and the server on
different machines, you will need to change these settings.
The comments in the program should describe how it works; one point that
requires mention is that the recommended way to get a reference to the home
interface on the server is like this:
InterestHome home = (InterestHome)
PortableRemoteObject.narrow (ref, InterestHome.class);
which ensures compatibility with different RMI servers (e.g., CORBA). `narrow'
ensures that the object returned in `ref' really can be converted to an object
of class `InterestHome'.
The test client doesn't need to be in the same package as the EJB classes, and
in practice it probably won't be. So it needs to import the EJB classes using
their fully-qualified class name, like this:
import com.web_tomorrow.interest.*;
You will also need to pay attention to the CLASSPATH when compiling. Even
though the EJB classes will run on the server, they need to be
identified to the client so that the compiler can do the appropriate type
checking. In the example program I have put the client at the top level of the
directory hierachy, so if the CLASSPATH includes the current
directory it will correctly find the EJB classes which are in the directories
beneath it.
javac -classpath usr/lib/jboss/lib/ext/ejb.jar:. InterestClient.java
This generates InterestClient.class in the current directory.
|