Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Mastering Enterprise JavaBeans™ and the Java 2 Platform, Enterprise Edition - Roman E

..pdf
Скачиваний:
41
Добавлен:
24.05.2014
Размер:
6.28 Mб
Скачать

The Basics of Stateless Session Beans 107

when a bean crashes. Some high-end EJB products even provide transparent fail-over for stateful beans by routinely checkpointing the stateful bean’s conversational state. In case of a critical, unrecoverable problem, your EJB container may support professional monitoring systems, alerting a system administrator in the event of a catastrophic error.

By way of comparison, application-level exceptions should always be thrown back to the client. Application-level exceptions indicate a routine problem, and the exception itself is valuable data that the client needs. For example, we could notify a client that there are insufficient funds in a bank account by throwing an application-level exception. The client would always want to know about this because it is an application-level problem, not a systems-level problem.

Besides correctly routing system-level and application-level exceptions, the EJB object is responsible for catching all unchecked exceptions (flavors of java.lang.RuntimeException) that your bean may throw, such as a NullPointer exception. These are typically not caught by code. Exceptions that are unchecked in the bean could leave the bean in an abnormal state because the bean is not expecting to handle such an exception. Under this kind of scenario, the EJB container intercepts the exception and can perform some action, such as throwing the exception back to the client as a remote exception. It also will probably stop using that bean because the bean is in an undefined state.

The following two rules of thumb should help you with exceptions:

1.Application-level exceptions are always thrown back to the client. This includes any exception the bean defines. It also includes the javax.ejb.CreateException for creating beans (and the javax.ejb.FindException for entity beans, which we’ll see in Chapters 7–9).

2.When system-level exceptions occur, the EJB container can do anything it wants to: page a system administrator with an alert, send an e-mail to a third party, or throw the exception back to the client. Your bean can throw a system-level exception as either a Java RMI remote exception or an unchecked RuntimeException. If the exception is thrown to the client, it is always thrown as a remote exception or a subclass of it.

Exceptions also have an impact on transactions. We’ll learn more about this effect in Chapter 10.

The Environment Properties

Finally, you can include an environment properties file with your bean to specify business logic customization. Your bean can use this information to adapt itself to a particular environment.

For example, if you have a bean that employs a variety of algorithms (using different strategies to solve a problem or the strategy design pattern), you could specify the particular algorithm to use on deployment with environment properties.

Go back to the first page for a quick link to buy this book online!

108

 

M A S T E R I N G

E N T E R P R I S E J A V A B E A N S

Table 4.1 Deployment Descriptor Settings for HelloBean

 

 

DEPLOYMENT

 

DESCRIPTOR SETTING

VALUE

Bean home name

HelloHome

Enterprise bean class name

com.wiley.compBooks.roman.session.helloworld.HelloBean

Home interface class name

com.wiley.compBooks.roman.session.helloworld.HelloHome

Remote interface class name

com.wiley.compBooks.roman.session.helloworld.Hello

Environment properties

<empty>

Re-entrant

false

Stateful or stateless

STATELESS_SESSION

Session timeout

10 seconds

Note the difference of function here—the container uses the deployment descriptor to aid in managing your bean, while your bean can use the environment properties file to customize its internal logic.

Because our “Hello, World!” bean is very simple, we do not need to define properties. If you’d like to see environment properties in action, see Chapter 6.

The Ejb-jar File

There’s one last step before deploying our bean. Now that we’ve written all the necessary files for our component, we need to package the files together in an Ejb-jar file. This is a compressed file that contains everything we’ve written above, following the .ZIP compression format. Jar files are convenient, compact modules in which to wrap our beans. Note that you can have more than one bean in an Ejb-jar file, allowing you to ship an entire product set of beans in a single jar file.

The following files must be included in an Ejb-jar file:

■■Enterprise bean(s)

■■Remote interface(s)

■■Home interface(s)

■■Deployment descriptor(s), including properties to customize your beans’ logic

If you’re developing with EJB 1.0, you can also include a manifest file containing a list of what’s in the Ejb-jar file.

Go back to the first page for a quick link to buy this book online!

The Basics of Stateless Session Beans 109

The Manifest

Manifests are simple text files that can be part of a jar file. Usually you put information in the manifest detailing what’s in the jar. In EJB 1.0, the manifest file identifies which enterprise beans are inside your Ejb-jar file. In EJB 1.1, manifests are not necessary because the XML deployment descriptor contains all the necessary descriptive information.

Manifests are organized into several sections. You must separate one section from another with a blank line. Within each section you can put one or more headers. Each header is similar to a Java properties file, of the form <tag> : <value>.

There are two header tags that are relevant to EJB:

Name whose value is the location of a bean’s deployment descriptor in the Ejbjar file. This name must be a “relative” name, meaning the location relative to the root of the jar file.

Enterprise-Bean whose value must be “True.”

For example, the manifest that follows identifies the locations of two beans, whose serialized deployment descriptors are named Bean1DD.ser and

Bean2DD.ser:

Name: Bean1/deployment/manifest/Bean1DD.ser

Enterprise-Bean: True

Name: Bean2/deployment/manifest/Bean2DD.ser

Enterprise-Bean: True

Here’s the manifest that goes with our “Hello, World!” example:

Name: com/wiley/compBooks/roman/session/helloworld/deployment/

HelloBeanDD.ser

Enterprise-Bean: True

The EJB container will look for this manifest in a well-known location in the jar, and it will use the manifest to acquire information about the beans inside the jar. The previous example contains the following information in the manifest:

■■The first line locates our serialized deployment descriptor within the jar. Remember, the deployment descriptor tells everything about our bean, so this is the only real locator information we need to supply in our manifest.

■■The second line simply indicates to the container that we are indeed supplying an enterprise bean. This is a reality check so the container knows it is dealing with an enterprise bean.

Go back to the first page for a quick link to buy this book online!

110 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

Generating the Ejb-jar

Once we have all the ingredients, we generate the Ejb-jar with the following statement:

jar cmf ..\manifest HelloWorld.jar *

This command assumes that the manifest file is one directory below the current one. The asterisk indicates the files to include in the jar—this means all the necessary classes, properties files, and deployment descriptors. They must be in properly named subdirectories of the current directory. For example, our

Hello.class file is located in com\wiley\compBooks\roman\session\helloworld\ Hello.class, below the current directory. You must store your classes in a directory corresponding to the package that the class belongs to or the JVM will be unable to locate your classes when it searches your jar.

If you’re using a development environment supporting EJB, the development environment may contain an automated way to generate the Ejb-jar file for you.

Deploying the Bean

Finally, we’re ready to deploy our bean in an EJB container. This step will vary from container to container. When you reach this point, you should consult your container’s documentation on how to deploy a bean. For an example using the BEA WebLogic server, see the included CD-ROM.

When deploying an Ejb-jar file into a container, the following steps are usually performed:

■■The Ejb-jar file is verified. The container checks that the enterprise bean class, the remote interface, and other items are valid. Any commercial tool should report intelligent errors back to you, such as “You need to define one ejbCreate() method in a stateless session bean.”

■■The container tool generates an EJB object and home object for you.

■■The container tool generates any necessary RMI stubs and skeletons (see Appendix A for more information about stubs and skeletons).

Once you’ve performed these steps, start up your EJB container/server product. Most products will output a server log or have a GUI to view the beans that are deployed. Make sure that your container is indeed making your bean available. For example, when we start the BEA WebLogic server, the server yields the following output:

...

Tue Feb 23 05:20:07 CST 1999:<I> <EJB> Reading Enterprise JavaBean

descriptor: d:/apps/weblogic/classes/com/wiley/compBooks/roman/session/

helloworld/deployment/HelloBeanDD.ser

Go back to the first page for a quick link to buy this book online!

The Basics of Stateless Session Beans 111

Tue Feb 23 05:20:08 CST 1999:<I> <EJB> EJB home interface 'com.wiley.compBooks.roman.session.helloworld.HelloHome' bound to the JNDI name 'HelloHome'

Tue Feb 23 05:20:08 CST 1999:<I> <EJB> Deployed d:/apps/weblogic/ classes/com/wiley/compBooks/roman/session/helloworld/deployment/ HelloBeanDD.ser

...

As you can see, the server recognized our deployed bean and made it available for clients to call.

Writing Client Code for Our Stateless Bean

Next, let’s write a sample client to call our enterprise bean. The complete client source code illustrating the previous steps is shown in Source 4.4.

package com.wiley.compBooks.roman.session.helloworld;

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

import java.util.Properties;

/**

*This class is an example of client code that invokes

*methods on a simple stateless session bean.

*/

public class HelloClient {

public static void main(String[] args) {

try { /*

* Get System properties for JNDI initialization */

Properties props = System.getProperties();

/*

* Form an initial context */

Context ctx = new InitialContext(props);

/*

*Get a reference to the home object

*(the factory for EJB objects)

*/

Source 4.4 HelloClient.java (continues).

Go back to the first page for a quick link to buy this book online!

112 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

HelloHome home = (HelloHome) ctx.lookup("HelloHome");

/*

* Use the factory to create the EJB Object */

Hello hello = home.create();

/*

* Call the hello() method, and print it */

System.out.println(hello.hello());

/*

* Done with EJB Object, so remove it */

hello.remove();

} catch (Exception e) { e.printStackTrace();

}

}

}

Source 4.4 HelloClient.java (continued).

The client code performs the following tasks:

1.Looks up a home object

2.Uses the home object to create an EJB object

3.Calls hello() on the EJB object

4.Removes the EJB object

Each of these steps was described fully in Chapter 3.

Running the System

To try out the deployment, you first must bring up the application server. This step will vary depending on your vendor. For BEA’s WebLogic, we type the following (assuming a correct CLASSPATH):

t3server

Next, run the client application. When running the client, you need to supply the client with JNDI environment information. As we explain in Appendix B, JNDI requires at a minimum two properties to retrieve an initial context:

Go back to the first page for a quick link to buy this book online!

The Basics of Stateless Session Beans 113

■■The name of the initial context factory. An example is com.sun.jndi.ldap

.LdapCtxFactory.

■■The provider URL, indicating the location of the directory structure to use. An example is ldap://louvre:389/o=Airius.com.

The actual parameters you need should be part of your EJB container’s documentation. For example, with BEA’s WebLogic application server, we launched our client program with the following JNDI initialization properties:

java -Djava.naming.factory.initial= weblogic.jndi.TengahInitialContextFactory

-Djava.naming.provider.url= t3://localhost:7001

com.wiley.compBooks.roman.session.helloworld.HelloClient

For your EJB client code to work, you must take care to distribute the correct class files on the right machines. Because client code uses home interfaces and remote interfaces, you must deploy those class files in your client environment. And because clients never directly access your bean implementation, you don’t need to (nor should you) deploy your bean classes in your client environment.

The Server-Side Output

When we run the client, our container shows the following debug log (debug logs are great for seeing what your enterprise beans are doing):

setSessionContext()

ejbCreate()

hello()

ejbRemove()

As you can see, the container associated our bean with a session context, called create(), delegated a business method to the bean, and then called remove(). Note that because bean pooling algorithms are proprietary, you may see different output for other containers—it’s all implementation-specific and part of EJB product differentiation. Keep this in mind when debugging your beans.

The Client-Side Output

After running the client, you should see the following output:

Hello, World!

Congratulations—it took awhile, but you’ve successfully completed your first Enterprise JavaBeans deployment!

Go back to the first page for a quick link to buy this book online!

114 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

Summary

In this chapter, we learned how to program stateless session beans. We saw the theory behind programming each of the beans, as well as examples of the beans in action. We also looked at how deployment descriptors work and how EJB client code is written.

In the next chapter, we’ll learn how to code stateful session beans.

Go back to the first page for a quick link to buy this book online!

C H A P T E R5

The Basics of Stateful

Session Beans

tateful session beans are conversational beans because they hold conversations Swith clients that span multiple method invocations. Stateful session beans store conversational state within the bean. That conversational state is specific to a particular client. This chapter will teach you the basics of writing stateful session beans. We’ll begin at the conceptual level and quickly move into a code example illustrating session bean development. We’ll wrap up with a comparison

of the stateful and stateless programming models.

Characteristics of Stateful Session Beans

Let’s begin with a look at the characteristics that all stateful session beans share.

Achieving the Effect of Pooling with Stateful Beans

Imagine a scenario where thousands of clients are having conversations with different stateful session beans running within a container. Let’s assume that the clients are typical clients and take a long time to “think” between method calls. Perhaps a client is far away, connecting from another country, and the network lag is high. Or perhaps the client represents a human interacting with a Java applet, and the human is deciding on the next button to click.

Thousands of clients imply thousands of stateful session beans, each holding conversational state on behalf of a specific client. And, of course, our EJB container/server has only a finite amount of resources available, such as memory, database connections, and socket connections. If the conversational state that

115

Go back to the first page for a quick link to buy this book online!

116 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

the beans are holding is large, the container/server could easily run out of resources. This was not a problem with stateless session beans because the container could pool only a few beans to service thousands of clients.

With stateful session beans, pooling is not as simple. When a client invokes a method on a bean, he or she is starting a conversation with the bean, and the conversational state stored in the bean must be available for that same client’s next method request. Therefore, the container cannot easily pool beans and dynamically assign them to handle arbitrary client method requests, since each bean is storing state on behalf of a particular client. But we still need to achieve the effect of pooling for stateful session beans, so that we can conserve resources and enhance the overall scalability of the system.

This problem should sound quite familiar to operating systems gurus. Whenever you run an application on a computer, you have only a fixed amount of physical memory in which to run. The operating system still must provide a way for many applications to run, even if the applications take up more aggregate memory than is available physically. To provide for this, operating systems use your hard disk as an extension of physical memory. This effectively extends the amount of virtual memory that your system has. When an application goes idle, its memory can be swapped out from physical memory and onto the hard disk. When the application becomes active again, any needed data is swapped in from the hard disk and into physical memory. This type of swapping happens very often when switching between applications (called context switching).

EJB containers exploit this very paradigm to conserve stateful session bean resources. To limit the number of stateful session bean instances in memory, the container can swap out a stateful bean, saving its conversational state to a hard disk or other storage. This is called passivation. After passivating a stateful bean, the conversational state is safely stored away, allowing resources such as memory to be reclaimed. When the original client invokes a method, the passivated conversational state is swapped in to a bean. This is called activation. This bean now resumes the conversation with the original client. Note that the bean that receives the activated state may not be the original bean instance. But that’s all right because the instance is resuming its conversation from the point where the original instance was passivated.

Thus, EJB does indeed support the effect of pooling stateful session beans. Only a few instances can be in memory when there are actually many clients. But this pooling effect does not come for free—the passivation/activation steps could entail an I/O bottleneck. Contrast this to stateless session beans, which are easily pooled because there is no state to save.

So how does the container decide which beans to activate and which beans to passivate? The answer is specific to each container. Most containers will employ a Least Recently Used (LRU) passivation strategy, which simply means to

Go back to the first page for a quick link to buy this book online!