Oracle8i Enterprise JavaBeans and CORBA Developer's Guide Release 8.1.5 A64683-01 |
|
EJBs are based conceptually on the Java Remote Method Invocation (RMI) model. For example, remote object access and parameter passing for EJBs follow the RMI specification.
The EJB specification does not prescribe that the transport mechanism has to be pure RMI. The Oracle8i EJB server uses RMI over IIOP for its transport protocol, a practice that is becoming common among server vendors.
Figure shows the basic EJB architecture.
Before going into details about implementing EJBs, some basic concepts must be clarified. First of all, recall that a bean runs in a container. The container, which is part of the EJB server, provides a number of services to the bean. These include transaction services, synchronization services, and security.
To provide these services, the bean container must be able to intercept calls to bean methods. For example, a client application calls a bean method that has a transaction attribute that requires the bean to create a new transaction context. The bean container must be able to interpose code to start a new transaction before the method call, and to commit the transaction, if possible, when the method completes, and before any values are returned to the client.
For this reason and others, a client application does not call the remote bean methods directly. Instead, the client invokes the bean method through a two-step process, mediated by the ORB and by the container.
First, the client actually calls a local proxy stub for the remote method. The stub marshalls any parameter data, and then calls a remote skeleton on the server. The skeleton unmarshalls the data, and upcalls to the bean container. This step is required because of the remote nature of the call. Note that this step is completely transparent both to the client application developer as well as to the bean developer. It is a detail that you do not need to know about to write your application code, either on the client or the server. Nevertheless, it is useful to know what is going on, especially when it comes to understanding what happens during bean deployment.
In the second step, the bean container gets the skeleton upcall, then interposes whatever services are required by the context. These can include:
The container then delegates the method call to the bean. The bean method executes. When it returns, the thread of control returns to the bean container, which interposes whatever services are required by the context. For example, if the method is running in a transaction context, the bean container performs a commit operation, if possible. This depends on the transaction attributes in the bean descriptor.
Then the bean container calls the skeleton, which marshalls return data, and returns it to the client stub.
These steps are completely invisible to client-side and server-side application developers. One of the major advantages of the EJB development model is that it hides the complexity of transaction and identity management from developers.
When a client needs to create a bean instance, it does so through the home interface. The home interface specifies one or more create()
methods. A create()
method can takes parameters, that are passed in from the client when the bean is created.
For each create method in the home interface, there must be a corresponding method called ejbCreate()
specified in the remote interface, with the same signature. The only difference is that create()
is specified to return the bean type, while ejbCreate()
is a void method. When a client invokes create()
on the home, the container interposes whatever services are required at that point, and then calls the corresponding ejbCreate()
method in the bean itself.
A reference to the home object is what gets published in the database by the deployejb
tool. See "deployejb". This is the object that the client looks up to create instances of the bean.
The bean developer writes a remote interface for each EJB in the application. The remote interface specifies the business methods that the bean contains. Each method in the bean that the client is to have access to must be specified in the remote interface. Private methods in the bean are not specified in the remote interface.
The signature for each method in the remote interface must match the signature in the bean implementation.
(PL/SQL developers will recognize that the remote interface is much like a package spec, and the remote interface implementation is akin to the package body. However, the remote interface does not declare public variables. It declares only the methods that are implemented by the bean.)
The remote interface must be public, and it must subclass javax.ejb.EJBObject
. For example, you could write a remote interface for an employeeManagement
bean as follows:
public interface employeeManagement extends javax.ejb.EJBObject { public void hire(int empNumber, String startDate, double salary) throws java.rmi.RemoteException; public double getCommission(int empNumber) throws java.rmi.RemoteException; // empRecord is a class that is defined separately as part of the bean public empRecord getEmpInfo(int empNumber) throws java.rmi.RemoteException; ... }
All methods in the remote interface are declared as throwing RemoteException
. This is the usual mechanism for notifying the client of runtime errors in the bean. However, the bean container can throw other exceptions, such as SQLException
. Any exception can be thrown to the client, as long as it is serializable.
Runtime exceptions are transferred back to the client as a remote runtime exception. These contain the stack trace of the remote exception.
See "Remote Interface" for information about implementing the remote interface.
You get access to a bean so that you can invoke its methods in a two-step process. First, you look up the bean home interface, which is published in the Oracle8i database as part of the bean deployment process. You use the Java Naming and Directory Interface (JNDI) to look up the home interface. Then, using the home interface, you create instances of the bean in the server. For those who know CORBA, the bean home interface is acting very much like a CORBA factory object, able to produce new CORBA objects on demand.
Once you have the home interface, and then the bean reference returned by the home interface create()
method, you call the bean methods using the normal Java syntax: bean.method()
.
These steps are completely illustrated by example in A First EJB Application.
As a quick first example, suppose that myBeanHome
is a reference that you have obtained to the home interface of a bean called myBean
. myBean
must have at least one create()
method, that lets you instantiate the bean. So you create a new instance of the bean on the remote server by coding:
myBean home = (myBean) initialContext.lookup(URL); // get the home interface using JNDI myBean tester = home.create(); // create a new bean of type myBean
and then call myBean's methods using the usual syntax
tester.method1(p1, p2);