Declaring the Component Interface

   

As with entity beans, a client's view of a session bean is defined by the bean's component interface. Remember that a remote interface must always be declared to extend EJBObject and a local interface must extend EJBLocalObject . As illustrated previously with entity beans, the remote and local interfaces are where you define the business methods you want to expose to clients of your beans. Again, these methods must be declared such that

  • No method name starts with ejb

  • All methods are declared as public

  • No method is declared as static or final

  • All remote interface methods include java.rmi.RemoteException in their throws clauses

  • All remote interface method arguments and return types must be legal RMI-IIOP types

Note

The requirements for legal RMI-IIOP types span five pages in OMG's "Java Language to IDL Mapping" document. However, in general, the legal RMI-IIOP types include the Java primitives, remote interfaces, serializable classes, arrays that hold objects of a legal type, and checked exceptions. You can download this document from OMG at http://www.omg.org/cgi-bin/doc?ptc/00-01-06 if you want a more precise description.


Work can be done through a session object after a client obtains a reference to its component interface. A client with a reference to a session object's component interface can

  • Call the session object's business methods

  • Call remove to remove a stateful session object

  • Obtain the session object's handle (only done by remote clients using getHandle )

  • Obtain a reference to the session object's home interface (using getEJBLocalHome or using getEJBHome )

  • Pass the reference as a parameter or return value of a method call (limited to local methods when using the local interface)

Caution

Even though a session bean's remote interface must extend EJBObject , a client should never call the getPrimaryKey method for a session bean. Calling this method will result in a RemoteException . Similarly, calling getPrimaryKey on EJBLocalObject for a session bean results in a javax.ejb.EJBException .


Comparing Object Identity

The component interface, and its isIdentical method in particular, offers some insight into how the container views session bean instances. Unlike entity beans, session beans are intended to be anonymous to the client. This is why they don't have an identity that's exposed to the client through a primary key. However, each session object is in fact assigned an identity by the container when it's created. The meaning and behavior of this identity differ depending on what type of session bean you're talking about. Because each stateful session bean instance is different due to the state it holds for its client, each instance is assigned a unique identity by the container when the instance is created. The behavior is somewhat different for stateless session beans. Each stateless session bean object created from the same home factory has the exact same identity. This is because stateless session bean instances should be interchangeable as far as both the client and the container are concerned .

Note

It's not common, but you're allowed to deploy the same session bean into the container more than once under a distinct home factory. When you do this, the container assigns a different unique identity to each home deployment. Otherwise, all instances of a particular stateless session bean in a given container will have the same identity assigned to them when they're created.


Testing whether one session object is identical to another is done the same way regardless of whether it's a stateful or stateless session bean. To test whether session beans are identical, you should use the isIdentical method defined by the EJBObject and EJBLocalObject interfaces. The isIdentical method takes a single argument, which is the corresponding remote or local interface of the object to which you're making the comparison. Although the same method is used for both stateful and stateless session beans, its result depends on which one you're using.

Using isIdentical with Stateful Session Beans

Because each stateful session bean instance is created for a specific client, references to session objects of this type are identical only if they point to the object that was created in response to the same client request. Remember that the container assigns a unique identity to each stateful session bean instance. It's this identity that's being used for the comparison. To illustrate this behavior with an example, the following code fragment declares references to two unique stateful session objects:

 // Obtain a reference to a stateful session bean's home interface  AuctionCheckoutHome checkoutHome = ...;  // Create two different stateful session objects  AuctionCheckout checkout1 = checkoutHome.create();  AuctionCheckout checkout2 = checkoutHome.create(); 

If you then execute the following test using the checkout1 and checkout1 remote interface references the if statement returns false because each stateful session bean instance has a unique identity so that no two are identical:

 // This test would return false  if ( checkout1.isIdentical( checkout2 ) ) {   ...  } 

If you instead execute this test, it returns true because the stateful session bean instance and itself have the same identity, by definition:

 // This test would return true  if ( checkout1.isIdentical( checkout1 ) ) {   ...  } 
Using isIdentical with Stateless Session Beans

The behavior of isIdentical for stateless session beans is the same as that for stateful when a reference is compared to itself. However, the results change when two different instances from the same home are compared. If the preceding example is repeated for two stateless session using the following code fragment:

 // Obtain a reference to a stateless session bean's home interface  AuctionHouseHome auctionHouseHome = ...;  // Create two different stateful session beans  AuctionHouse auctionHouse1 = auctionHouseHome.create();  AuctionHouse auctionHouse2 = auctionHouseHome.create(); 

and you execute the following test:

 // This test would return true  if ( auctionHouse1.isIdentical( auctionHouse2 ) ) {   ...  } 

it returns true because all instances of a stateless session bean from the same home factory have the same unique identity and are considered to be identical.

The Auction Component Interfaces

For the auction example, the session beans identified in Table 9.1 provide the interface to the Web tier . This means that they must be written and deployed to support remote clients. Listing 9.1 shows a remote interface declaration that could be used for the auction house stateless session bean.

Listing 9.1 AuctionHouse.java “A Remote Interface for an Auction House Session Bean
 package com.que.ejb20.auction.controller;  /**   * Title:        AuctionHouse<p>   * Description:  The EJB remote interface for the AuctionHouse bean<p>   */  import java.util.List;  import java.rmi.RemoteException;  import javax.ejb.EJBObject;  import javax.ejb.FinderException;  import com.que.ejb20.auction.exceptions.InvalidAuctionStatusException;  import com.que.ejb20.auction.exceptions.InvalidBidException;  import com.que.ejb20.auction.view.AuctionDetailView;  public interface AuctionHouse extends EJBObject {   /**     * Return a list of all open, closed, or cancelled auctions     *     * @return a List of AuctionSummaryView objects     */    public List getNonPendingAuctions() throws RemoteException;    /**     * Return a detailed description of a specific auction     *     * @param auctionId the primary key for the selected auction     * @return a description of the auction and its offered item     */    public AuctionDetailView getAuctionDetail(int auctionId)      throws FinderException, RemoteException;    /**     * Submit a bid to an open auction     *     * @param bidAmount the amount bid     * @param auctionId the primary key for the selected auction     * @param bidderId the primary key for the bidder     *     */    public String submitBid(double bidAmount, int auctionId, int bidderId)      throws InvalidBidException, InvalidAuctionStatusException, RemoteException;    /**     * Return a list of BidView objects describing all bids submitted by a bidder     */    public List getBids(int bidderId) throws FinderException, RemoteException;  } 

This example of a remote interface shows the minimum set of business methods that the auction house session bean would need to provide. As defined here, the AuctionHouse interface allows a client to get a list of auctions, get detailed information about a single auction, submit a bid, and get a list of bids submitted by a particular user . The application exceptions referenced by the methods, InvalidAuctionStatusException and InvalidBidException , and AuctionDetailView were declared previously in Chapter 5. For an actual site, you would likely supply other functionality such as displaying information to a bidder about all the auctions that had been participated in or displaying a summary of all the bids submitted on a particular auction.

The getNonPendingAuctions method of the AuctionHouse interface uses a view class to return information about particular auctions using a simple data structure. Listing 9.2 shows this class, which is appropriate for summarizing an auction's state.

Listing 9.2 AuctionSummaryView.java “A Summary Description of an Auction
 package com.que.ejb20.auction.view;  /**   * Title:        AuctionSummaryView<p>   * Description:  Summary view class for an English Auction suitable for   *               building a list of defined auctions<p>   */  import java.io.Serializable;  import java.sql.Timestamp;  public class AuctionSummaryView implements Serializable {   private Integer id;    private String name;    private String status;    private Double leadingBidAmount;    private Timestamp scheduledEndDateTime;    public AuctionSummaryView() {   }    public AuctionSummaryView(Integer newId, String newName, String newStatus,     Timestamp newScheduledEndDateTime, Double newLeadingBidAmount) {     setId(newId);      setName(newName);      setStatus(newStatus);      setScheduledEndDateTime(newScheduledEndDateTime);      setLeadingBidAmount(newLeadingBidAmount);    }    public Integer getId() {     return id;    }    public void setId(Integer newId) {     id = newId;    }    public void setName(String newName) {     name = newName;    }    public String getName() {     return name;    }    public void setStatus(String newStatus) {     status = newStatus;    }    public String getStatus() {     return status;    }    public void setLeadingBidAmount(Double newLeadingBidAmount) {     leadingBidAmount = newLeadingBidAmount;    }    public Double getLeadingBidAmount() {     return leadingBidAmount;    }    public void setScheduledEndDateTime(Timestamp newScheduledEndDateTime) {     scheduledEndDateTime = newScheduledEndDateTime;    }    public Timestamp getScheduledEndDateTime() {     return scheduledEndDateTime;    }  } 

Returning objects, such as AuctionSummaryView and AuctionDetailView , instances from the methods of AuctionHouse provides a separation between the clients of this data and the objects that maintain it. As discussed in the beginning of this chapter, a client rarely interacts directly with an entity bean. The preferred approach is for clients to go through session bean methods and work with entity beans indirectly. This tends to make a client's use of an entity more coarse-grained. A client often needs to perform multiple fine-grained operations on an entity object.

Think about how you update the state of an object or retrieve it for display. It's likely that you want to update or retrieve multiple attributes as part of a single action, which could lead to multiple calls on an entity from a client. Encapsulating a related set of entity bean calls in a session bean method simplifies the transaction management of an entity update, and it also can reduce the network traffic required to set or retrieve multiple attributes. If your clients don't call your entities directly, you need a means of passing the associated data between a client and a session bean. View classes provide a way for session beans to expose the data associated with an entity without directly exposing the entity to a client.

You can declare view classes to support the various ways clients of your application need to interact with an entity's data without having any impact on the interface supported by the entity bean. As long as the entity exposes all the information that's important to its clients, its implementation doesn't need any knowledge of how its data is pieced together for use by the applications that are built using it. This use of view classes also lends itself to entity reuse as well. If an entity provides all the data and business logic that are appropriate for the business object it's modeling, you can reuse it by defining additional view classes that can be supported by your session beans to build new applications. Remember that session beans can be thought of as extensions to your application clients. This means that it's acceptable for session beans to have application-specific knowledge.

You have several options when defining view classes like AuctionSummaryView and AuctionDetailView . The approach selected here was to use a JavaBean with accessor and mutator methods for each attribute. This makes them easy to use in a variety of clients, such as JSP pages. Another option is to use a simple data structure that declares all its attributes as public without providing any methods at all. This approach emphasizes the fact that classes like these are for passing data and not implementing business logic. Yet another option is to declare a view class as immutable by providing get methods and a constructor that accepts values for all the attributes but no set methods. You just need to consider the types of clients you're trying to support when you design the interface presented by your session beans.

You might remember from Chapter 5 that the auction entity bean declares a getAuctionDetail method in the EnglishAuction local interface that returns an AuctionDetailView . This view is somewhat generic in that it contains a complete copy of an auction's attributes. AuctionSummaryView is quite different in that it includes a subset of data that reflects a particular client need. Because AuctionSummaryView is client-specific, it isn't appropriate for the entity bean to have any knowledge of this view class or be able to generate an instance of it. Client-specific views are better generated by session beans or their helper classes. This helps keep your entity beans immune to changing client requirements.

The administrative functions for auction maintenance belong in the AuctionManager interface. Listing 9.3 shows a simple version of this interface with a representative set of methods.

Listing 9.3 AuctionManager.java “A Remote Interface for an Auction Manager Session Bean
 package com.que.ejb20.auction.controller;  /**   * Title:        AuctionManager<p>   * Description:  The EJB remote interface for the AuctionManager bean<p>   */  import java.rmi.RemoteException;  import java.util.List;  import javax.ejb.CreateException;  import javax.ejb.EJBObject;  import javax.ejb.FinderException;  import com.que.ejb20.auction.exceptions.InvalidAuctionStatusException;  import com.que.ejb20.auction.view.AuctionDetailView;  public interface AuctionManager extends EJBObject {   /**     * Create a new auction and return it's primary key     */    public Integer createAuction(AuctionDetailView view) throws CreateException,      RemoteException;    /**     * Assign an item to be auctioned     */    public void assignItemToAuction(Integer auctionId, Integer itemId,      int quantity) throws InvalidAuctionStatusException, FinderException,      RemoteException;    /**     * Get a view of the auction's state     */    public AuctionDetailView getAuctionDetail(int auctionId)      throws FinderException, RemoteException;    } 

Listing 9.4 shows a remote interface for a stateful session bean that might be used to manage the order entry process for an auction win. What you should notice here is that there's nothing about a session bean's component interface that indicates whether the bean is stateful or stateless.

Listing 9.4 AuctionCheckout.java “A Remote Interface for a Stateful Session Bean Used to Complete an Auction Order
 package com.que.ejb20.auction.controller;  /**   * Title:        AuctionCheckout<p>   * Description:  Remote interface for the Auction Checkout   *               stateful session bean<p>   */  import java.rmi.RemoteException;  import javax.ejb.EJBObject;  import com.que.ejb20.auction.view.AddressView;  public interface AuctionCheckout extends EJBObject {   public void setBidder(int bidderId) throws RemoteException;    /**     * Attach the item from an auction to an order     *     * @param auctionId the primary key for the selected auction     */    public void addAuctionWinToOrder(int auctionId) throws RemoteException;    /**     * Supply a shipping address for the order     *     * @param shippingAddress the address to use for this order     */    public void updateShippingAddress(AddressView shippingAddress)      throws RemoteException;    /**     * Select a shipping carrier and method     *     * @param carrierId an identifier for the shipping carrier     * @param priorityId an identifier for the shipping method     */    public void selectShippingMethod(int carrierCode, int priorityCode)      throws RemoteException;    /**     * Submit the order     */    public void completeOrder() throws RemoteException;  } 


Special Edition Using Enterprise JavaBeans 2.0
Special Edition Using Enterprise JavaBeans 2.0
ISBN: 0789725673
EAN: 2147483647
Year: 2000
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net