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

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

.pdf
Скачиваний:
45
Добавлен:
24.05.2014
Размер:
6 Мб
Скачать
☆

C H A P T E R14

J2EE in the Real World:

Implementing Our E-Commerce

Session Beans

n Chapter 12, we designed an object model for a real e-commerce solution us- Iing EJB. In this chapter, we’re going to implement our e-commerce deployment’s session beans. Whereas entity beans model data, our session beans will contain business logic that performs the necessary algorithms and strategies. In general,

every serious EJB deployment will have a combination of beans such as this.

We’ll present four new session beans in this chapter. If you need a refresher on the motivation behind creating these beans, or if you need to see the big picture for our deployment, refer to Chapter 12.

A Quote Line Item session bean. When the user navigates our Web site, he or she will choose certain products and add them to the shopping cart, or Quote. A Quote is composed of many line items, where each line item has information about a single product that the user wants. The user is free to add or remove line items from the Quote until he or she is satisfied and wants to buy the selections. Once the user clicks the purchase button, the Quote Line Items become line items for a permanent order. Thus, a Quote Line Item is temporary and in-memory only and is well modeled as a stateful session bean. The bean’s state is the product and quantity being quoted.

A Quote session bean. A Quote represents the user’s shopping cart and stores each of the user’s Quote Line Items. A Quote is also a stateful session bean.

A Pricer session bean. Our Pricer bean will be responsible for taking a Quote bean as input, and computing its price. The price is calculated based on a set of pricing rules, such as a discount for a particular customer. Our Pricer bean serves as a simple method provider of business logic, and it is well-modeled as a stateless session bean because it retains no state after computing a price.

401

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

402 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

EJB Design Strategies

When Should I Wrap Entity Beans with Session Beans?

As we mentioned in Chapter 12, a useful EJB paradigm is to keep your functional objects in session beans and have them transactionally manipulate entity beans that reside in an underlying store.

Working with this paradigm has many benefits. For example:

■■If you cache your transactional functionality in a session bean (as we’ll see later in this chapter), you eliminate the need for your client code (such as servlets) to have any transaction know-how. This greatly reduces usage errors.

■■Because clients don’t need to have any explicit transaction calls, client programming is simplified. You can perform transactions declaratively, rather than programmatically, by deploying a session bean whose transactions are managed by the application server.

■■By wrapping entity beans with session beans, you reduce round trips between the client and the beans. If your presentation tier is making numerous transactional calls to the business logic tier, your application’s performance is going to grind to a halt.

However, you shouldn’t always wrap entities with sessions. If you have a simple deployment where you are in control of the operational environment, wrapping entities with sessions may be an unnecessary layer of indirection. An example of when you’d want to call entity beans directly is an e-commerce deployment where servlets and enterprise beans are running in the same application server. Because they’re in the same address space, there are no network round trips to deal with, so performance is high. Unfortunately, if you’re in the market of selling beans, you can’t always choose your deployment environment.

We’ll see more design strategies, such as the one at the end of Chapter 15, when we’ve completed our e-commerce system. For now, let’s begin writing our session beans.

A Teller bean. If you’ll recall, in Chapter 8 we design a Bank Account entity bean. In this chapter, we’ll write a Bank Teller session bean, which wraps that Bank Account entity bean. The Teller serves as a convenience class for performing bulk bank account operations (such as a transfer of funds from one account to another). You’ll see this familiar paradigm of wrapping entity beans with session beans frequently in the EJB world. It makes a lot of sense—rather than calling across the network frequently when accessing entity beans, you can design a session bean to perform bulk entity bean updates for you.

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

J2EE in the Real World: Implementing Our E-Commerce Session Beans 403

The Quote Line Item Stateful Session Bean

Our first session bean is a Quote Line Item. As the user goes through the catalog, he or she will pick out different Products and add them to the Quote bean (described later in this chapter). Quotes are made up of Quote Line Items, where each line item contains information about a single product and quantity. More specifically, a line item contains the following data:

■■The ID of this line item

■■The Product (entity bean) that the user wants to buy

■■The quantity of that Product

■■Any discounts the customer gets from the base price of the Product

Because a Quote Line Item is specific to one customer and is not persistent, it is best modeled as a stateful session bean. Let’s begin our implementation.

QuoteLineItem.java

The first source code that we’ll generate is our bean’s remote interface. The remote interface is the interface that clients operate on to call methods on our bean. The code is in QuoteLineItem.java, shown in Source 14.1.

This is a straightforward remote interface, exposing simple get/set methods to modify the session bean’s internal state. Of note, the getProduct() method returns the Product entity bean that this line-item represents. There is no setProduct() method—our bean implementation’s ejbCreate() method will handle that.

package com.wiley.compBooks.ecommerce;

import javax.ejb.*;

import java.rmi.RemoteException;

/**

*These are the business logic methods exposed publicly

*by QuoteLineItemBean.

*

*This interface is what clients operate on when they

*interact with beans. The container vendor will implement

*this interface; the implementation object is called the

Source 14.1 QuoteLineItem.java (continues).

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

404 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

*EJB Object, which delegates invocations to the actual

*bean.

*/

public interface QuoteLineItem extends EJBObject {

// Getter/setter methods for Entity Bean fields

public Product getProduct() throws RemoteException;

public double getBasePrice() throws RemoteException;

public double getDiscount() throws RemoteException;

public void setDiscount(double discount) throws RemoteException;

public int getQuantity() throws RemoteException;

public void setQuantity(int quantity) throws RemoteException;

}

Source 14.1 QuoteLineItem.java (continued).

QuoteLineItemBean.java

Next, we’ll write our core bean’s implementation. The code is in QuoteLineItemBean

.java, shown in Source 14.2.

Our session bean does not contain much logic—indeed, most of our bean is made up of get/set methods, comments, and empty methods that EJB requires. Our bean’s state is the product that this line-item represents, the product quantity desired, and the discount that the customer receives. Notice that our session bean references the Product entity bean we created in Chapter 9. It uses that bean to identify the product associated with this line item.

Our session bean has no unique identifier or primary key. No session beans have primary keys because session beans are not permanent, identifiable, persistent, locatable objects, as entity beans are.

package com.wiley.compBooks.ecommerce;

import java.sql.*; import javax.naming.*; import javax.ejb.*; import java.util.*;

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

Source 14.2 QuoteLineItemBean.java (continues).

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

J2EE in the Real World: Implementing Our E-Commerce Session Beans 405

/**

*

*This stateful session bean represents an individual

*line item, which is part of a quote that a customer is

*working on. A quote is a set of products that the

*customer is interested in but has not committed to buying

*yet. You can think of this bean as a shopping cart - as the

*customer surfs our e-commerce Web site, the quote stores all

*the products and quantities he or she is interested in.

*

*A quote consists of a series of line items. Each line item

*represents one particular product the customer wants, as

*well as a quantity for that product. This bean models a

*line item.

*

*The distinction between a quote and an order is that a quote

*is only temporary and in-memory (hence a stateful session

*bean), whereas an order is a persistent record (hence an

*entity bean). This quote bean is smart enough to know how

*to transform itself into an order (via the purchase() method). */

public class QuoteLineItemBean implements SessionBean {

protected SessionContext ctx;

//--------------------------------------------------------

//Begin Stateful Session Bean Conversational State fields

//(Conversational state is non-transient, and is

//perserved during passivation and activation)

//--------------------------------------------------------

/*

* The product that this line item represents. */

private Product product;

/*

* The quantity of the product desired */

private int quantity;

/*

* Any discount the customer gets */

private double discount;

//--------------------------------------------------------

// End Stateful Session Bean Conversational State fields //--------------------------------------------------------

Source 14.2 QuoteLineItemBean.java (continues).

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

406 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

public QuoteLineItemBean() { System.out.println(

"New QuoteLineItem Session Bean created by EJB Container.");

}

//--------------------------------------------------------

// Begin public business methods //--------------------------------------------------------

// Simple getter/setter methods of Session Bean fields.

public Product getProduct() throws RemoteException { System.out.println("QuoteLineItem.getProduct() called."); return product;

}

/**

*Returns the base price. The base price is the

*product's price times the quantity ordered. This

*figure does not take discounts into consideration. */

public double getBasePrice() throws RemoteException { System.out.println("QuoteLineItem.getBasePrice() called."); return quantity * product.getBasePrice();

}

/**

* Returns the discount that the customer gets on this

*order.

*Note: The discount is a whole number, not a percentage

*discount.

*/

public double getDiscount() throws RemoteException {

System.out.println("QuoteLineItem.getDiscount() called.");

return discount;

}

/**

*Sets the discount that the customer gets on this order.

*Note: The discount is a whole number, not a percentage

*discount.

*/

public void setDiscount(double discount) throws RemoteException {

System.out.println("QuoteLineItem.setDiscount() called.");

this.discount = discount;

}

Source 14.2 QuoteLineItemBean.java (continues).

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

J2EE in the Real World: Implementing Our E-Commerce Session Beans 407

public int getQuantity() throws RemoteException { System.out.println("QuoteLineItem.getQuantity() called."); return quantity;

}

public void setQuantity(int quantity) throws RemoteException { System.out.println("QuoteLineItem.setQuantity() called."); this.quantity = quantity;

}

//--------------------------------------------------------

// End public business methods //--------------------------------------------------------

//--------------------------------------------------------

//Begin EJB-required methods. The methods below are

//called by the Container and are never called by client

//code.

//--------------------------------------------------------

/**

* Associates this Bean instance with a particular context. */

public void setSessionContext(SessionContext ctx) throws RemoteException { System.out.println("QuoteLineItem.setSessionContext called"); this.ctx = ctx;

}

/**

*The container calls this method directly after

*activating this instance. You should acquire any

*needed resources.

*/

public void ejbActivate() throws RemoteException { System.out.println("QuoteLineItem.ejbActivate() called.");

}

/**

*The container calls this method directly before

*passivating this instance. You should release

*resources acquired during ejbActivate().

*/

public void ejbPassivate() throws RemoteException { System.out.println("QuoteLineItem.ejbPassivate () called.");

}

/**

* This is the initialization method that corresponds

Source 14.2 QuoteLineItemBean.java (continues).

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

408 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

*to the create() method in the Home Interface.

*When the client calls the Home Object's create()

*method, the Home Object then calls this ejbCreate()

*method.

*/

public void ejbCreate(Product product) throws CreateException, RemoteException {

System.out.println("QuoteLineItem.ejbCreate(" + product.getName() + ") called");

this.product = product; this.quantity = 1; this.discount = 0;

}

/**

*Removes this quote line-item, and hence all

*client-specific state.

*/

public void ejbRemove() throws RemoteException { System.out.println("QuoteLineItem.ejbRemove() called.");

}

//--------------------------------------------------------

// End EJB-required methods. //--------------------------------------------------------

}

Source 14.2 QuoteLineItemBean.java (continued).

QuoteLineItemHome.java

Next, we’ll write our bean’s home interface. Clients will call the home interface to create and destroy Quote Line Item EJB objects. The code is in QuoteLineItemHome

.java, shown in Source 14.3.

Our home interface has a single create method—create()—that creates a new quoted line item for a specific product.

The Deployment Descriptor

Finally, we have a deployment descriptor for our Quote Line Item, shown in Table 14.1.

The most important entries in Table 14.1 are the transaction isolation level and the transaction attribute. When deciding on the proper isolation level for this

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

J2EE in the Real World: Implementing Our E-Commerce Session Beans 409

package com.wiley.compBooks.ecommerce;

import javax.ejb.*;

import java.rmi.RemoteException; import java.util.Enumeration;

/**

*This is the home interface for QuoteLineItem. This interface

*is implemented by the EJB Server's glue-code tools - the

*implemented object is called the Home Object and serves as a

*factory for EJB Objects.

*

*One create() method is in this Home Interface, which

*corresponds to the ejbCreate() method in the QuoteLineItem

*file.

*/

public interface QuoteLineItemHome extends EJBHome {

/*

*This method creates the EJB Object.

*Notice that the Home Interface returns an EJB Object,

* whereas the Bean returns void. This is because the

*EJB Container is responsible for generating the

*EJB Object, whereas the Bean is responsible for

*initialization.

*

*@param product Product Entity Bean for this line item

*@return The newly created EJB Object.

*/

public QuoteLineItem create(Product product) throws CreateException, RemoteException;

}

Source 14.3 QuoteLineItemHome.java.

bean, we recall that Quote Line Items are temporary, in-memory session beans. We do not perform any persistent operations at all, and we do not anticipate any concurrency issues. This leads us to choose the weakest isolation level— TRANSACTION_READ_COMMITTED—that will give us the highest performance. We also choose to support transactions but not require them, as we are not performing any operations that require a transaction. For our security runas mode, we are not performing any secure operations, so we’ll leave the bean to run as the client identity.

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

410

 

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 14.1 Deployment Descriptor Settings for QuoteLineItemBean

 

 

DEPLOYMENT

 

DESCRIPTOR SETTING

VALUE

Bean home name

Ecommerce.QuoteLineItemHome

Enterprise bean class name

com.wiley.compBooks.ecommerce.QuoteLineItemBean

Home interface class name

com.wiley.compBooks.ecommerce.QuoteLineItemHome

Remote interface class name

com.wiley.compBooks.ecommerce.QuoteLineItem

Environment properties

<empty>

Re-entrant

false

Stateful or stateless

STATEFUL_SESSION

Session timeout

15 minutes

Transaction isolation level

TRANSACTION_READ_UNCOMMITTED

Transaction attribute

TX_SUPPORTS

Run-as mode

CLIENT_IDENTITY

 

 

 

 

The Quote Stateful Session Bean

The Quote Line Item bean we have just written represents a single product the user is interested in purchasing. The next session bean we’ll write is the complement of this—a Quote bean. A quote acts as a shopping cart, holding many product selections the user has made. As the user traverses the Web site, he or she adds or removes goods from the quote. Our Quote bean will use the Quote Line Item bean we just made to represent each product the user wants.

Each customer who’s logged in should have his or her own temporary and separate quote to work in. Therefore, our quotes will need to hold client-specific state in them. They should not be persistent because the user can always cancel the quote. These requirements naturally lend themselves to the stateful session bean paradigm.

Our Quote bean will contain the following information:

■■The Customer (entity bean), who we authenticated at the login screen. We need to store the Customer so that we know who to bill, what discounts to apply, and where to ship the manufactured products.

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