EJB Handles

In everything we have done so far, we have followed the standard model of locating a “home” object, and then using it to create or find the EJB. Also, since there are no finders in the case of session beans, once the program using a session bean exits, the bean is gone in our model.
There is another model provided for getting to EJBs. This method uses “handles”. Each home or bean object has a handle. You can ask for this handle from the home or bean object. Later on, you can get back to the object by using the handle.
The handle doesn’t just work during the running program, it even works if your program exits and is restarted, or if the handle is used from another program. The handle itself is like a permanent object. Of course, if your program exits, it has to have a way to save the handle. This can be done simply by writing the handle to a file (or any another such method of passing or preserving bytes.) The handle derives from java.io.Serializable, so it can be written to files.
The code to obtain a handle from an EJB object and to get an EJB object back from a handle is fairly straightforward. The following code fragment shows how to obtain a handle from a bean object called “stock” and to write it into a file:

Handle handle = stock.getHandle();
ObjectOutputStream p = new ObjectOutputStream(
new FileOutputStream("C:\\SaveHandle.dat"));
p.writeObject( handle );
//Once the handle has been saved, 
//it can be read back from the file and object created from it:
ObjectInputStream p = new ObjectInputStream(
new FileInputStream( "C:\\SaveHandle.dat"));
Handle handle = (Handle) p.readObject();
StockQuotes stock = (StockQuotes) handle.getEJBObject();
// Use PortableRemoteObject in 1.3 or when available.

Note that the object returned by getEJBObject() has to be cast into the correct type. An important item to remember about handles is that session beans are discarded after a certain timeout. Therefore, if you use a session bean’s handle after that certain timeout, you will not get the bean back. Instead, an exception will be thrown. (The timeout value can usually be changed, see server documentation for this.)
Exercise: Modify your session bean client to save a handle to the (stateful) StockQuotes bean. Write another program that retrieves the handle and gets the bean. Confirm that the “stock” member variable of the bean is the same as when saved. Obtain the price from this “recovered” bean. Try using your second bean within the timeout period, and after the timeout period.

The deployment descriptor

As you may have noted, in all the frameworks created by the wizzard, a folder (sub-directory) named “Meta-inf” is created, containing a file “ejb-jar.xml”. Every EJB jar file is required to contain a file “Meta-inf/ejb-jar.xml” to describe the EJB.
This is an XML file and you can open it in Internet Explorer (as of this writing, Netscape Navigator does not have XML display built-in) and examine its structure. You will notice that this is a tree-like structure, with nodes containing branches.
The top level node is named “ejb-jar”. Underneath it, there is a brief textual “description” node, and another node called “enterprise-beans”. The “enterprise-beans” node further contains a “session” and/or “entity” nodes, depending upon what kind of EJBs are present. (Multiple EJBs may be included in a single Jar file.)
If you drill down in the tree further, you will notice that “session” or “entity” nodes contain the name of the EJB, fully qualified names of the home and remote classes, and the ejb-class (the implementation class for the remote interface.) For entity beans, the primary class is also specified, and a node specifies that “persistence-type” is “Container”. Normally, for an entity bean, the “persistence” is managed automatically by the container. If you wish to load and unload the bean data yourself, you can set persistence-type to user and write the body of the ejbLoad and ejbStore functions to load and store the data.
There are some nodes called “cmp-fields”. The “cmp” stands for “container managed persistence”, so these are only needed if the persistence-type is container. There should be a “cmp-field” for each field of the EJB that is to be managed by the container.
Most of the other things should be relatively obvious. Note the “level” of the nodes. In the next few chapters, we will be talking about the “level” of a node and adding items “below” or “at the same level as” it. Or alternatively, some nodes being “children” of some other node and some nodes being “siblings”.
For instance, at the same level as the “enterprise-beans” node, another node can be added, called “assembly-descriptor”. This means the XML will look like:

.... details of enterprise beans...
... details of assembly descriptor

Note that the “assembly-descriptor” goes after the end of “enterprise-beans”, but before the end of the parent node “ejb-jar”. Here “assembly-descriptor” is a sibling of “enterprise-beans” node and “ejb-jar” is the parent of both.
As another example, the “env-entry” and “ejb-refs” nodes go “below” the “session” node, at the same level but after “transaction-type” node. So this might look like:

... details of env-entry ...
... details of ejb-refs ...

Notice that the env-entry and ejb-refs node go before “session” node has been closed, making them go “below” or “as children of” the session node. But they go after the “transaction-type” node has been closed, making them “at the same level at” or “as siblings” of the “transaction-type” node.
The full syntax of the deployment descriptor has a lot of detail. The goal in this tutorial is not to provide a reference for the deployment descriptor (you can find the reference in other places) but to familiarize you with its structure and usages so you will be easily able to make sense of reference documents.

Exercise: Familiarize yourself with the deployment descriptors of all the EJBs we have created. In the next lessons, we will be making changes to these deployment descriptors.