Introduction to Enterprise JavaBeans

This chapter looks at one of the principal types of component in the Java 2 Platform, Enterprise Edition (J2EE) — Enterprise JavaBeans (EJBs). See how EJBs are applied and how they are deployed. (This is chapter 4 from Sams Publishers, author Martin Bond, et. al., Teach Yourself J2EE in 21 Days, second edition, ISBN: 0-672-32558-6).

bondJ2EE provides different types of components for different purposes. Today, you will start to look at one of the principal types of component in J2EE—Enterprise JavaBeans (EJBs).

The study of EJBs is continued on Day 5, “Session EJBs,” Day 6, “Entity EJBs,” Day 7, “Container-Managed Persistence and EJB Query Language,” Day 8, “Transactions and Persistence,” and Day 10, “Message-Driven Beans.” As you can see, there is a lot to learn about EJBs, so today serves as a first step on the road to all of this EJB knowledge. Today, you will:

  • Examine the different types of EJB available

  • See how EJBs are applied

  • Explore the structure of one of the EJBs that forms part of the case study to see how the different parts fit together

  • Deploy and use some of the EJBs from the case study

  • Write a simple client for an EJB

First, you need to understand what EJBs are and why you would use them.

What Is an EJB?

In a typical J2EE application, Enterprise JavaBeans (EJBs) contain the application’s business logic and live business data. Although it is possible to use standard Java objects to contain your business logic and business data, using EJBs addresses many of the issues of using simple Java objects, such as scalability, lifecycle management, and state management.

Beans, Clients, Containers, and Servers

An EJB is essentially a managed middleware component that is created, controlled, and destroyed by the J2EE container in which it lives. This control allows the container to manage the number of EJBs currently in existence and the resources they are using, such as memory and database connections.

Each container will maintain a pool of reusable EJB instances that are ready to be assigned to a client. When a client no longer needs an EJB, the EJB instance will be returned to the pool and all of its resources will be released. This pooling and recycling of EJB instances means that a few EJB instances, and the resources they use, can be shared between many clients. This maximizes the scalability of the EJB-based application. The EJB lifecycle is discussed further on Days 5 and 6.

The client that uses the EJB instance does not need to know about all of the work done on its behalf by the container. As far as the client is concerned, it is talking to a remote component that supports defined business methods. How those methods are implemented and any magic performed by the container, such as just-in-time instantiation of that specific component instance, are entirely transparent to the client part of the application.

To benefit from certain services provided by the container, such as automatic security, automatic transactions, lifecycle management, and so on, an EJB is packaged with a deployment descriptor (DD) that indicates the component’s requirements for services, such as transaction management and security authorization. The container will then use this information to perform authentication and transaction demarcation on behalf of the component—the component does not contain code to perform these tasks.

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=Types of EJB and Common Uses of EJBs}

Types of EJB

In most texts on this subject you will see pictures of a 3-tier system containing boxes labeled “EJB.” It is actually more important to identify what application functionality that should go into an EJB.

At the start of application development, regardless of the precise development process used there is generally some analysis that delivers a model, or set of classes and packages, that represent single or grouped business concepts.

Two types of functionality are generally discovered during analysis—data manipulation and business process flow. The application model will usually contain data-based classes such as Customer or Product. These classes will be manipulated by other classes or roles that represent business processes, such as Purchaser or CustomerManager. There are different types of EJB that can be applied to these different requirements:

  • Session EJB—A Session EJB is useful for mapping business process flow (or equivalent application concepts). There are two sub-types of Session EJB—stateless and stateful—that are discussed in more detail on Day 5. Session EJBs commonly represent “pure” functionality and are created as needed.

  • Entity EJB—An Entity EJB maps a combination of data (or equivalent application concept) and associated functionality. Entity EJBs are usually based on an underlying data store and will be created on the data within that store.

  • Message-Driven EJB—A Message-driven EJB is very similar in concept to a Session EJB, but is only activated when an asynchronous message arrives.

As an application designer, you should choose the most appropriate type of EJB based on the task to be accomplished.

Common Uses of EJBs

So, given all of this, where would you commonly encounter EJBs and in what roles? Well, the following are some examples:

  • In a Web-centric application, the EJBs will provide the business logic that sits behind the Web-oriented components, such as servlets and JSPs. If a Web-oriented application requires a high level of scalability or maintainability, use of EJBs can help to deliver this.

  • Thick client applications, such as Swing applications, will use EJBs in a similar way to Web-centric applications. To share business logic in a natural way between different types of client applications, EJBs can be used to house that business logic.

  • Business-to-business (B2B) e-commerce applications can also take advantage of EJBs. Because B2B e-commerce frequently revolves around the integration of business processes, EJBs provide an ideal place to house the business process logic. They can also provide a link between the Web technologies often used to deliver B2B and the business systems behind.

  • Enterprise Application Integration (EAI) applications can incorporate EJBs to house processing and mapping between different applications. Again, this is an encapsulation of the business logic that is needed when transferring data between applications (in this case, in-house applications).

These are all high-level views on how EJBs are applied. There are various other EJB-specific patterns and idioms that can be applied when implementing EJB-based solutions. These are discussed more on Day 18, “Patterns.”

Why Use EJBs?

Despite the recommendations of the J2EE Blueprints, the use of EJBs is not mandatory. You can build very successful applications using servlets, JSPs or standalone Java applications.

As a general rule of thumb, if an application is small in scope and is not required to be highly scalable, you can use J2EE components, such as servlets, together with direct JDBC connectivity to build it. However, as the application complexity grows or the number of concurrent users increases, the use of EJBs makes it much easier to partition and scale the application. In this case, using EJBs gives you some significant advantages.

The main advantage of using EJBs in your application is the framework provided by the EJB container. The container provides various services for the EJB to relieve the developer from having to implement such services, namely

  • Distribution via proxies—The container generates a client-side stub and server-side skeleton for the EJB. The stub and skeleton use RMI over IIOP to communicate.

  • Lifecycle management—Bean initialization, state management, and destruction is driven by the container, all the developer has to do is implement the appropriate methods.

  • Naming and registration—The EJB container and server provide the EJB with access to naming services. These services are used by local and remote clients to look up the EJB and by the EJB itself to look up resources it may need.

  • Transaction management—Declarative transactions provide a means for the developer to easily delegate the creation and control of transactions to the container.

  • Security and access control—Again, declarative security provides a means for the developer to easily delegate the enforcement of security to the container.

  • Persistence (if required)—Using the Entity EJB’s Container-Managed Persistence mechanism (CMP), state can be saved and restored without having to write a single line of code.

All of these container services are covered in more detail as the book progresses.

Now that you know why you would want to use an EJB and how to apply it, you can examine the inner workings of an EJB to understand how all the parts fit together.

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=What’s in an EJB?}

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 artifacts that make up an EJB. In other words, what’s in one?

There are four components to an EJB:

  • The remote interface—Defining the signatures of the business methods for the EJB

  • The home interface—Defining the signature of the methods associated with the bean lifecycle (creation, use and destruction)

  • The bean itself—A concrete Java class implementing the business and lifecycle method functionality

  • The deployment descriptor—Meta data about the EJB, such as component classes, EJB type, transaction demarcation, resource and EJB references, environment entries, and security requirements

The names of the two Java interfaces and the Bean class usually follow a simple convention. For a given remote interface XXX the home interface is called XXXHome and the bean implementation is XXXBean. (Some users prefer to use XXXEJB for the implementation class.) Although this convention is not enforced, it is recommended that you use it when naming your EJB components.

Similarly, as discussed later in the section “The Bean Implementation,” there are corresponding rules about the names of methods defined in the interfaces and the names of methods in the bean implementation. Unlike the class names, these rules are part of the EJB specification and must be rigorously applied, otherwise your EJBs will not deploy correctly.

The Business Interface

As stated already, 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 remote (or business) interface as opposed to the home interface you will look at in a moment.

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 exceptions. This allows the RMI subsystem to signal network-related errors to the client.

  • RMI rules apply to parameters and return values, so any types used must either be primitives (int, boolean, float, and the like), or implement the Serializable or Remote interfaces. Most Java classes, such as String and the primitive wrapper classes, implement Serializable.

  • The interface must declare that it extends the javax.ejb.EJBObject interface.


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 an object as a parameter into a local method call, a reference to the original object is 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 object—only a reference is passed. This mechanism is known as pass by reference.

On the other hand, when using RMI remote methods, only objects that are serializable (that is, implement the Serializable interface) are passed. A copy of the object is made and this copy is passed over the remote interface to the method. 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. This mechanism is known as pass by value.

You can see an example of an EJB remote interface in Listing 4.1—in this case, the one for the Agency EJB used in the case study introduced on Day 2, “The J2EE Platform and Roles.”

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 getApplicants()
throws RemoteException;
void createApplicant(String login, String name, String email)
throws RemoteException, DuplicateException, CreateException; void deleteApplicant (String login)
throws RemoteException, NotFoundException;

Collection getCustomers() 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 remote 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 interface—in this case, passing Strings and returning serializable Collection objects.

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

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=The Home Interface}

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 to 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 or Entity) 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 can create a new instance of a Session bean before using it. On the other hand, when you interact with Entity EJBs, you will frequently use findXXX()methods to use existing beans. Message-Driven beans do not have a home interface as their lifecycle is more rigidly controlled compared to Session and Entity beans (the Message-driven bean life-cycle is covered in detail on Day 10.

Listing 4.2 shows the home interface for the example Agency EJB.

Listing 4.2 Home Interface for the Agency Bean

package agency;

import java.rmi.*;
import javax.ejb.*;

public interface AgencyHome extends EJBHome
{
  Agency create () throws RemoteException, CreateException;

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 Days 5 and 6.

The Bean Implementation

After the interfaces are defined, there is the none-too-trivial task of implementing the business logic behind them. 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, 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.

Implementing the Business Interface

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; however, there is a very good reason for this.

In order for the container to apply services, such as access control, on behalf of the EJB 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.

The interception is performed by a server-side object called the EJB Object (not to be confused with the interface of the same name). The EJB Object acts as a server-side proxy for the bean itself, and it is the EJB Object that actually implements the EJB’s remote interface. Figure 4.1 shows the relationship between the client, the bean, and the EJB Object.

bond

Figure 4.1
The EJB Object acts as a server-side proxy for the bean itself.

As shown in Figure 4.1, the client calls the business methods on the EJB Object implementation. The EJB Object applies the required extra services and then forwards the method calls to the bean itself.

The J2EE server generates the EJB Object class when you deploy the EJB. The deployment process uses the information you provide in the home and remote interfaces and the DD to generate the required EJB Object class.

Every business method in the remote interface must have a corresponding business method in the bean. The method name, parameters, and return type must be identical and the bean method must throw the same exceptions as the interface method apart from the RemoteException required by all remote methods. All business methods must have public visibility.

For example, the remote interface method

public Collection findAllApplicants() throws RemoteException; must have the corresponding method in the bean:

public Collection findAllApplicants();

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.3 shows the outlines of the business methods in the example AgencyBean with some of the code removed for clarity.

Listing 4.3 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() { … }
  public Collection findAllApplicants() { … }

  public void createApplicant(String login, String name, String email)
   throws DuplicateException, CreateException { … }

  public void deleteApplicant (String login)
   throws NotFoundException { … }

  public Collection findAllCustomers() { … }

  public void createCustomer(String login, String name, String email)
   throws DuplicateException, CreateException { … }

  public void deleteCustomer (String login) throws NotFoundException { … }

  public Collection getLocations() { … }

  public void addLocation(String name) throws DuplicateException { … }

  public void removeLocation(String code) throws NotFoundException { … }

  public Collection getSkills() { … }

  public void addSkill (String name) throws DuplicateException { … }

  public void removeSkill (String name) throws NotFoundException { … }

  public List select(String table) { … }
}

An EJB implementation must implement the appropriate javax.ejb class, as described in the section “Implementing the Home Interface.” The AgencyBean example is a Session EJB and therefore must extend javax.ejb.SessionBean.


Note - Note that your bean methods will only throw business exceptions or standard Java exceptions. They should not throw java.rmi.RemoteException, because this exception should only be generated by the RMI subsystem.


This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=Implementing the Home Interface}

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 EJBs discussed earlier (Session, Entity, and MDB) 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 are defined in the javax.ejb package.

  • Standard lifecycle methods must be provided.

  • 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.4 contains the lifecycle methods in the example AgencyBean with most of the implementation code removed for clarity

Listing 4.4 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 = “”;

  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() { … }

  private SessionContext ctx;
 
  public void setSessionContext(SessionContext ctx) {
    this.ctx = ctx;
  }
}

As you can see, the example AgencyBean implements the SessionBean interface. This means that it must implement the ejbRemove(), ejbActivate(), ejbPassivate(), and setSessionContext() methods. The context passed in setSessionContext() provides a way for the bean to communicate with the container. It is usual to save the session context object in an instance variable for use by the other bean methods.

In an Entity bean the ejbCreate() method takes on the role of constructor in that most of the bean initialization will take place in this method, and corresponds to the create() method defined in the home interface. The ejbCreate() method is not defined in the SessionBean interface, because its signature will vary from one EJB to another (as described tomorrow when Session EJBs are discussed in detail).

The Deployment Descriptor

The final piece of the EJB jigsaw lies in the provision of configuration information, or meta data, 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 for JNDI lookup to locate the bean.

  • The bean type Session, Entity, or Message-Driven.

  • The EJB’s remote interface class. This interface will typically just be named according to the EJB’s functionality, for example, Agency or BankTeller.

  • The EJB’s home interface class. The name for an EJB’s home interface will typically be derived from its remote interface name.

  • The bean class itself. Again, the name for the bean will typically be derived from the associated remote interface name.

  • Any name/value pairs to be provided as part of the bean’s environment. Effectively, these are variables that can be given values by the assembler or deployer as well as the developer.

  • 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. The deployment descriptor is defined as an XML document, and is discussed in more detail later when examining the packaging of an EJB.

In addition to the essential information, the deployment descriptor can also carry other metadata such as:

  • Declarative attributes for security and transactions

  • Structural information about bean relationships and dependencies

  • Persistence mapping (if applicable)

You will see examples of all of these as you progress through this book.

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=Verifying an EJB}

One of the problems most developers come across when writing EJBs is making sure the bean implementation provides the requisite functionality in the remote and home interfaces. Because your bean does not implement the remote interface (or the home interface), you must manually check that you have defined all the business methods in the bean implementation and that every create() method in the home interface has a corresponding ejbCreate() method in the implementation.

There are two ways of solving this problem:

  • Generate a template bean implementation class from the home and remote interfaces.

  • Use a tool that checks the bean implementation against the home and remote interfaces.

The drawback to the first approach is that changes to the home or remote interfaces necessitate regenerating the template class and copying existing functionality into the newly generated template. The process of manually copying existing code into the new template could lead to errors and is best avoided.

Use of a separate verification utility is more common, as this can be used any time changes are made to the interfaces or the implementation. The J2EE RI comes with the verifier tool, which validates the contents of an enterprise application and generates a comprehensive list of any errors encountered. The verifier is discussed in more detail in the section “Verifying the Case Study Application.”

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.

How Do I Create an EJB?

First you have to design and write your EJB classes. After that small task, all that remains is to wrap the class files up as a deployable unit with the deployment descriptor. In reality, not all of the deployment information is defined in the EJB specification. A certain amount of EJB information will, of necessity, be J2EE implementation specific. Consequently there will typically be at least two deployment descriptors in an EJB. Before looking at the deployment descriptors, there are certain caveats you should bear in mind while creating your bean.

Caveats on EJBs

Due to the managed nature of the bean lifecycle, the EJB container imposes certain restrictions on the bean including

  • EJBs cannot perform file I/O. If you need to log messages or access files, you must find an alternative mechanism.

  • EJBs are not allowed to start threads. The container controls all threading and ensures that the EJB is always multi-thread safe by only allowing a single thread of execution for each EJB.

  • EJBs cannot call native methods.

  • EJBs cannot use static member variables.

  • There is no GUI available to an EJB, so it must not attempt to use AWT or JFC components.

  • An EJB cannot act as a network server, listening for inbound connections.

  • An EJB should not attempt to create class loaders or change factories for artifacts, such as sockets.

  • An EJB should not return this from a method. Although not strictly a restriction (the container will not prevent you from doing it), it is identified as being a very bad practice as it would potentially give a client a direct remote reference to the bean rather than the EJB Object. Instead, the bean should query its EJB context for a reference to its associated EJB Object and return that to the caller in place of the this variable.

For a full list of restrictions, see the EJB specification available online at http://java.sun.com/products/ejb/docs.html.

The EJB Deployment Descriptor

The EJB specification defines a standard format for the XML deployment descriptor document that stores EJB meta data. The exact format of a deployment descriptor is usually hidden behind tools (such as the J2EE RI deploytool) that manipulates it on your behalf. However, it is worth examining some of the contents of a deployment descriptor to see how the EJB fits together and how extra information and meta data is provided.

Listing 4.5 shows the deployment descriptor for the example Agency EJB.

Listing 4.5 Agency Bean EJB Deployment Descriptor

<?xml version=”1.0″ encoding=”UTF-8″?>
<ejb-jar version=”2.1″ xmlns=”
http://java.sun.com/xml/ns/j2ee
 xmlns:xsi=”
http://www.w3.org/2001/XMLSchema-instance
 xsi:schemaLocation=”
http://java.sun.com/xml/ns/j2ee
 http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd“>
 <display-name>Simple</display-name>
 <enterprise-beans>
  <session>
   <ejb-name>AgencyBean</ejb-name>
   <home>agency.AgencyHome</home>
   <remote>agency.Agency</remote>
   <ejb-class>agency.AgencyBean</ejb-class>
   <session-type>Stateless</session-type>
   <transaction-type>Bean</transaction-type>
   <env-entry>
    <env-entry-name>AgencyName</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>J2EE in 21 Days Job Agency</env-entry-value>
   </env-entry>
   <security-identity>
    <use-caller-identity/>
   </security-identity>
   <resource-ref>
    <res-ref-name>jdbc/Agency</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
   </resource-ref>
  </session>
 </enterprise-beans>
</ejb-jar>

The essential parts of the deployment descriptor in Listing 4.5 are

  • The <session> tag delimits the definition of the Agency EJB and indicates that it is a Session EJB.

  • The <ejb-name> tag defines the name of the EJB, in this case Agency.

  • The home and remote interface types (as defined by their fully-qualified class filenames) are specified by the <home> and <remote> tags, respectively. The type of the bean itself is defined by the <ejb-class> tag.

In addition, two other parts are of particular note at this point in time:

  • An environment entry is defined using the <env-entry> tag. This indicates that a String property called AgencyName should be made available to the bean. The value of the property is J2EE in 21 Days Job Agency. The environment defined in the deployment descriptor is made available through JNDI under java:comp/env. In this case, the agency name can be retrieved by looking up the name java:comp/env/AgencyName. This lookup can be seen in the ejbCreate() method of Listing 4.4.

  • An external resource is defined using the <resource-ref> tag. This defines that a DataSource should be made available to this EJB under the name jdbc/Agency. As with the environment entry for the agency name, this resource is made available through JNDI under java:comp/env, so the EJB can retrieve the DataSource by looking up the name java:comp/env/jdbc/Agency. Again, this lookup can be seen in the ejbCreate() method of Listing 4.4.

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=The EJB-JAR File}

All of the EJB classes and the deployment descriptor should be bundled up in a JAR file. The deployment descriptor is stored in a META-INF directory (the same location as the JAR manifest file) and must be named ejb-jar.xml. If there are multiple EJBs packaged in the same JAR file, the deployment descriptor will have multiple EJB definitions in it. The JAR file is then termed an EJB-JAR file to denote its payload. The JAR file itself can be called anything (but obviously a name appropriate to the application makes most sense) and conventionally has a .jar file extension.

The EJB-JAR file can also contain any extra resources required by the EJB, such as platform-specific configuration information that does not fit in the standard deployment descriptor.

Typical contents of a platform specific deployment descriptor are

  • The JNDI name the EJB must be deployed under Mappings between resources referenced in the J2EE components such as EJBs and the actual resources within the J2EE server

An EJB-JAR file can store more than one platform-specific deployment descriptor file, enabling it to be used with different J2EE implementations. Although the EJB-JAR file is now complete, it must form part of an application to serve a useful purpose. J2EE defines that enterprise applications can be built from components (Web, EJB, and Client Application components). Therefore, a second JAR file is used to bundle these J2EE components into a complete J2EE Application, this is called the Enterprise Archive file.

The Enterprise Archive File

The Enterprise Archive (EAR) file contains a number of J2EE components comprising an application and yet another deployment descriptor. This descriptor includes a description of the application, which components it uses, how those components relate to each other, and which specific resources they use. This is the information provided by the Application Assembler and Deployer.

The application deployment descriptor is also an XML document, called application.xml, and it is stored in the META-INF directory of the Enterprise Archive (which although a JAR file the Enterprise Archive typically has a filename extension of .ear not .jar). Listing 4.6 shows the application.xml descriptor for the Agency application.

Listing 4.6 Agency Bean EJB Deployment Descriptor

<?xml version=”1.0″ encoding=”UTF-8″?>
<application version=”1.4″ xmlns=”
http://java.sun.com/xml/ns/j2ee
 xmlns:xsi=”
http://www.w3.org/2001/XMLSchema-instance
 xsi:schemaLocation=”
http://java.sun.com/xml/ns/j2ee
 
http://java.sun.com/xml/ns/j2ee/application_1_4.xsd“>
 <description>Application description</description>
 <display-name>agency</display-name>
 <module>
  <ejb>agency-session-ejb.jar</ejb>
 </module>
 <module>
  <web>
   <web-uri>webagency.war</web-uri>
   <context-root>/webagency</context-root>
  </web>
 </module>
</application>

The application.xml file just lists the modules that form the enterprise application, in this case the single Agency EJB contained in agency-session-ejb.jar.

An EAR file may also contain one or more platform-specific deployment descriptors for the application enabling it to be used with different J2EE implementations.

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=How Do I Deploy an EJB?}

After an EJB is packaged, it can be deployed in an appropriate J2EE server. This is done using tools supplied by the J2EE Server vendor. Often these will be Java GUI applications, but command-line tools and Web interfaces are also used by some vendors. The typical process is to define the target J2EE server, identify the EAR file to be deployed, supply user credentials (typically administrative username and password) and away you go.

Remember that J2EE defines a separate role for the application Deployer. It may be that, for particular installations the databases or other resource names need to be changed to match the local environment. When configuring the application, the Deployer may need to alter the EJB or enterprise deployment descriptors but will not need to change the Java source code.

When an EJB is deployed into a particular EJB container, the EJB must be plugged into that container. To do this, an EJB Object must be generated based on the EJB’s remote interface. This EJB Object will be specific to that EJB container and will contain code that allows the EJB Object to interface with that container to access security and transaction information. The container will examine the deployment descriptors supplied with the EJB to determine what type of security and transaction code is required in the EJB Object.

The container will also generate a class that implements the EJB home interface so that calls to the create, find, and destroy EJB instances are delegated to container-defined methods.

Finally, the container will register the JNDI name for the home interface of the EJB. This allows other application components to create and find this application’s EJBs.

After the EJB has been deployed, any subsequent changes to its functionality will mean that the EJB must be redeployed. If the enterprise application or EJB is no longer needed, it should be undeployed from the container.

How Do I Use an EJB?

Given that EJBs are middle-tier business components, they are of little use without a client to drive them. As mentioned earlier, those clients can be Web components, standalone Java clients, or other EJBs.

Regardless of the type of client, using an EJB requires the same set of steps—namely, discovery, retrieval, use, and disposal. Listing 4.7 shows a simple client for use with the Agency EJB illustrating these steps. The following three sections cover these steps in more detail.

Listing 4.7 Simple Agency Client SimpleClient.java

package client;

import agency.*;
import javax.ejb.*;
import javax.naming.*;
import java.rmi.*;
import javax.rmi.*;
import java.util.*;

public class SimpleClient
{
  private static String agencyJNDI = “java:comp/env/ejb/Agency”;

  public static void main(String[] args) {
    if (args.length == 1)
      agencyJNDI = args[0];
    else if (args.length > 1) {
      System.err.println(“Usage: SimpleClient [ AgencyJNDI ]“);
      System.exit(1);
    }
   
    try {
      InitialContext ic = new InitialContext();
      Object lookup = ic.lookup(agencyJNDI);
     
      AgencyHome home = (AgencyHome)
        PortableRemoteObject.narrow(lookup, AgencyHome.class);    
      Agency agency = home.create();
      System.out.println(“Welcome to: “+agency.getAgencyName());
      System.out.println(“Customer list: “+agency.getAgencyName());
      Collection customers = agency.findAllCustomers();
      Iterator it = customers.iterator();
      while (it.hasNext())
      {
        String name = (String)it.next();
        System.out.println(name);
      }
      agency.close();
    }
    catch (NamingException ex) {
       System.err.println(ex);
    }
    catch (ClassCastException ex) {
       System.err.println(ex);
    }
    catch (CreateException ex) {
       System.err.println(ex);
    }
    catch (RemoteException ex) {
       System.err.println(ex);
    }
    catch (RemoveException ex) {
       System.err.println(ex);
    }
  }
}

Discovery

To create or find an EJB, the client must call the appropriate method on the EJB’s home interface. Consequently, the first step for the client is to obtain a remote reference to the home interface. The client obtains the reference by accessing the J2EE server’s name service using JNDI.

For this simple process to work, the following three actions must have taken place:

  • The developer has defined the EJB reference used in the Java code

  • The Deployer has mapped this reference onto the actual JNDI name of the EJB

  • The EJB container has registered the home interface using the JNDI name specified as part of the platform specific deployment descriptor

As discussed on Day 3, each J2EE component has its own Java Component Environment space and the JNDI name used in the client code will be prefixed with java:comp/env. The object retrieved is a reference to the RMI-IIOP remote stub that must be downcast to the home interface. The following code shows the initial lookup required for the Agency EJB:

try
 {
  InitialContext ic = new InitialContext();
  Object lookup = ic.lookup(“java:comp/env/ejb/Agency”);
  AgencyHome home =
     (AgencyHome)PortableRemoteObject.narrow(lookup, AgencyHome.class);
  …
 }
 catch (NamingException ex) { /* Handle it */ }
 catch (ClassCastException ex) { /* Handle it */ }

Now that you have a reference to the home interface, you can create the EJB.

Retrieval and Use

Once you have a reference to the EJB home interface, you can call the create() method you saw defined on the AgencyHome interface. The create() method returns a remote reference to the newly-created EJB. If there are any problems with the EJB creation or the remote connection, a CreateException or RemoteException will be thrown. CreateException is defined in the javax.ejb package, and RemoteException is defined in the java.rmi package, so remember to import these packages in your client class.

Now that you have a reference to an EJB, you can call its business methods as follows:

 try
 {
  …
  Agency agency = home.create();
  System.out.println(“Welcome to: ” + agency.getAgencyName());
  …
 }
 catch (RemoteException ex) { /* Handle it */ }
 catch (CreateException ex) { /* Handle it */ }

The previous code sample shows the getAgencyName() method being called on the returned Agency reference. Again, whenever you call a remote method that is defined in an EJB remote interface, you must be prepared to handle a RemoteException.


Note - You will see later that some Entity beans are found rather than created. In this case, all steps are the same except that the create() method is replaced by the appropriate finder method and find-related exceptions must be handled. You still end up with a remote reference to an EJB. All of this is covered when Entity beans are discussed on Day 6.


This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=Disposing of the EJB}

You have now created and used an EJB. What happens now? Well, if you no longer need the EJB, you should get rid of it by calling its remove method, and set its reference to null as follows:

 // No longer need the agency EJB instance
 agency.remove();
 agency = null;

The remove() method can throw RemoveException. After calling remove() you should obviously not call any business methods on the bean as it has been removed from use. Using an EJB after remove() has been called will throw a RemoteException.


Note - Normally you would only call the remove() method for Session beans. Entity beans (see Day 5) represent data in a persistent data store, and calling remove() for an Entity bean would typically remove the data from the data store.


If you do not remove a Session EJB after a default period of inactivity (typically 30 minutes), then the EJB container will remove the bean on your behalf. This is an example of the added value provided by the EJB lifecycle. A lazy or novice developer can forget to remove an EJB and the container will still tidy up and release resources: a bit like your mother tidying your bedroom when you were a young child.

Running the Client

To compile and run the client, you will need the following:

  • The J2EE classes.

  • Access to the EJB’s home and remote interface classes.

  • RMI stubs for the home and remote interfaces.

  • If the client does not have the JNDI name of the EJB compiled in, you may want to provide this on the command line or through a system property.


Note - If your client is a J2EE Web client (such as a servlet or JSP as discussed on Day 12, “Servlets” and Day 13, “JavaServer Pages”), then the client will implicitly have access to the J2EE classes, EJB interfaces, RMI stubs and JNDI name server.


When you deploy the EJB, you can usually ask the container for a client JAR file. This client JAR file will contain all of the classes and interfaces needed to compile the client (as defined in the previous bulleted list). You should add this client JAR file to your CLASSPATH when compiling your client.

Client Applications

Application client programs are simple Java programs with a main() method that run in their own JVM but make use of services provided by the J2EE server. Application clients are usually invoked by a program supplied by the J2EE server vendor. The J2EE RI, for instance, provides a program called appclient for running application clients.

The various J2EE server vendors may handle client applications differently, but the J2EE specification allows for application clients to be packaged into JAR files, together with a deployment descriptor, and deployed to the J2EE server. The J2EE RI uses this approach, and Listing 4.8 shows the application client deployment descriptor file (application-client.xml) for the simple Agency application client shown previously in Listing 4.7.

Listing 4.8 Application Client Deployment Descriptor application-client.xml

<?xml version=”1.0″ encoding=”UTF-8″?>
<application-client version=”1.4″ xmlns=”
http://java.sun.com/xml/ns/j2ee
 xmlns:xsi=”
http://www.w3.org/2001/XMLSchema-instance
 xsi:schemaLocation=”
http://java.sun.com/xml/ns/j2ee
 
http://java.sun.com/xml/ns/j2ee/application-client_1_4.xsd“>
 <display-name>SimpleClient</display-name>
 <ejb-ref>
  <ejb-ref-name>ejb/Agency</ejb-ref-name>
  <ejb-ref-type>Session</ejb-ref-type>
  <home>agency.AgencyHome</home>
  <remote>agency.Agency</remote>
 </ejb-ref>
</application-client>

An application client deployment descriptor is used to define J2EE server resources required by the client. In this case, a single EJB reference is needed to define the name of the EJB as used in the code (ejb/Agency) and the type and classes for the EJB.


Note - As with all applications bundled into a JAR file, the class containing the main() method entry point is defined by a Main-class entry in the JAR Manifest file.


This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=Using the J2EE Reference Implementation}

In this section, you will look at how to deploy an EJB in the J2EE Reference Implementation (RI) and how to run the simple application client.

Configuring J2EE RI

On Day 2 you were asked to install and configure the J2EE RI available, free of charge, from Sun Microsystems (at http://java.sun.com/j2ee) and build a sample database for the exercises in this book. If you have not already done so go back to Day 2 and follow the instructions for installing the J2EE RI and building the Agency case study database.


Note - As discussed on Day 2, before running any of the tools described in this section, you will need to set the J2EE_HOME environment variable to the location on your hard drive where you installed the J2EE reference implementation. You should also add the bin directory below J2EE_HOME to your executable search path (%PATH% under Windows or $PATH under Solaris/Linux) so that you can run J2EE tools and batch files from the command line. You should place the J2EE bin directory at the front of your PATH setting to avoid conflicts with system tools with the same names as the J2EE tools. You should also copy the code in the CaseStudy directory on the accompanying Web site onto your local hard disk, because commands you will run today require write access to the working directory.


There are two approaches to building and deploying a J2EE component or application using J2EE RI:

  • You can use the deploytool provided with the J2EE SDK.

  • You can use the asant utility supplied with the J2EE SDK (this is a modified version of the popular Apache Ant utility from http://jakarta.apache.org/ant). The J2EE tutorial examples for J2EE SDK 1.4 are built and deployed using asant build files and asant build files are supplied for all the examples used throughout this book.

As a newcomer to J2EE, you will find it informative to use the GUI interface of deploytool for building and configuring the EAR and WAR files used to hold your EJBs, applications, and web components. As you gain more experience, you might find the speed of the asant command-line interface to be preferable. You will also find asant build files useful for scripting automated testing procedures.

The disadvantage of using asant is that you will have to write the build files yourself; not to mention hand crafting all the deployment descriptors. Many developers use deploytool once to generate the basic deployment descriptors and then save these descriptors to disk for use with asant build files. That is how most of the examples for this book were developed.

This section will show how to build and deploy J2EE components using deploytool before looking at the asant build files used for the Agency case study example. The directory structure for the book’s example code was discussed on Day 2, but as a quick reminder, these are the subdirectories under the exercise directory for Day 4:

  • build—A temporary directory used by the asant build files (created when needed)

  • classes—The compiled class files

  • dd—The deployment descriptor files used by the asant build files

  • j2ee-ri—Repository for files manipulated by deploytool

  • src—The Java source files

  • JSP—The HTML and JavaServer Pages source files

Remember to make sure you are running the J2EE RI server and PointBase database servers and have created the Agency database before starting this exercise.

Opening the Case Study EAR File

Now you are ready to run the deploytool found in the bin directory under the J2EE_HOME directory. Start a command line window in the Day04/exercise directory and enter the command:

deploytool

You will be presented with a graphic interface for building J2EE components. If you have not set your PATH to include the bin directory under J2EE home you will have to provide the full pathname for deploytool. Windows users can use the Start, Programs, Sun Microsystems, J2EE 1.4 SDK, Deploytool menu or run

%J2EE_HOME%bindeploytool

Solaris and Linux users should enter

$J2EE_HOME/bin/deploytool

In deploytool, use the File, Open menu to open the supplied agency enterprise archive (EAR) file in Day04/exercise/j2ee-ri/agency.ear. The agency application will now be displayed in the list of applications, as shown in Figure 4.2.

bond

Figure 4.2
The Agency application loaded by deploytool.

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=Examining the Case Study Application}

You can use deploytool to examine and alter deployment descriptor information for the application and, if necessary, for individual components, such as EJBs.

After you open an EAR file, the enterprise application will be selected and deployment information appropriate to the application is available in the tabbed dialog pages in the right pane. In Figure 4.3, clicking on the key icons to the left of each item has exposed the nested structure of the information.

bond

Figure 4.3
The Agency application loaded by deploytool.

Figure 4.3 shows that the application has three components:

  • An Agency JAR file containing a single Agency EJB

  • A WebApp WAR file containing a simple Web Application (Web Applications are introduced on Day 12)

  • A SimpleClient client application

The right General pane in Figure 4.3 shows the files comprising the Agency application as follows:

  • META-INF/application.xml—The application DD as shown in Listing 4.6

  • META-INF/sun-j2ee-ri.project—A proprietary J2EE RI projects file (you can ignore this)

  • META-INF/sun-j2ee-ri.xml—A J2EE RI platform-specific DD (discussed in the section “Defining the Platform-Specific Settings”)

  • agency-session-ejb.jar—The JAR file for the Agency EJBs

  • app-client-ic.jar—The JAR file for the application client

  • webagency.war—The WAR file for the Web Application

The remaining tabbed dialog-pages in the application pane will be discussed in later days in this book.

With the agency application selected in the left pane you can use the Tools, Descriptor Viewer, Descriptor Viewer menu option to examine the application.xml deployment descriptor shown in Listing 4.6. You can also use the Tools, Descriptor Viewer, Application Server Descriptor… menu to view the Sun Specific deployment descriptor.

Figure 4.4 shows the EJB JAR specific information with the contents of the JAR file expanded in the right pane.

bomd

Figure 4.4
Details of the Agency JAR file.

The right General pane in Figure 4.4 shows the files that compose the Agency EJB JAR:

  • META-INF/ejb-jar.xml—The EJB DD

  • META-INF/sun-ejb-jar.xml—The Sun Specific EJB DD

  • META-INF/sun-j2ee-ri.project—A proprietary J2EE RI projects file (you can ignore this)

  • agency/Agency.class—The Agency Session bean remote interface (see Listing 4.1)

  • agency/AgencyBean.class—The Agency Session bean itself (see Listing 4.3)

  • agency/AgencyHome.class—The Agency Session bean home interface (see Listing 4.2)

  • agency/DuplicateException.class—Supporting class for the Agency Session

  • agency/NotFoundException.class—Supporting class for the Agency Session

With the Agency EJB JAR file selected in the left pane you can use the Tools, Descriptor Viewer, Descriptor Viewer menu option to examine the ejb-jar.xml deployment descriptor shown in Listing 4.5. You can also use the Tools, Descriptor Viewer, Application Server Descriptor… menu to view the Sun Specific EJB deployment descriptor.

Drilling down further into the EJB, Figure 4.5 shows the Agency Session bean itself.

bond

Figure 4.5
Details of the Agency Session bean.

In Figure 4.5 the General tab shows the bean type and component classes for the Agency Session bean. This information is provided when the bean is created and cannot be changed thereafter. Creating a Session bean is discussed on Day 5. However, most of the configuration information for a bean can be changed through the remaining tabbed dialog pages shown in Figure 4.5.

Table 4.1 shows the basic categories of information that can be provided for an EJB.

Table 4.1 EJB DD Categories.

Category

Description

Environment Entries

Name value pairs that can be used by the developer but defined by the Deployer/Assembler (see Figure 4.6).

EJB References

References to other EJBs used by this EJB, typically Entity beans referenced by a Session bean, as shown on Day 6.

Resource Environment References

Resource references added to the EJB environment, typically JMS resources, as discussed on Day 10.

Resource References

Resources used by the EJB, such as database connections (see Figure 4.7), JavaMail objects and JMS resources.

Security

Security configuration, as discussed on Day 15, “Security.”

Transactions

Transaction requirements, as discussed in detail on Day 8.

Message Destination References

Message-Driven Bean destinations, as discussed on Day 10.

Web Service Endpoints

Web Service endpoints, as discussed on Day 20, “Using RPC-Style Web Services with J2EE,” and Day 21, “Message-Style Web Services and Web Service Registries.”

Web Service References

References to Web Services, as discussed on Day 21.


The Agency EJB illustrates common requirements for most EJBs. The use of environment references is shown in Figure 4.6, where the displayable Agency name is stored as a String environment reference. The data source definition for the Agency database is shown in Figure 4.7.

bond

Figure 4.6
Agency name stored as an environment entry.

bond

Figure 4.7
Agency database Resource Reference.

Finally, you can examine the simple application client in the Agency EAR file. In Figure 4.8, the main dialog page for an application client has been selected to show the entry for the Main Class name.

bond

Figure 4.8
Simple Client for the Agency application.

In Figure 4.8, you can see that an application client has similar configuration requirements as an EJB. Most of the tabbed dialog pages available are the same as those for an EJB. Figure 4.9 shows the configuration of the Agency Session EJB reference defined for the simple client.

bond

Figure 4.9
Agency Session EJB Reference.

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=Verifying the Case Study Application}

The J2EE RI comes with a verifier utility that you can use to validate the contents of an EAR file. The verifier can be run from the command line or it can be invoked from the Tools, Verify J2EE Compliance… menu option from within deploytool.


Note - The authors used J2EE SDK 1.4 released in November 2003 for the development of the code used in this book. Unfortunately they encountered problems when running the verifier from within deploytool. Specifically running the verifier against this simple example incorrectly reported a problem with a missing JNDI name for the jdbc/Agency resource reference. Running the command line verifier against the same EAR file did not report a problem. You are urged to double check any verification problems reported from deploytool by using the command line verifier utility. For the example case study you can do this manually using the command

verifier j2ee-ri/agency.ear

from within the Day04/exercise directory. Alternatively use the supplied asant build files (see section “Case Study asant Build Files”) and enter

asant verify-j2ee-ri



Caution - Micosoft Windows users should be aware that there is a standard Windows 2000/XP utility called verifier. If you have not put the %J2EE_HOME%bin directory at the start of your PATH environment variable you will have to use the command

%J2EE_HOME”binverifier

to run the J2EE SDK verifier. The supplied asant build files for the case study use the fully qualified file name and therefore do not require the PATH to be modified.


You are advised to run verifier on all new EAR files or when changes have been made to any of the files composing an EJB. To illustrate the use of the verifier, Figure 4.10 shows the errors produced by a simple mistake in coding the AgencyBean.java class; in this case the ejbCreate() method was mistakenly defined as create().

bond

Figure 4.10
verifer errors from a missing ejbCreate() method in AgencyBean.java.

Running the verifier from within deploytool produces a list of failed tests or a brief “There were no failed tests” message. Selecting each failed test in turn will supply further information about the test. In Figure 4.10 the message indicates the following:

 [agency.AgencyBean] does not properly declare at least one ejbCreate() method

A simple mistake can cause the failure of many tests, so do not be alarmed if you see a large number of test failures.


Caution - The verifier tool works from the on-disk EAR file and not from the in-memory copy created by deploytool. Make sure you save your application using the File, Save menu option before running verifier.


After you have written, packaged up your application, and verified the application contents, you are ready to deploy.

Deploying the Case Study Application

You can deploy the server-side components of the agency application using deploytool. To deploy the agency application, select the agency application item (indicated by a blue diamond under the Applications folder in the explorer area in the left-hand panel), and select the Tools, Deploy… menu. This will display the initial deployment screen shown in Figure 4.11.

bond

Figure 4.11
Deployment dialog for the Agency case study.

You will need to provide the administrative username and password (admin and password if you installed the J2EE SDK as described on Day 2). You should also check the Return Client Jar box on the dialogue to ensure your Application Client Jar file is downloaded from the J2EE server. Accept the default location for the client JAR file (this will be the same directory as the EAR file).

Click on OK to proceed with deploying your application and then click Close on the popup window when the deployment completes.


Note - If your J2EE component has already been deployed, the existing version will be undeployed, and then the new version will be deployed. When redeploying an application the J2EE RI will not return a new client JAR file even if asked it to do so. You will either have to do this manually or explicitly undeploy and redeploy your application as described in the section “Managing J2EE RI Applications.”


This is the point at which things might go wrong. If you are using the software from the Web site, you should have no trouble, but if you are developing your own example then you might come across problems at this stage. The “Troubleshooting Deployment” section, later on, discusses problems that might occur at deployment. If something does go wrong, study the information in the deployment progress window and also look at the J2EE console window for additional, more detailed information.

Running the Application Client

After you have successfully deployed the server-side components of the application under the J2EE RI, you can run the simple application client to test the application.

To run an application client you must have obtained the client-side JAR file from the deployed application. You did this when you deployed the application by checking the Return Client Jar… box on the deployment popup window. You can also obtain the client JAR file using either deploytool, the Web-based Admin Console, or the command line asadmin utility as described in the following section “Managing J2EE RI Applications.”

The client JAR file contains all the client and EJB class files as well as the RMI stub files required to run the application client.

You run a J2EE RI application client using the appclient command (from the J2EE SDK bin directory). The appclient requires the name of the client JAR as its single –client parameter. Assuming you have followed the deployment process described in the previous section, your returned client JAR file will be in the Day02/exercise/ j2ee-ri directory and called agencyClient.jar.

You can run your deployed client as follows (your command entry is shown in bold):

appclient -client j2ee-ri/agencyClient.jar
Welcome to: J2EE in 21 Days Job Agency
Customer list: J2EE in 21 Days Job Agency
abraham
alfred
george
winston

Done

The client JAR file is always named after the application by appending Client.jar to the name of the application.

Congratulations, you have just deployed and run your first J2EE application. If the client fails to run, then look at the errors on the console window or in the domains/domain1/logs/server.log file in the J2EE SDK home directory for more information.

If you want to examine the simple Web Application you deployed with the EJB, then browse to the URL http://localhost:8000/webagency. You will look at Web Applications in detail on Days 12, 13, and 14.

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=Managing J2EE RI Applications}

You can manage J2EE RI applications using any of the following interfaces:

  • deploytool

  • The asadmin command line utility

  • The Admin Console web application (http://localhost:4848/asadmin/)

Using deploytool you can obtain a list of deployed objects by selecting the localhost:4848 entry under Servers in the left pane and a list of deployed components will be displayed, as shown in Figure 4.12.

bond

Figure 4.12
Managing J2EE Deployed Objects with deploytool.

You can start, stop and undeploy an object using the appropriate buttons on this dialog.

Should you need to retrieve a client JAR file from a deployed application you can do this by selecting your application, clicking on the Client Jar… button and specifying a directory location on the popup dialogue window.

If you prefer to work from the command line, then you can use the asadmin utility. To deploy an application you use the asadmin deploy command. To deploy the example EAR file you have been viewing use the command

asadmin deploy –user admin –force j2ee-ri/agency.ear

You need to specify the name of your administrative user and the EAR filename; the –force option forces a redeployment if the application has already been deployed. You will be prompted for the administrative password unless you have stored this password in a configuration file, or as an environment variable, as described on Day 2 under the installation instructions for the J2EE SDK.

If you want to return the client JAR file when deploying an application use a command such as:

asadmin deploy –user admin –force –retrieve j2ee-ri j2ee-ri/agency.ear

The –retrieve option requires the name of the directory for the client JAR file; the client JAR filename is derived from the application name as described previously.

You can retrieve the client JAR file for a previously deployed application using the get-client-stubs command to asadmin as follows:

asadmin get-client-stubs –user admin –appname agency j2ee-ri

This command requires the application name (–appname option) and the target directory for the client JAR file.

As discussed on Day 2 asadmin will provide useful help messages when an invalid command is entered. And, you can always use the –help option to get more information. For example:

asadmin -help
asadmin deploy -help
admin get-client-subs –help

Finally, you can administer deployed applications using the J2EE RI Admin Console at http://localhost:4848/asadmin/. Select the Applications, Enterprise Applications option in the left pane to deploy and undeploy applications as shown in Figure 4.13.

You can only stop, start, deploy and undeploy applications using the Admin Console interface; you cannot return client JAR files.

bond

Figure 4.13
Using the J2EE RI Admin Console to Manage J2EE Components.

Case Study asant Build Files

As an alternative to using deploytool to build and deploy J2EE components, you can use Apache Ant (sometimes called Jakarta Ant) to assemble the EAR or WAR files from the constituent components. Ant is a Java-based, open source, automated build tool that is quickly becoming the de facto standard build tool for Java programmers. A version of Apache Ant, called asant, is included with the J2EE SDK and example asant build files are supplied with the J2EE 1.4 Tutorial examples. A discussion on writing the Ant build files required to assemble a J2EE archive is outside the scope of this book, but the online Ant documentation at http://ant.apache.org/manual/index.html gives a good introduction to writing build files. Alternatively you could check out the book Extreme Programming with Ant from SAMS Publishing.

On the accompanying Web site, asant build files have been provided to compile and package the EAR and WAR files used throughout this book. As described in Day 2, each working directory contains a build.xml file that defines the asant build targets appropriate for the directory.

The build.xml file in the Day04/exercise directory will build, deploy, and run the simple client example. In order to help you use asant with the case study, each build.xml file contains a help build target that will tell you which targets you can use for each directory, this is also the default asant target. Run the following command from the Day04/exercise directory to see what targets are available:

asant

To remove all the temporary files and then compile and build the case study from scratch, use the command

asant clean build

The generated agency.ear file is stored in the build subdirectory and is kept separate from the supplied agency.ear file in the j2ee-ri directory. The various deployment descriptors used to build the EAR file are kept in the dd/agency subdirectory.

You can verify the built application using the command

asant verify

The verification results from this command are stored in the file build/agency.ear.txt.

To deploy the case study from the build directory, use the command

asant deploy

This will return the client JAR as build/agencyClient.jar. To run the simple client example, use the command

asant run

You should see the following output:


appclient:
   [echo] (build) appclient.bat -client agencyClient.jar -name SimpleClient
   [exec] Welcome to: J2EE in 21 Days Job Agency
   [exec] Customer list: J2EE in 21 Days Job Agency
   [exec] abraham
   [exec] alfred
   [exec] george
   [exec] winston

   [exec] Done

To undeploy the agency example use

asant undeploy

If you want to use deploytool to build the EAR file but work at the command line to verify, deploy and run the examples, then you can use the following commands.

Verify the deploytool maintained agency.ear file in the j2ee-ri sub-directory with

asant verify-j2ee-ri

Deploy and return the j2ee-ri/agencyClient.jar file with

asant deploy-j2ee-ri

Run the application client (in the j2ee-ri sub-directory) using

asant run-j2ee-ri

To undeploy the agency example you still use

asant undeploy

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

{mospagebreak title=Troubleshooting the Case Study Application}

If you have encountered difficulties running the case study application, the following may help you in resolving your problems:

  • Have you started the J2EE RI?

  • If you are not sure, try locating its console window or looking for it in the list of processes or applications on your machine. Try browsing to http://localhost:4848 to view the Admin Console.

  • At J2EE RI install time did you define the HTTP server port to be a different value to 8000?

  • Try browsing to http://localhost:8000 to verify you are using port 8000. If you selected a different HTTP server port number you will have to use your value rather than 8000 as shown in all the examples in this book.

  • Have you started the PointBase database?

  • Try running the initial database test at the end of Day 2 exercise to ensure that the data is present and that the database server is running.

  • Have you verified the EJBs?

  • Use the asant build files to run the command line verifier. Run either
asant verify

or

asant verify-j2ee-ri

as discussed in the section “Case Study asant Build Files.”

  • Have you deployed the EJBs?

  • By opening the EAR file, you are simply loading the enterprise application into the deploytool environment. You must explicitly deploy the application to the server you are using through the Tools, Deploy menu. Check that you application has been deployed using the Admin Console application at http://localhost:4848/asadmin.

  • Have you retrieved the client JAR file after deploying your application?

  • Retrieve your application client using
    asant deploy-j2ee-ri 
  • Does the J2EE RI console window show any exceptions or errors?

  • Does the J2EE server.log file under the /domains/domain1/logs directory in J2EE_HOME show errors?

If you still have problems and you suspect there is a problem with the configuration of your J2EE RI, you can re-install, or you could try manually removing the deployed applications. You will find manually removing the applications easier than re-installing.

To manually remove an EJB component, you must perform the following steps, which are described in detail following this list:

  1. Stop the J2EE RI server.

  2. Remove the application from the J2EE domains/domain1/applications/j2ee-apps directory.

  3. Remove the application from the J2EE server configuration (domains/domain1/config/domain.xml) file.

  4. Restart the J2EE server.

You can stop the J2EE server using the command

asadmin stop-domain

or simply close down the J2EE RI window.

Once the J2EE RI has stopped you will be able to edit the configuration to manually remove an offending application.

In the J2EE home directory there is a domains sub-directory, inside which is a domain1 directory. Find the applications/j2ee-apps directory, and beneath this a subdirectory for each deployed application. Delete the offending application directory. Make sure you do not delete the supplied MejbApp and __ejb_container_timer_app directories, otherwise you will need to reinstall the J2EE RI.

In the domains/domain1 directory in the J2EE_HOME directory there is a config directory and a file called domain.xml. For safety, take a backup copy of this file before changing it. Now edit the domain.xml file and find the <applications> tag element (near the start of the file). Look for a nested <j2ee-application> with a name attribute matching your application, the entry for the example agency application will look like

<j2ee-application enabled=”true”
  location=”${com.sun.aas.instanceRoot}/applications/j2ee-apps/agency”
  name=”agency”
  object-type=”user”/>

Delete the <j2ee-application> element for your application. Make sure you do not delete the <applications> element itself or corrupt any other part of this file.

Restart the J2EE server and (hopefully) everything will still work and you can try deploying your application again. If you still have problems, your only option is to remove the J2EE SDK, reinstall and start again.

Summary

Today, you have seen common ways that EJBs are used in applications and why you would want to use them. You have seen that an EJB will have a home interface, a business or remote interface, and an implementation. You have seen how the EJB container will provide much of the underlying code to support the EJB, and that it relies on detailed deployment information that defines the EJB’s requirements.

You have also seen that a J2EE application consists of components and deployment information and how the server-side part of such an application can be deployed. You have seen a client that is able to use such server-side components and the code required to write such a client.

Q&A

  1. How many Java classes and interfaces must you write to create an EJB?

  2. The EJB writer must define a remote (or business) interface, a home interface, and the bean implementation itself.

  1. Why does an EJB run inside a container?

  2. The container provides many services to the EJB, including distribution, lifecycle, naming/registration, transaction management, security/authentication, and persistence. If the container did not exist, you would have to write all the code to interact with these services yourself.

  1. What issues are there in passing an object as part of a remote method call?

  2. To be passed as an argument or return type, an object must be either serializable or remote. If it is neither of these, an error will occur at runtime. If an object is defined as serializable, a new copy will be created and passed/returned. This can add to the overhead of making the method call, but it is a very useful tool when trying to cut down the amount of network traffic between clients and EJBs (as you will see later on Day 18).

  1. Most of the deployment descriptor information is straightforward, but what is the difference between a <resource-ref> and an <env-entry>, and what sort of information is contained in each type of entry?

  2. <resource-ref> is part of a deployment descriptor that defines an external resource used by a J2EE component. The <resource-ref> will define a name and type for a resource together with other information for the container. To access a resource defined in a <resource-ref>, you would use JNDI to look up its name (for example java:comp/env/jdbc/Agency).

    An <env-entry>, on the other hand, contains information that is intended only for the EJB itself. It will define a name, a class type and a value. The contents of <env-entry> elements are usually strings. Again, you would use JNDI to look up its name (for example java:comp/env/AgencyName).

Exercises

The intention of this day is for you to familiarize yourself with the EJB environment and the use of EJBs. To ensure that you are comfortable with these areas, you should attempt the following tasks.

  1. If you have not already done so, follow the steps to deploy the example Agency EJB from the Day04/exercise directory on the Web site using deploytool.

  2. Examine the information displayed by deploytool and make sure that you can identify where the resource reference for the Agency JDBC connection is set, where the environment reference for the agency name is set, and where the JNDI name of the Agency EJB itself is set.

  3. From within the Day04/exercise directory run the command “asant verify-j2ee-ri” to verify your application.

  4. Use the appclient command shown in today’s lesson and run the SimpleClient example. Make sure that this client runs without errors and successfully lists all the customers in the agency database.

  5. Try changing the name under which the EJB is registered in JNDI using deploytool. Change the JNDI name used by your client to find the Agency EJB and make sure that it still works.

  6. Use the asant build files instead of deploytool to compile, build, verify and deploy the example Agency application.

  7. Edit the dd/agency/sun-j2ee-ri.xml file (make a backup first of course) and change the JNDI name for the Agency Session EJB. Change the JNDI name used by your client to find the Agency EJB and make sure that it still works.

This chapter is from Teach Yourself J2EE in 21 Days, second edition, by Martin Bond et. al. (Sams, 2004, ISBN: 0-672-32558-6). Check it out at your favorite bookstore today. Buy this book now.

Google+ Comments

Google+ Comments