Coding and compiling the test client

An 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, an ordinary JavaBean, a JSP page, an 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.

On deployment of the bean as performed in the previous step, the server has bound the EJB home interface under the JNDI name of interest/Interest and exported the home interface so that it can be invoked via RMI. What we are going to cover here is the way you lookup a the home interface using JNDI from a client and invoke methods on it. The example client code is listed in the following figure:

Figure 1.8. Test client, file name


import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;


/** This simple application tests the 'Interest' Enterprise JavaBean which is
 implemented in the package ''. For this to work, the
 Bean must be deployed on an EJB 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)
      // 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
         // 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)

Please note that the client lookup up the InterestHome interface under the JNDI name "interest/Interest". Your bean's home interface has been bound to this name if you supplied a proper jboss.xml file. If not, the JNDI name will be "Interest". Connecting to the JBoss JNDI implementation entails creating an InitialContext object with the correct in the client classpath. In the source, all that is required is:

// Get a naming context
InitialContext jndiContext = new InitialContext();
System.out.println("Got context");

The file we have to use is located in the examples/resources/ of the documentation examples distribution. Its contents are:

This specifies the InitialContextFactory, provider url, and the packages of object factories specific to the JBoss JNDI provider. The provider url can be abbreviated to simply "localhost" or the hostname on which JBoss is running when using the default port of 1099.

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 protocols (e.g., RMI/IIOP). The 'narrow' method ensures that the 'ref' object 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 as illustrated.

To compile and run the InterestClient execute the following ant command:

bash-2.04$ ant intro-interest-client
Buildfile: build.xml



     [echo] Using JBoss directory=/tmp/JBoss-2.2.2
     [echo] Using base classpath=/tmp/JBoss-2.2.2/client/ejb.jar:/tmp/JBoss-2.2.2/client/jaas.jar:/tmp/JBoss-2.2.2/client/jbosssx-client.jar:/tmp/JBoss-2.2.2/client/jboss-client.jar:/tmp/JBoss-2.2.2/client/jnp-client.jar:/tmp/tomcat/lib/servlet.jar
     [echo] Using Source directory=/tmp/examples
     [echo] Using Build directory=/tmp/examples/build-examples



     [echo] Using client classpath: /tmp/JBoss-2.2.2/client/ejb.jar:/tmp/JBoss-2.2.2/client/jaas.jar:/tmp/JBoss-2.2.2/client/jbosssx-client.jar:/tmp/JBoss-2.2.2/client/jboss-client.jar:/tmp/JBoss-2.2.2/client/jnp-client.jar:/tmp/tomcat/lib/servlet.jar:/tmp/examples/build-examples/interest/classes:/tmp/examples/resources
     [java] Got context
     [java] Got reference
     [java] Interest on 1000 units, at 10% per period, compounded over 2 periods is:
     [java] 210.00000000000023


Total time: 2 seconds

The output is what you should see if all goes well. This shows that the classpath used to execute the client included a number of jars located in the JBoss client directory as well as the directory containing the compiled example classes and the directory containing the file. These JBoss client jars contain the standard EJB and JNDI interfaces as well as the JBoss specific container code. The various jars are:

There should be output from the Interest EJB on the server console as well. This is generated to show that the bean has executed on the server, not the client. Look for something like this in the server log or console:

[Interest] Someone called `calculateCompoundInterest!'

Well, that's it. We covered coding, compiling and deploying an EJB, and coding and running a simple test client.