Published: April 2, 2001
By Richard G. Baldwin
Java Programming, Lecture Notes # 1322
A cookbook approach
Previous lessons in this series provided accelerated instructions to help you get your first enterprise bean up and running as quickly as possible.
In working through the accelerated lessons, I provided the information more or less in a cookbook fashion.
A change of pace
Now that you have your first enterprise bean running successfully in your J2EE server, it is time to slow down the pace, and embark on the task of understanding Enterprise JavaBeans (not only what, but also how and why).
The purpose of the remaining lesson in this series on EJB will be to help you really understand what enterprise beans are, how to write them, and how to use them to advantage.
From this point on, I intend to go much more slowly explaining things more carefully as I proceed. Along the way, I will show you lots of sample bean programs, each of which will be as simple as I can make it while still illustrating the concept that the program is intended to illustrate.
Recommended supplementary reading
It is strongly recommended that you study the previous lesson entitled Enterprise JavaBeans: Middle-Tier Servers and J2EE before embarking on this lesson.
Additional supplementary material that I have written is available at Gamelan. As of the date of this writing, Gamelan does not maintain a consolidated index to my Java tutorials. Therefore, they may be difficult to locate on the Gamelan site. A consolidated index with links to the tutorials on the Gamelan site is available at Baldwin's Java Programming Tutorials.
Viewing tip
You may find it useful to open another copy of this lesson in a separate browser window. That will make it easier for you to scroll back and forth and refer to earlier material without losing your place.
This sample program will require deployment procedures that are a little different than those that I have shown you in previous lessons. In particular, this program includes a helper class that the primary bean class uses to accomplish the objectives of its business method. You must make certain that you cause the class file representing the helper class to be included in the bean's jar file when you deploy the bean.
Helper classes
The purpose of this bean is to illustrate the use of helper classes. Helper classes are classes that the primary bean class calls upon to successfully execute its business methods.
This bean receives and returns a String object via a single business method named aBusinessMethod(). When the business method is invoked by the client, the business method instantiates an object of another class named AHelperClass and invokes a method on that object named getTheDate(). The method named getTheDate() returns a String representation of the current date and time.
(Obviously, this could be accomplished without a helper class, but the objective here is to illustrate the use of helper classes and this is one way to do that.)
Business method returns the date and time
The business method concatenates the string Hello onto the incoming String producing a new String. It concatenates the date string onto that String with a newline character separating the two, producing the final String. It then returns the final String that results from the concatenation process.
The string that is returned is:
"Hello" + <incoming string> + '\n' +
<date/time>
where the material in angle brackets varies from one invocation of the business method to another invocation of the business method.
A little more complicated...
This bean is slightly more complicated than the bean that I used to teach you how to write, compile, deploy, and run a stateless session bean in the previous lessons. I am providing this bean to give you additional practice in deploying a bean.
The punch line
Class files for helper classes must be encapsulated in the jar file that contains the primary bean class files along with the class files for the remote and home interfaces, the manifest, etc.
After you deploy the bean, it would be a good exercise for you to unzip the resulting J2EE application file, and the bean's jar file to confirm that you did successfully encapsulate the class file for the helper class in the bean's jar file.
My results
My J2EE application file (produced by the deployment process)
was named Helper01.ear. The bean's jar file contained within
the application file was named ejb-jar-ic.jar. The contents
of the bean's jar file are shown in Listing 1 below (META-INF. indicates
a sub directory).
META-INF.ejb-jar.xml META-INF.MANIFEST.MF AHelperClass.class HelperRemote.class HelperBean.class HelperHome.class Listing 1 |
Four class files were encapsulated
As you can see, the bean's jar file contained class files for the bean, the remote interface, the home interface, and the helper class. It also contained a deployment descriptor file named ejb-jar.xml, and a manifest file named MANIFEST.MF.
The deployment descriptor file
Listing 2 below shows the contents of the deployment descriptor file
(note
that I had to manually enter some line breaks and use a very small font
to make it fit in this narrow presentation format). You might
find it useful to examine the contents of your deployment descriptor file
to see if you can correlate various elements in the file with actions that
you took during the deployment process.
<?xml version="1.0" encoding="Cp1252"?> <!DOCTYPE ejb-jar PUBLIC '-// Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN' 'http://java.sun. com/j2ee/dtds/ejb-jar_1_1.dtd'> <ejb-jar> <description>This bean illustrates the use of helper classes. </description> <display-name>Helper01JAR </display-name> <enterprise-beans> <session> <description>no description</description> <display-name>Enterprise Bean</display-name> <ejb-name>Enterprise Bean</ejb-name> <home>HelperHome</home> <remote>HelperRemote</remote> <ejb-class>HelperBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Bean</transaction-type> </session> </enterprise-beans> </ejb-jar> Listing 2 |
The contents of your deployment descriptor file may not match mine exactly, because you may use different names and different descriptions during deployment. However, everything highlighted in boldface in Listing 2 should probably match.
The manifest file
Listing 3 below shows the contents of the manifest file.
Manifest-Version: 1.0 Listing 3 |
The output
When the business method was executed on the bean by the simple client program shown in Listing 11, the following output was produced on my client screen. Obviously, your date and time will be different.
Bean returned: Hello Dick Baldwin
Mon Jan 08 18:19:34 CST 2001
The bean was tested using Sun J2EE and JDK 1.3 under WinNT 4.0.
The bean class declaration
The first fragment, shown in Listing 4 below, shows import directives,
along with the declaration of the bean class, and the declaration of an
instance variable, capable of storing a reference to a SessionContext
object.
import javax.ejb.*; import java.util.Date; public class HelperBean implements SessionBean{ SessionContext ctx; Listing 4 |
Recall that a class file from which a session bean will be instantiated must implement the SessionBean interface.
Nothing in Listing 4 above is particularly interesting. I included it here simply for completeness.
The business method
Listing 5 below shows the only business method belonging to the bean.
public String aBusinessMethod( String str){ return "Hello " + str + '\n' + new AHelperClass().getTheDate(); }//end aBusinessMethod() Listing 5 |
The interesting thing about this method is the fact that it instantiates an object of the helper class, and invokes a method on that object to get a String representation of the current date and time. It concatenates that string onto another string and returns the fully-concatenated String object to the client program.
Remaining code in the bean class
Listing 6 below shows the remaining code in the bean class. It might be worthwhile to point out that the four callback methods that are used to deal with the life cycle events of the bean are defined as empty methods. (I didn't need to do anything special when the life cycle events occurred.)
Otherwise, there is nothing particularly interesting in Listing 6.
I included this fragment for completeness also.
public void setSessionContext( SessionContext ctx){ this.ctx = ctx; }//setSessionContext() //Note that the following // callback methods are empty. public void ejbCreate(){} public void ejbRemove(){} public void ejbActivate(){} public void ejbPassivate(){} //public constructor public HelperBean(){} }//end class HelperBean Listing 6 |
The helper class
Finally, Listing 7 below shows the simple definition of the helper class
that the business method uses to get a String representation of
the current date and time.
class AHelperClass{ String getTheDate(){ return new Date().toString(); }//end method getTheDate(); }//end class AHelperClass Listing 7 |
The most interesting thing about the code shown in Listing 7 is the fact that it exists, and the fact that the class file that results from the compilation of AHelperClass must be contained in the bean's jar file. You accomplish that by including it in the set of class files that you specify for inclusion in the bean's jar file on the deployment screen shown in Figure 1 below.
Figure 1. Deployment screen used to add files to a bean's jar file.
(You should recognize Figure 1 as one of the screens that appears when you use Sun's J2EE deployment tool. If you don't recognize it, you will need to review the previous lessons in this series, including the lesson entitled Enterprise JavaBeans(TM): Getting Started with EJB, Part 5.)
The home interface
The source code for the home interface is shown in Listing 8.
Hopefully, you will remember that every bean must have a home interface,
and a remote interface, and that the home interface must declare one or
more overloaded create() methods for the bean.
/* File HelperHome.java Copyright 2001 R.G.Baldwin **************************************/ import javax.ejb.*; public interface HelperHome extends EJBHome{ public HelperRemote create() throws java.rmi.RemoteException, javax.ejb.CreateException; }//end interface Listing 8 |
The remote interface
The source code for the remote interface is shown in Listing 9 below.
Again, hopefully, you will remember that the remote interface must declare
all the business methods belonging to the bean.
/* File HelperRemote.java Copyright 2000 R.G.Baldwin **************************************/ import javax.ejb.*; import java.rmi.*; public interface HelperRemote extends EJBObject{ String aBusinessMethod(String s) throws RemoteException; }//end interface Listing 9 |
The client program
A complete listing of the client program that I used to exercise this bean is shown in Listing 11 near the end of the lesson. There is nothing new in that program, so I won't discuss it further in this lesson. If you don't understand what you see there, you should go back and study the lesson entitled Enterprise JavaBeans(TM): Getting Started with EJB, Part 7.
During deployment, you must make certain that you cause the class file representing that helper class to be included in the bean's jar file. You do that using the deployment screen shown in Figure 1 above.
Other than the existence of the helper class, the sample bean program provided in this lesson is no more complicated than the bean program that I used to teach you how to deploy stateless session beans in the previous lessons.
/* File HelperBean.java Copyright 2001 R.G.Baldwin Rev 1/6/01 The purpose of this bean is to illustrate the use of helper classes. Helper classes are classes that the primary bean class calls upon to successfully execute its business methods. This is a stateless session bean. This bean receives and returns a String object via a single business method. When the method is invoked by the client, it instantiates an object of a class named AHelperClass and invokes a method on that object named getTheDate(). That method returns a String representation of the current date and time. The business method concatenates the String Hello to the incoming String. It concatenates the date string onto that String with a newline character separating the two. It then returns the String that results from the complete concatenation operation. The String that is returned is: "Hello" + <incoming string> + '\n' + <date/time> The class files for helper classes must be encapsulated in the jar file that contains the primary bean class files along with the class files for the remote and home interfaces, the manifest, etc. When the business method was executed on the bean by a simple client, the following output was produced on the client screen: Bean returned: Hello Dick Baldwin Mon Jan 08 18:19:34 CST 2001 Tested using Sun j2ee and JDK 1.3 under WinNT 4.0 workstation. **************************************/ import javax.ejb.*; import java.util.Date; public class HelperBean implements SessionBean{ SessionContext ctx; public String aBusinessMethod( String str){ return "Hello " + str + '\n' + new AHelperClass().getTheDate(); }//end aBusinessMethod() public void setSessionContext( SessionContext ctx){ this.ctx = ctx; }//setSessionContext() //Note that some of the following // callback methods are empty. public void ejbCreate(){} public void ejbRemove(){} public void ejbActivate(){} public void ejbPassivate(){} //public constructor public HelperBean(){} }//end class HelperBean //===================================// //This class is a helper class. The // class file for this class must be // encapsulated into the bean's jar // file. class AHelperClass{ String getTheDate(){ return new Date().toString(); }//end method getTheDate(); }//end class AHelperClass Listing 10 |
/* File HelperClient.java Copyright 2001 R.G.Baldwin Rev 1/6/01 This client program was tested with the bean named HelperBean. That is a simple session bean that receives and returns a String object. The purpose of HelperBean is to illustrate the use of helper classes by the primary bean class to execute its business methods. The following output was produced in the client window: Bean returned: Hello Dick Baldwin Mon Jan 08 18:19:34 CST 2001 Tested using Sun JDK1.3 with J2EE1.2.1 under WinNT WkStn 4.0. **************************************/ import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; import HelperRemote; import HelperHome; public class HelperClient{ public static void main( String[] args) throws Exception { //Get a reference to the bean's // home interface. MyHelper01 is // the JNDI name for the bean. try { Context initial = new InitialContext(); Object objRef = initial.lookup( "MyHelper01"); HelperHome refToHome = (HelperHome) PortableRemoteObject. narrow(objRef, HelperHome.class); //Use the home reference to // create the bean object and get // a remote reference. HelperRemote refToRemote = refToHome.create(); //Invoke a business method on the // remote reference to the bean String returnValue = refToRemote.aBusinessMethod( "Dick Baldwin"); System.out.println( "Bean returned: " + returnValue); //Remove the bean refToRemote.remove(); }catch (Exception ex) { System.err.println("Exception!"); ex.printStackTrace(); }//end catch }//end main }//end class Listing 11 |
Richard has participated in numerous consulting projects involving Java, XML, or a combination of the two. He frequently provides onsite Java and/or XML training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Java Programming Tutorials, which has gained a worldwide following among experienced and aspiring Java programmers. He has also published articles on Java Programming in Java Pro magazine.
Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.
-end-