http://www.developer.com/

Back to article

Introduction to EJBs: Part 3


July 31, 2002


This is the third 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.


How Do I Create an EJB?

You will create specific types of EJB as you progress through the book. However, the creation of EJBs follows the same steps and principals for all types of EJB.

The Creation Mechanism

As you may have gathered from the previous discussion on EJB contents, the EJB developer must go through the following cycle:

  1. Design and define the business interface. This may involve mapping from a UML model of the solution into Java.

  2. Decide on a bean type appropriate to the task in hand. Entity, Session, and Message-driven beans all have their own pros and cons. If you choose to use a Session bean, another question is whether to use a stateful Session bean or a stateless Session bean. Choice of the appropriate type is discussed in more detail on Days 5, 6, 7, and 10.

  3. Decide which home interface methods are appropriate for the bean type and define the home interface for the EJB.

  4. Create (or generate) a "boilerplate" bean with correct lifecycle methods.

  5. Create your business logic by filling out the business methods.

  6. Fill out lifecycle methods to control creation, destruction and to manage state (if applicable).

If your EJB classes are written correctly, all that remains is to wrap them up as a deployable unit. However, there are certain caveats you should bear in mind while creating your bean.

Caveats on Code Creation

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. All threading is controlled by the container.

  • 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 classloaders 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. This relates to the earlier discussion that a bean should not implement its associated remote interface. This would potentially give a client a direct remote reference to the bean rather than the EJBObject. Instead, the bean should query its EJB context for a reference to its associated EJBObject and return that to the caller.

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

Create the Deployable Component

One alternative definition of a component is "a unit of deployment." Following this theme, a component should

  • Contain all the information required to deploy it, above and beyond the classes. This is the metadata discussed earlier.

  • Be bound up in such a way that it can easily be transported and deployed without losing any parts along the way.

Consequently, after the classes and interfaces for an EJB have been created, the following steps must be performed:

  1. Capture the EJB's metadata in a universally understood format. This takes the form of an XML-based deployment descriptor (DD).

  2. Bundle the classes and deployment descriptor up in a deployable format, namely a JAR file.

The Deployment Descriptor

The EJB specification defines a standard format of an XML deployment descriptor document that can house EJB metadata. The exact format of a deployment descriptor is usually hidden behind tools that manipulate them 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 metadata is provided.

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

Listing 4.5 Agency Bean EJB Deployment Descriptor

 1: <?xml version="1.0" encoding="UTF-8"?>
 2: 
 3: <!DOCTYPE ejb-jar PUBLIC 
 '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN'
 'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>
 4:
 5: <ejb-jar>
 6:  <display-name>Simple</display-name>
 7:  <enterprise-beans>
 8:   <session>
 9:    <display-name>Agency</display-name>
 10:    <ejb-name>Agency</ejb-name>
 11:    <home>agency.AgencyHome</home>
 12:    <remote>agency.Agency</remote>
 13:    <ejb-class>agency.AgencyBean</ejb-class>
 14:    <session-type>Stateless</session-type>
 15:    <transaction-type>Bean</transaction-type>
 16:    <env-entry>
 17:     <env-entry-name>AgencyName</env-entry-name>
 18:     <env-entry-type>java.lang.String</env-entry-type>
 19:     <env-entry-value>J2EE in 21 Days Job Agency</env-entry-value>
 20:    </env-entry>
 21:    <security-identity>
 22:     <description></description>
 23:     <use-caller-identity></use-caller-identity>
 24:    </security-identity>
 25:    <resource-ref>
 26:     <res-ref-name>jdbc/Agency</res-ref-name>
 27:     <res-type>javax.sql.DataSource</res-type>
 28:     <res-auth>Container</res-auth>
 29:     <res-sharing-scope>Shareable</res-sharing-scope>
 30:    </resource-ref>
 31:   </session>
 32:  </enterprise-beans>
33: </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 (lines 8 and 31).

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

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

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

  • An environment entry is defined between lines 16 and 20 by 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 the name 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.3.

  • An external resource is defined in lines 25–30 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.3.


Note

It is important to realize that the name used for a <resource-ref> is only a logical name. In other words, it is just a text string used by a component to reference an external resource. In theory, the resource name used by the EJB to refer to the data source could be anything (foo, for example) as long as it ties in with the information in the deployment descriptor. However, by convention, such names are kept in line with the name you would expect to use under JNDI. As a result, in this example, the data source resource is referred to by the bean as jdbc/Agency and will be registered under JNDI with the same name.


All of the EJB classes and the deployment descriptor should then be bundled up in a JAR file. The deployment descriptor should 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. This JAR file is then termed an EJB-JAR file to denote its payload. The JAR file itself can be called anything (within reason) and has a .jar file extension.

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

Enterprise Applications

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 application components). The key is how to define the relationships between the different parts of the application—there must be some way of plugging things together.

The answer is that there must be a description of the application itself, 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 roles.

To provide this information to the target J2EE platform, another level of deployment descriptor is used —the J2EE deployment descriptor. The J2EE deployment descriptor provides the following:

  • A list of the components in the application

  • Security role information

  • Web root information for Web components

This information is stored in an XML file called application.xml. All of the constituent component JAR files (such as EJB-JARs) and the J2EE deployment descriptor are then bundled up in another JAR file, this time called an Enterprise Archive (EAR) file, which has a .ear extension. The contents of the J2EE deployment descriptor will be covered in more detail as you examine the different parts of the example enterprise application.

Is the application now ready to deploy? Unfortunately, the answer is "Not quite yet." The J2EE deployment descriptor does not cover information about how to map the application onto a specific J2EE application server, specifically

  • The JNDI name under which the application server will make the EJB available. In the case of the Agency bean, this would mean that an entry was required to map the bean name of Agency to the JNDI name under which the EJB is registered, for example, ejb/Agency.

  • Information about how the security roles defined map to underlying security principals (this is covered on Day 15).

So, yet another XML-based deployment descriptor is required to contain this information, this time an application server-specific one. This file contains extra mapping information, as previously described, and also any other container-specific information required for a smooth deployment in that environment. This extra deployment descriptor is also stored in the EAR file, ready to be accessed when the application is deployed.


Note

The specific deployment descriptor for the J2EE Reference Implementation (RI) server is called sun-j2ee-ri.xml.


How Do I Deploy an EJB?

After an EJB is packaged, it can be deployed in an appropriate J2EE server. There is no limit to the number of times an EJB can be deployed as a part of different applications.

Remember that J2EE defines a separate role for the application deployer. It may be that for particular installations, databases, or other resource names need to be changed to match the local environment. When configuring the application, the deployer can alter this EJB or enterprise application metadata.

Plugging into the Container

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

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

The container will examine the EJB and enterprise application metadata and hook up resource references. It will also provide an environment for the application components.

Finally, the container will register the home interface of the EJB with JNDI. This allows other application components to create and find EJBs of this type.

Performing the Deployment

As mentioned previously, when deploying an EJB or enterprise application, the application developer taking on the J2EE role of deployer can choose to alter certain of the metadata relating to the configuration of the application. Although this can be done manually, it is usually done through a GUI tool to make things easier and to keep things consistent.

After the EJB has been deployed, any subsequent changes to its functionality will mean that the EJB must be re-deployed. 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. These steps are covered in the next three sections.

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 get hold of a remote reference to the home interface. On Day 3, you looked at naming services and how these can be used to register information in a distributed environment. In a J2EE environment, such a naming service is accessible through JNDI and can be used to store references to EJB home interfaces.

The EJB container will have registered the home interface using the JNDI name specified during deployment (as part of the deployment descriptor). This is the name that the client should use to look up the home interface. Recall from the EJB deployment descriptor shown in Listing 4.5 that the EJB name specified was Agency. When deploying the EJB, the deployer has a chance to set the JNDI name by which clients will find this EJB. In this case, you would expect the deployer to simply set a JNDI name of ejb/Agency so that the client could find the home interface by looking up java:comp/env/ejb/Agency. The following code shows the initial lookup required:

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 */ }

As you can see, because the reference returned from JNDI is just an object, you must narrow it to the home interface type you expect—in this case, AgencyHome. If there are any problems with the JNDI access or if the wrong object type is returned, a NamingException or ClassCastException will be thrown.

There is no magic here. The object returned by the JNDI is simply an RMI remote object stub. This stub represents the home interface remote object created by the container when the EJB was deployed. This can be seen in Figure 4.2.

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

Retrieval and Use

You can now call the create() method you saw defined on the AgencyHome interface in Listing 4.4 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 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 at the top of your client class.

Now that you have a reference to an EJB, you can call its methods. 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 RemoteExceptions.


Note

You will see later that some types of EJB 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 later when Entity EJBs are discussed on Day 6.


Disposing of the EJB

You have now created and used an EJB. What happens now? Well, if you no longer need the EJB, you can get rid of it in exactly the same way that you would get rid of a local Java object or a remote Java object defined using RMI—by setting its reference to null as follows:

 // No longer need the agency EJB instance
 agency = null;

When the local RMI runtime detects that the remote object no longer has any local references, it will trigger remote garbage collection for that object, which means that its remote reference will time out. This will result in the object being de-referenced at the server-side. In the case of the simple Agency bean (a stateless Session bean), this will cause the bean to be destroyed.

Although it is possible to use the remove() method to get rid of the EJB, you would not normally use this for such a simple bean. Use of this method is discussed in more detail on Days 5 and 6.

Running the Client

You are now in a position to write a simple application client for the Agency EJB. After you have written it, you will want to compile and run it.

Before compiling your client, you should ensure that you have j2ee.jar on your classpath. This JAR file lives in the lib directory under J2EE_HOME. If you are using an enterprise IDE, you may find that all the relevant classes are already in your classpath.

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

  • The J2EE classes. These must be accessible through the classpath.

  • Access to the EJB's home and remote interface class files via the classpath.

  • RMI stubs for the home and remote interfaces. These can either be installed on the local classpath or downloaded dynamically from the EJB server.

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

When you deploy the EJB, you should be able to 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.

In theory, this should be it. However, you will find that any form of security definition on the server will require you to authenticate yourself before you can run the application. In this case, you must explicitly use the client container to provide the required security mechanism.


Note

The client container is called runclient under the J2EE RI.


Monday's installment: What is an EJB and why use them?

Tuesday's installment: What's in an EJB and how do I create one?

Thursday's installment: Deploying and Using an EJB in the J2EE Reference Implementation


About the Author

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

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.

To access the full Table of Contents for the book

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date