Chapter 22. Building an EJB

In this chapter we write a very simple EJB and compile it.

What You Will Learn

  • What a simple EJB example looks like.

  • What are the several pieces that you need to make an EJB.

  • How to compile the pieces of an EJB.

You’ll find the full text of our example on the book’s Web site at http://www.javalinuxbook.com/. We will only use code excerpts in this chapter.

EJBs: You Don’t Know Beans?

Enough theory about EJBs and naming services and the like. It’s time to put together an actual EJB so you can see one run. First we need to write our EJB classes, then compile them. Then, in the next chapter, we’ll package them, along with other supporting information, into an EAR file. But let’s begin by writing some Java classes.

It’s not that we just write a single EJB class, say a session bean, and we’re done. Keep in mind that we’re going to be using these beans in a distributed environment, so we need a way to have an application running on one system find, create, look up, or otherwise access the bean running on another machine somewhere in our enterprise network. The job of EJBs is to simplify (up to a point) the efforts of the application programmer doing all this, and make it seem as if the bean is quite local or at least independent of location.

Here’s how it works. Any application that wants to use the functions provided by an EJB must first locate the bean. It uses a naming service (Chapter 21) for this. What it gets from the lookup is something called a home interface. The home interface object is in effect a factory for producing remote interfaces, which are the proxies for the actual service(s) that our application wants to use. A remote interface has the method signatures that give the functionality that the application is after, but it doesn’t do the actual work of the bean. Rather, it is a proxy for the bean. The remote interface’s job is to do all the work behind the scenes to marshal the arguments and send them off to the bean, and to unmarshal the results returned from the bean.

So it’s a three step process:

  1. Do the lookup.

  2. Use the home interface to produce a remote interface.

  3. Use the remote interface to call the methods on the bean.

What’s all this talk about interfaces? They provide a way to define the methods you want to use, but without having to write all the code to do it. For example, with the remote interface you may define a method to do something with several arguments, say Blah (a, b, c). Now the remote object doesn’t really do the Blah work; its job is to marshal the arguments (serialized a, b, and c) and send them off to the EJB to do whatever Blah is, and then unmarshal the results. So you as an application programmer will write the guts of Blah in the EJB object, but for the remote object, its proxy, you only need to declare the method signature. Then the job of the EJB container (e.g., JBoss or Geronimo) is to provide the smarts of the proxy—that is, to generate a Java class that implements your interface, along with the code that knows how to contact your EJB and marshal and unmarshal the arguments and results. That’s right, the EJB container (server) makes code that uses your interfaces, along with its own code, to do the infrastructure work of EJBs.

Talking about all these pieces of an EJB can be confusing, too. Sometimes it is helpful to think of an EJB as a single class; sometimes it’s better to think of it as a family of classes that act together pretending to be a single bean that is distributed across several hosts. This can make it a bit confusing when talking about an EJB—do we mean the family of interacting classes or do we mean the single class that provides the application functionality that we want?

The names of EJB classes and EJB interfaces (which we will extend and implement) don’t help much either—they can be confusing, too. For example, we will extend EJBObject, but not to write an EJB session bean; no, we extend SessionBean for that, but EJBObject is the name for the remote interface. Go figure.

A bit of perspective may help here. The names Remote, Local, and Home are used as modifiers on these classes. Local means “on the same host as the bean.” But Home and Remote don’t offer much of a clue. The home interface is what we get from a lookup; it produces remote objects (objects which implement the remote interface). A remote object is what our application uses as if it were a Java object doing what we need, even though its application-specific activity will happen on a bean somewhere else on the network.

Let’s look at a very very simple example, to see the pieces in action.

SessionBean

Let’s write a stateless session bean that will compute the time value of money. Why that? Well, two reasons. First, we already have an SAMoney class with a save() method for computing some values; and second, we need some simple, stateless, but somewhat computationally intensive task to make for a halfway reasonable example.

The real guts of an EJB, the core of the application functionality—in our example, the computation of the time value of money—is the session (or entity) bean. For our session bean we begin by implementing the SessionBean interface, which means that we need to define these methods:

public void setSessionContext(SessionContext context) { }
public void ejbCreate() { }
public void ejbRemove() { }
public void ejbActivate() { }
public void ejbPassivate() { }

which, for our example, we can implement as empty methods. A stateless session bean never needs an activation or passivation method to do anything—it is pointless to passivate a stateless session bean. Why? Since it’s stateless, any instance of it is as good as any other, so the instances are interchangeable and there’s no need to passivate one to get to another—just use the one available. It follows that if a bean is never passivated, it will never have to be activated.

But why no body to the ejbCreate() method? Well, our bean isn’t doing anything extra. This would only be used if our example were more complicated and we needed to do application-specific initializations. For example, if the bean had to connect to a database (and did not use entity beans), it might establish the JDBC connection in ejbCreate and close it in ejbRemove(). Similarly, we can have an empty ejbRemove() method.

Next we add our own methods, the ones that provide the application functionality. For our MoneyBean application, we’ll add save() and debt() methods which will use an SAMoney class by calling its save() and debt() methods. Example 22.1 is the listing of the SessionBean.

Example 22.1. Listing of our implementation of a SessionBean

package com.jadol.budgetpro;
import net.multitool.util.*;

import javax.ejb.*;

/**
 * Actual implementation of the EJB
 */
public class
MoneyEJBean
  implements SessionBean
{
  protected SessionContext sessionContext;
  // typical; just not used now

  public Cost
  save(double amt, double rate, double paymnt)
    throws java.rmi.RemoteException
  {
    return SAMoney.save(amt, rate, paymnt);
  } // save
  public Cost
  debt(double amt, double rate, double paymnt)
    throws java.rmi.RemoteException
  {
    return SAMoney.debt(amt, rate, paymnt);
  } // debt

  public void
  setSessionContext(SessionContext context)
  {
    sessionContext = context;

  } // setSessionContext

  public void
  ejbCreate() { }

  public void
  ejbRemove() { }

  public void
  ejbActivate() { }

  public void
  ejbPassivate() { }

} // interface MoneyEJBean

EJBObject

At the other end of the chain of EJB objects used to accomplish all this distributed computing is the object that our application is actually going to touch. When our application creates an EJB, it, acting as a client, won’t actually get its hands on the distant session (or entity) bean because that session bean is running somewhere out in the network. There will be, however, a proxy object, acting on behalf of the distant EJB. It is described as the remote interface, because it is remote from the EJB (though very close to the application). It is an interface because J2EE supplies a class that does the hidden work of marshaling the data, contacting the EJB, sending the data and receiving the results; the application developer only adds a few additional application-specific methods, via this interface (Example 22.2).

Example 22.2. Sample remote interface

package com.jadol.budgetpro;
import javax.ejb.*;
import java.rmi.*;
import net.multitool.util.*;

/**
 * Remote Interface for the Money EJB
 */
public interface
Money
  extends EJBObject
{
  // the methods from the remote object which we will call
  public Cost
  save(double amt, double rate, double paymnt)
    throws java.rmi.RemoteException;

  public Cost
  debt(double amt, double rate, double paymnt)
    throws java.rmi.RemoteException;

} // interface Money

The crucial thing to note with this interface is that we have defined two methods that match the two methods in our SessionBean—the save() and debt() methods. These are the methods that will actually be called by our application, and the J2EE mechanisms will do their work behind the scenes to connect to the methods of our SessionBean implementation and send back the results.

EJBHome

Between the SessionBean and its remote interface lies the home interface, also called the remote home interface, since it pairs with the remote interface. An object that implements the home interface is the kind of object that is returned after the lookup() and then narrow() method calls. It is used to create a reference to the EJB. The home interface for a stateless session bean needs only implement a single method, the create() method with no arguments. The body of the method needs do nothing. All the real work is done by the underlying object supplied by J2EE.

Example 22.3 is a listing of our home interface. It looks like an empty shell, but it is all that we need. The rest is handled by J2EE.

Example 22.3. Sample (remote) home interface

package com.jadol.budgetpro;
import javax.ejb.*;
import java.rmi.*;

/**
 * Remote Home Interface
 */
public interface
MoneyHome
  extends EJBHome
{
  public Money
  create()
    throws CreateException, RemoteException
  ;

} // interface MoneyHome

Summarizing the Pieces

With these three pieces—the session bean, the remote interface, and the home interface—we can see the structure of the key pieces of an EJB. Let’s review what we have:

Application object

Extends/implements

Talked about as

Money

EJBObject

remote interface

MoneyHome

EJBHome

home interface

MoneyBean

SessionBean

the implementation

EJBLocalHome and EJBLocalObject

When the session or entity bean is going to be referenced by application code that resides on the same host as the bean, there are variations on the home and remote interfaces that allow for more efficient execution. When you know that the beans are local to this host, you should use a local interface (Example 22.4) and a local home interface (Example 22.5). The local interface is in place of the remote interface and extends EJBLocalObject. The local home interface is in place of the remote home interface and extends EJBLocalHome.

Example 22.4. Sample local interface

package com.jadol.budgetpro;
import javax.ejb.*;
import java.rmi.*;

/**
 * Local Interface for the Money EJB
 */
public interface
MoneyLocal
  extends EJBLocalObject
{
  // the methods which we will call

} // interface MoneyLocal

Example 22.5. Sample local home interface

package com.jadol.budgetpro;
import javax.ejb.*;
import java.rmi.*;

/**
 * Local Home Interface
 */
public interface
MoneyLocalHome
  extends EJBLocalHome
{
  public MoneyLocal
  create()
    throws CreateException;

} // interface MoneyLocalHome

Why bother? Well, there’s no need to marshal and unmarshal all that data if the calls are staying on the same host. This saves execution time. Perhaps more importantly, since the arguments don’t have to be marshaled and unmarshaled, they don’t have to be serializable. For some applications, this is the only way that they can use beans.

Finally, keep in mind that the choice of local versus remote interfaces is not necessarily an either-or choice. For our session bean we have defined both kinds of interfaces. Then the deployment can determine which one will be used.

Compiling Your Beans

In order to compile these bean-related Java classes, you need to have a J2EE JAR in your classpath. If you’ve installed JBoss into /usr/local/jboss, you could add the JAR to your classpath this way:

export CLASSPATH="/usr/local/jboss/client"
"/jboss-j2ee.jar:.:${CLASSPATH}"

If you have the Sun J2EE reference implementation installed on your system (in /usr/local), then you could use:

export CLASSPATH="/usr/local/SUNWappserver"
"/lib/j2ee.jar:.:${CLASSPATH}"

If you have Geronimo installed on your system (with an environment variable GHOME to hold its location), then you would use: [1]

export CLASSPATH="${GHOME}/repository/geronimo-spec/jars"
"/geronimo-spec-j2ee-1.0-M1.jar:.:${CLASSPATH}"

In any case, the point is to have in your classpath the JAR file which contains the javax/ejb/ classes, such as EJBObject.class. If you haven’t installed one of these containers on your machine, then download a copy of the JAR from the machine where that container is installed. Put your copy somewhere in your classpath, as in the examples above.

If you are using Ant (and why wouldn’t you be?) you will need to put the path to the J2EE JAR in the classpath which Ant uses. Since Ant can define its own classpath, you may want to define your compile task as something like this:

<target name="compile" >
<javac srcdir="${src}"
    destdir="${build}"
    classpath="/usr/local/SUNWappserver/lib/j2ee.jar:${stdpath}" />
</target>

Now it’s a simple matter to compile. The basic Java compile command:

$ javac com/jadol/budgetpro/*.java

will compile all the various classes and interfaces that make up the EJB. There may be other classes in your source tree that need to be compiled as well. With all that going on, you can see why so many people use Ant. With the compile target defined as in our example above, you would need only the command:

$ ant compile

Review

There are many pieces involved in the construction of an EJB. Besides writing the session bean implementation, there are the remote and home interfaces to be written. The local and local home interfaces are optional, but useful, especially in cases where arguments cannot be serialized or where you know that the beans and the client will reside on the same host. Compiling an EJB is not different from any other Java compile, but it requires a special JAR in your classpath, one that contains the definitions of the J2EE objects and interfaces.

What You Still Don’t Know

We still haven’t shown you how to deploy the EJB, now that you have one compiled. In the next chapter we’ll show you how to assemble the pieces of the EJB into an Enterprise Archive and then deploy and run it.

More importantly, though, we haven’t covered how to write the code for stateful session beans or entity beans. Stateful session beans are one-to-a-client-session, rather than taking all comers, so there is a little more to code, and a few small changes required in the ejb-jar.xml config file. (What is the ejb-jar.xml config file? It is part of the configuration information used to deploy your EJB, the topic of the next chapter.) But there are some serious complications with entity beans that involve retrieving the bean’s data from a “backing store”—for example, a database—and writing it back. There are many good references on these topics, and we mention our favorites in the next section.

Resources

These are some of our favorite resources for learning about and dealing with EJBs. All of these give much more extensive examples that we have space for, and we encourage you to look at one or more of them.

  • J2EE and Beyond by Art Taylor (Prentice Hall PTR, ISBN 0-13-141745-2) gives a very good overview of all of the pieces of J2EE. At over 1,000 pages, it’s no small book, but it covers a lot more than just EJBs.

  • Enterprise JavaBeans Component Architecture: Designing and Coding Enterprise Applications by Gail Anderson and Paul Anderson, Sun Microsystems Press, ISBN 0-13-035571-2. At only 435 pages it is the most concise of the three, with the tightest focus and an emphasis on the code.

  • Applied Enterprise JavaBeans Technology by Kevin Boone, Sun Microsystems Press, ISBN 0-13-044915-6. At just over 700 pages, it is midway between the other two titles. Like the Taylor book, it covers some related technologies, but gives more depth to EJBs than Taylor, as that is its focus. It provides more examples than the Andersons, but its examples are not any deeper, just broader.



[1] Our JAR is named geronimo-spec-j2ee-1.0-M1.jar but yours will likely have a different name by the time the J2EE-certified version of Geronimo is available. It may likely just have the trailing -M1 dropped from the name; check in the geronimo-spec/jars directory. Another option is to use any of the J2EE JARs, for example, from the Sun reference implementation. That’s the advantage of standards. Any of them should work for this compilation step. The resulting compiled code should be deployable to any server. “Compile once, run anywhere,” right?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.179.193