< Zurück | Inhalt | Weiter >

Chapter 22 Building an EJB


image

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


image



22.1 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.


22.2 EJBS: YOU DONT 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


493


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 pro- vided 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 func- tionality 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 unmar- shal 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 imple- ment 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.


22.2.1 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 ses- sion 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 es- tablish 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.



image

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


image


22.2.2 EJBObject

At the other end of the chain of EJB objects used to accomplish all this distribut- ed 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, be- cause 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).


image

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


image


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 ap- plication, 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.


22.2.3 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 ref- erence 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.


image

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


image


 


22.2.4 Summarizing the Pieces

22.2.6 Compiling Your Beans