http://www.developer.com/java/article.php/1435271/Introduction-to-EJBs-Part-2.htm
This is the second of four installments that make up Chapter 4: Introduction to EJBs from the book Sams Teach Yourself J2EE in 21 Days (ISBN:0-672-32384-2) written by Martin Bond, Dan Haywood, Debbie Law, Andy Longshaw, and Peter Roxburgh, published by Sams Publishing. So far, you have been presented with a "black box" view of an EJB;
it provides business functionality via an RMI remote interface, and it
cooperates with its container to perform its duties. To understand, use, and
ultimately write EJBs, you will need to know more in concrete terms about the
Java programming artefacts that make up an EJB. In other words, what's in
one? The primary purpose of an EJB is to deliver business or application logic. To
this end, the bean developer will define or derive the business operations
required of the bean and will formalize them in an RMI remote interface. This is
referred to as the bean's business or remote interface as opposed to the
home interface you will look at in a moment. Note You may see references to local EJB interfaces and wonder how these
relate to the current discussion. Don't worry about local interfaces for
the moment; they are covered on Day 6 when you examine entity EJBs. The actual methods defined on the remote interface will depend on the purpose
of the bean, but there are certain general rules concerning the interface: As with any RMI-based interface, each method must be declared as throwing
java.rmi.RemoteException in addition to any business-oriented
exceptions. This allows the RMI subsystem to signal network-related errors to
the client. RMI rules also apply to parameters and return values, so any types used
must either be primitive, Serializable, or Remote. The interface must declare that it extends the
javax.ejb.EJBObject interface. This provides a handful of basic methods
that you will encounter as you progress. Caution Failure to conform to the rules about extending
javax.ejb.EJBObject and throwing RemoteException will cause
the interface to be rejected by tools that manipulate EJBs. Additionally, if you
use parameter or return types that do not conform to the rules, your bean will
compile and even deploy, but will fail with runtime errors. The issue regarding object parameters and return values is worth considering
for a moment. When you pass a parameter into a local method call, a reference to
the original object is provided to be used within the method. Any changes to the
state of the object are seen by all users of that object because they are
sharing the same object. Also, there is no need to create a copy of the
objectonly a reference is passed. On the other hand, when using RMI remote methods, objects that are
serializable (implement the Serializable interface) are passed by
value, whereas objects that are remote (that is, EJBs) are passed by reference.
Pass by value means that a copy of the object is sent. This has several
implications. First, users of a serializable object passed across a remote
interface will no longer share the same object. Also, there may now be some
performance costs associated with invoking a method through a bean's remote
interface. Not only is there the cost of the network call, but also there is the
cost of making a copy of the object so that it can be sent across the network.
Most of the time, it will be serializable objects that are passed. You can see an example of an EJB remote interface in Listing 4.1in this
case, the one for the Agency EJB used in the case study. The interface lives in a package called agency, which will be common
to all the classes that comprise the EJB. The definition imports
java.rmi.* and javax.ejb.* for RemoteException and
EJBObject, respectively. The rest of the interface is much as you would
expect from any remote Java interfacein this case, passing
Strings and returning serializable Collections. Notice that all the methods must be declared as throwing
RemoteException. This means that the client will have to handle
potential exceptions that may arise from the underlying distribution mechanism.
However, your application will probably want to employ exceptions itself to
indicate application-level errors. These exceptions should be declared as part
of the remote interface, as shown by the use of NotFoundException and
DuplicateException in the Agency interface. After an interface is defined, there is the none-too-trivial task of
implementing the business logic behind it. The business logic for an EJB will
live in a class referred to as the bean. The bean consists of two parts: The business logic itself, including implementations of the methods
defined in the remote interface A set of methods that allow the container to manage the bean's
lifecycle. Note Although the bean itself must contain these elements, note that it is
possible, indeed common, for non-trivial beans to delegate some or all of their
business functionality to other, helper, classes. Drilling down into these areas reveals more about the structure of an
EJB. The first thing to note is that the bean itself does not implement the
remote interface previously defined. This may seem slightly bizarre at first
sight, because the equivalent RMI server would have to implement the
associated remote interface. However, there is a very good reason for this. As you will see later, it is possible to ask the container to apply services,
such as access control, on behalf of the EJB simply by setting attributes in the
EJB configuration information. To do this, the container must have some way of
intercepting the method call from the client. When it receives such a method
call, the container can then decide if any extra services need to be applied
before forwarding the method call on to the bean itself. Sticking with the
security example, the container would examine security information configured
for the EJB before deciding whether to forward the method call to the bean or to
reject it. The details about access control are covered on Day 15,
"Security," but you can see that it is necessary to interpose between
the client and the bean to "automagically" deliver such services. The interception is performed by a server-side object called the EJBObject
(not to be confused with the interface of the same name). The EJBObject acts
as a server-side proxy for the bean itself, and it is the EJBObject that actually
implements the EJB's remote interface. Figure 4.2 shows the relationship between the client, the bean, and the EJBObject. As shown in Figure 4.2, the client calls the business methods on the EJBObject implementation. The EJBObject applies the required extra services and then forwards the method calls on to the bean
itself. The EJBObject is separate from the RMI stub and skeleton that provide
the remote procedure call capability. Figure 4.2: The EJBObject acts as a server-side proxy for the bean itself. So, your bean must implement the business methods defined in the remote
interface. The container uses the method signatures defined in the interface,
together with the Java reflection API, to find the appropriate methods on the
bean, so you must ensure that you use the correct method signatures. Despite
this, the bean should not implement the remote interface itself (the reasons for
this are discussed later). However, if you are using a developer tool that
supports the creation of EJBs, it will generally generate empty methods for you
to populate. Listing 4.2 contains the outlines of the business methods in the
example AgencyBean. The detail of the method implementations have been removed for clarity,
because the main area of interest here is how the method signatures match up
with those on the remote interface. The contents of the methods are largely the
creation and dispatch of JDBC statements and handling the results from the
queries. Note that the bean does not implement the Agency interface. You can
also see that various of the methods, such as addSkill(), declare that
they throw an application-specific exceptionin this case,
DuplicateException. Note Note that your bean methods will only throw business exceptions or
standard Java exceptions. They should not throw
java.rmi.RemoteException, because such exceptions should only be
generated by the RMI subsystem. Remember that the intention of the EJB environment is that you will spend
most of your time writing business logic rather than network and database
"plumbing." Beyond writing the business logic, the only additional
thing the bean writer needs to do is to provide lifecycle "hooks" that
allow the container to manage the bean. Each of the different types of EJB discussed earlier has a slightly different
lifecycle, but the common parts are as follows: Bean creation and initialization Bean destruction and removal The saving and restoring of the bean's internal state (if
applicable) The details associated with each type of bean lifecycle will be discussed as
they are covered. For now, all you need to know is that An EJB will implement one or more lifecycle interfaces depending on its
type. The interfaces (SessionBean, EntityBean,
MessageDrivenBean, and SessionSynchronization) are defined in
the javax.ejb package. The lifecycle methods will generally begin with ejb so that they
can be easily distinguished from the business methods around them, for example,
ejbCreate(). Listing 4.3 contains the lifecycle methods in the example
AgencyBean. As you can see, the example AgencyBean implements the
SessionBean interface. This means that it must implement the
ejbCreate(), ejbRemove(), ejbActivate(),
ejbPassivate(), and setSessionContext() methods. The
ejbCreate() method takes on the role of constructor in that most of the
bean initialization will take place in there. The context passed in
setSessionContext() provides a way for the bean to communicate with the
container. This concludes the examination of the bean internals for the time being. You
will discover more as you learn about the specific types of EJB later. For an EJB to be used by a client, the client must create a new instance or
discover an existing one. Finding and gaining access to the services of a
traditional remote server is relatively simple. Such a server will tend to start
when the machine boots, reside in a well-know location, and carry on running
until the machine shuts down. However, EJBs are far more dynamic than that. It
is the ability to dynamically create and reuse beans that provides the
scalability inherent in the EJB model. To facilitate the creation and discovery of EJBs, each type of EJB provides a
home interface. The bean developer will provide an EJB home interface that acts
as a factory for that particular EJB. A home interface will extend the
javax.ejb.EJBHome interface and will contain the necessary methods
identified by the bean developer that allow a client to create, find, or remove
EJBs. There are two ways for a client to get hold of the EJB itself, depending on
the type of EJB (Session, Entity, or Message-driven) and the way it is intended
to be used. The EJB Home interface can contain one or more create()
methods to create a new instance of an EJB. So, for example, you will create a
new instance of a Session bean before using it. On the other hand, when you
interact with Entity EJBs, you will frequently find existing EJBs using one or
more findXXX() methods. The home interface may or may not allow you to
remove the bean, depending on bean type and usage. Listing 4.4 shows the home interface for the example Agency EJB. Because the Agency EJB is just a simple wrapper around some
JDBC-based functionality and does not maintain any business state, all that is
required is a simple creation methodcreate(). This maps onto the
ejbCreate() seen in Listing 4.3. The client will call create()
to create an instance of the Agency bean. The code underlying the home interface will work with the container to
create, populate, and destroy EJBs as requested by the client. The effects of
the method calls will vary depending on the type of EJB being manipulated. As a
result, a request to remove a Session EJB will just result in the EJB being
thrown away, while the same request on an Entity EJB may cause underlying data
to be removed. The types and effects of different home interface methods are
discussed in more detail on subsequent days. The final piece of the EJB jigsaw lies in the provision of configuration
information, or metadata, for the EJB. This provides a way of communicating the
EJB's requirements and structure to the container. If an EJB is to be
successfully deployed, the container will have to be provided with extra
information, including An identifier or name for the EJB that can be used to look it
up. The bean type (Session, Entity, or Message-driven). Which class is the EJB's remote interface. This interface will
typically just be named according to the EJB's functionality, for example,
Agency or BankTeller. Which class is the EJB's home interface. The name for an EJB's
home interface will typically be derived from its remote interface name. So, for
example, the Agency EJB has a home interface called
AgencyHome. However, because this is a convention rather than being
mandatory, the metadata explicitly indicates the name of the home
interface. Which class is the bean itself. Again, the name for the bean will
typically be derived from the associated remote interface name. So, for example,
the Agency bean is called AgencyBean. However, because this is
a convention rather than being mandatory, the metadata explicitly indicates the
name of the bean. Any name/value pairs to be provided as part of the bean's
environment. Information about any external resources required by the EJB, such as
database connections or other EJBs. All of this essential information is bundled into a deployment descriptor
that accompanies the EJB classes. As you might expect, given its recent rise as
the most ubiquitous way to define data, the deployment descriptor is defined as
an XML document. The deployment descriptor is discussed in more detail soon when
examining the packaging of an EJB. In addition to the essential information, the deployment descriptor can also
carry other metadata that you will encounter as you progress: Declarative attributes for security and transactions Structural information bean relationships and dependencies Persistence mapping (if applicable) You are now nearing the conclusion of this whistle-stop tour of the structure
of an EJB. After you have examined how an EJB is created and packaged, you will
be ready to deploy and use one. Andy Longshaw is a consultant, writer and educator specializing in J2EE, XML, Web-based technologies and components, particularly the design and architecture decisions required to use these technologies successfully. Andy has been explaining technology for most of the last decade as a trainer and in conference sessions. A wild rumor suggests that some people have managed to stay awake in these sessions. Despite being well educated and otherwise fairly normal, Andy still subjects himself, and his family, to "trial by unpredictability" by watching Manchester City FC far more often than is healthy. Andy and the other authors work for Content Master Ltd., a technical authoring company in the United Kingdom specializing in the production of training and educational materials. For more information on Content Master, please see their web site at www.contentmaster.com To access the full Table of Contents for the book
Introduction to EJBs: Part 2
July 30, 2002
What's in an EJB?
The Business Interface
Listing 4.1 Remote Interface for the Agency EJB
package agency;
import java.rmi.*;
import java.util.*;
import javax.ejb.*;
public interface Agency extends EJBObject
{
String getAgencyName() throws RemoteException;
Collection findAllApplicants()
throws RemoteException;
void createApplicant(String login, String name, String email)
throws RemoteException, DuplicateException, CreateException;
void deleteApplicant (String login)
throws RemoteException, NotFoundException;
Collection findAllCustomers() throws RemoteException;
void createCustomer(String login, String name, String email)
throws RemoteException, DuplicateException, CreateException;
void deleteCustomer (String login)
throws RemoteException, NotFoundException;
Collection getLocations()
throws RemoteException;
void addLocation(String name)
throws RemoteException, DuplicateException;
void removeLocation(String code)
throws RemoteException, NotFoundException;
Collection getSkills()
throws RemoteException;
void addSkill(String name)
throws RemoteException, DuplicateException;
void removeSkill(String name)
throws RemoteException, NotFoundException;
List select(String table)
throws RemoteException;
}
The Business Logic
Implementing the Business Interface

Listing 4.2 Business Method Implementation Signatures for the
AgencyBean
package agency;
import java.rmi.*;
import java.util.*;
import javax.ejb.*;
// Remaining imports removed for clarity
public class AgencyBean implements SessionBean
{
public String getAgencyName() {
// Code removed for clarity
}
public Collection findAllApplicants() {
// Code removed for clarity
}
public void createApplicant(String login, String name, String email)
throws DuplicateException, CreateException {
// Code removed for clarity
}
public void deleteApplicant (String login)
throws NotFoundException {
// Code removed for clarity
}
public Collection findAllCustomers() {
// Code removed for clarity
}
public void createCustomer(String login, String name, String email)
throws DuplicateException, CreateException {
// Code removed for clarity
}
public void deleteCustomer (String login) throws NotFoundException {
// Code removed for clarity
}
public Collection getLocations() {
// Code removed for clarity
}
public void addLocation(String name) throws DuplicateException {
// Code removed for clarity
}
public void removeLocation(String code) throws NotFoundException {
// Code removed for clarity
}
public Collection getSkills() {
// Code removed for clarity
}
public void addSkill (String name) throws DuplicateException {
// Code removed for clarity
}
public void removeSkill (String name) throws NotFoundException {
// Code removed for clarity
}
public List select(String table) {
// Code removed for clarity
}
// Remaining methods removed for clarity
}
Providing Lifecycle Hooks
Listing 4.3 Lifecycle Methods on the AgencyBean
package agency;
import java.rmi.*;
import java.util.*;
import javax.ejb.*;
// Remaining imports removed for clarity
public class AgencyBean implements SessionBean
{
private DataSource dataSource;
private String name = "";
private void error (String msg, Exception ex) {
String s = "AgencyBean: " + msg + "\n" + ex;
System.out.println(s);
throw new EJBException(s);
}
public void ejbCreate () throws CreateException {
try {
InitialContext ic = new InitialContext();
dataSource = (DataSource)ic.lookup("java:comp/env/jdbc/Agency");
name = (String)ic.lookup("java:comp/env/AgencyName");
}
catch (NamingException ex) {
error("Error connecting to java:comp/env/Agency:", ex);
}
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void ejbRemove() {
dataSource = null;
}
private SessionContext ctx;
public void setSessionContext(SessionContext ctx) {
this.ctx = ctx;
}
// Remaining methods removed for clarity
}
Factory Information
Listing 4.4 Home Interface for the Agency Bean
package agency;
import java.rmi.*;
import javax.ejb.*;
public interface AgencyHome extends EJBHome
{
Agency create () throws RemoteException, CreateException;
}
Bean Metadata
Monday's installment: What is an EJB and why use them?
Wednesday's installment: How do I create, deploy, and use an EJB?
About the Author
Source of this material

This is the first of four installments that make up Chapter 4: Introduction to EJBs from the book Sams Teach Yourself J2EE in 21 Days (ISBN:0-672-32384-2) written by Martin Bond, Dan Haywood, Debbie Law, Andy Longshaw, and Peter Roxburgh, published by Sams Publishing.