Designing EJB Classes and Interfaces

   

Managing Client Access

Designing the EJBs that support your applications requires you to focus on the business logic they implement and the goals that you have for maintainability. You also must take into account how the clients of your EJBs will interact with them. This includes deciding on the methods that you'll expose through the home and component interfaces of your beans, but it doesn't stop there. This section looks more at how the data that's passed between an EJB and its clients is packaged and how a client manages its interaction with an EJB.

Session Bean Fa §ade

Entity beans represent your business's core concepts. Conceptual entities such as customer, purchase order, and catalog are common in business applications deployed over the Internet. Entity beans are sometimes coarse-grained in terms of the overall functionality they provide but it's also typical for them to provide fine-grained access to their attributes using such operations as setCustomerName , getCustomerName , setOrderNumber , and getOrderNumber . This fine-grained support is necessary, but enterprise beans are distributed objects, so populating them from a remote client is an expensive operation performance-wise. You'll see more of this discussed in Chapter 17, "Addressing Performance."

It's also true that the work required by a client often involves multiple entity objects. A client might request the attributes of a single entity, such as those for an item in a catalog, but it's also common for clients to request operations such as viewing summary attributes for many items or creating an order entity and adding an item to it. For most actions a client needs, especially a thin client in a Web application, some coordination of objects usually must take place. This is the workflow management of an application.

To manage workflow and to reduce fine-grained access to entity beans, it's common to force a client to go through a session bean rather than allow it to interact with entity beans directly. This approach is sometimes referred to as the "Session Bean Wraps Entity Bean" pattern. The idea is that session beans should define coarse-grained methods that clients use to exercise the business logic they require and the access granularity between session and entity beans can be adjusted due to the introduction of local interfaces.

Typically, session beans are deployed with a transaction attribute of Required assigned to their methods so that the container starts a transaction at the beginning of each method to include all the work it performs . When one of these methods is called, the session bean interacts with one or more entity beans on behalf of the client, possibly using a local interface. This might involve creating or finding several entity objects and calling one or more business methods on them. The entity bean methods that are involved should normally have their transaction attributes set to Required as well so that they participate in the session bean's transaction. Direct access of the entity beans by a client would require the client to start and stop its own transactions or it would result in the client's work being spread across multiple transactions with no simple way to roll anything back if a problem occurred. Grouping this work within a session bean method avoids either of these undesirable alternatives.

Returning View Objects to the Client

There's not really a common name for this next strategy. What it recommends is that your session beans return simple data objects back to the client rather than remote interface references. These data objects are referred to as views because they represent a particular view of the underlying model maintained by the application tier .

For example, say that a client invokes a getNonPendingAuctions method on the AuctionHouse session bean. An entity object is associated with each auction in the database, so the session bean could return a collection of remote interfaces to the client. What this strategy suggests instead is that a collection of AuctionSummaryView objects be returned. A view class such as this is very thin and contains only data validation or formatting logic if any. The idea is that there's enough information in a view class to build the presentation view for an end user or satisfy whatever other need a client of a particular session bean method has. In this case, AuctionSummaryView would contain the high-level attributes needed to build a list of auctions. If the user selects an entry from this list and requests to see more detail, the getAuctionDetail operation could be invoked and an AuctionDetailView returned back to the client containing all of the auction's attributes.

There's always a tradeoff between controlling the number of network calls and controlling the amount of data returned with each call. This example of generating a summary list that supports selective displays of detailed information is quite common in practice. In this scenario, a client typically selects only a small number of the entries in the list for detailed viewing. Sending back a collection of remote interfaces from which to build the list is a heavyweight solution, especially given that many of the list entries would likely never be used. Returning a set of regular Java classes that the client uses to build the presentation screen and then releases for garbage collection is a much more efficient approach. Listing 16.4 shows a view class that represents a user's bid in an auction.

Listing 16.4 BidView.java “The View Class for a User's Bid
 package com.que.ejb20.auction.view;  /**   * Title:        BidView<p>   * Description:  Value object for an auction bid<p>   */  import java.io.Serializable;  import java.sql.Timestamp;  public class BidView implements Serializable {   private Integer auctionId;    private Integer bidderId;    private Timestamp dateTimeSubmitted;    private String transactionId;    private Double amount;    public BidView(Integer newAuctionId, Integer newBidderId,     Timestamp newDateTimeSubmitted, Double newAmount, String newTransactionId) {     setAuctionId(newAuctionId);      setBidderId(newBidderId);      setDateTimeSubmitted(newDateTimeSubmitted);      setAmount(newAmount);      setTransactionId(newTransactionId);    }    public Integer getAuctionId() {     return auctionId;    }    public void setAuctionId(Integer newAuctionId) {     auctionId = newAuctionId;    }    public Integer getBidderId() {     return bidderId;    }    public void setBidderId(Integer newBidderId) {     bidderId = newBidderId;    }    public Timestamp getDateTimeSubmitted() {     return dateTimeSubmitted;    }    public void setDateTimeSubmitted(Timestamp newDateTimeSubmitted) {     dateTimeSubmitted = newDateTimeSubmitted;    }    public Double getAmount() {     return amount;    }    public void setAmount(Double newAmount) {     amount = newAmount;    }    public String getTransactionId() {     return transactionId;    }    public void setTransactionId(String newTransactionId) {     transactionId = newTransactionId;    }  } 

A view class usually doesn't contain any business logic because its purpose is simply to transfer data between the application tier and the client. It might contain data validation or formatting logic, though. For example, when a user enters a bid for an auction and then clicks the submit button, it might be useful for the BidView class to contain some formatting logic to format the bid amount into a particular currency before passing it to a session bean. However, it's better to keep a view class as thin as possible and leave the business logic in the session and entity beans.

Changes a client makes to a view are not reflected in the underlying data used to generate the view. Changes are usually made through session bean methods by passing view objects as arguments to a session bean. The view objects are used to update the corresponding entity bean from the session bean methods.

Tip

Although the BidView class could have been declared without any set methods to make it clear that it can't be used to update any data, it might be necessary to provide set methods if your client tier uses JavaServer Pages. For an instance of the BidView class to function properly using JSP, it must follow the JavaBeans specification and provide both set and get methods for properties that a client wishes to access.


Referencing Home and Component Interfaces in the Client

A client communicates with an enterprise bean by obtaining an object that implements the bean's home interface and then acquiring a component interface reference. Regardless of whether the client is a JSP page, a servlet, or another enterprise bean, the procedure is similar. One question that soon arises related to this topic is over which of the references, if any, a client should hold between calls to the application tier. It seems intuitive that it would be to your advantage to avoid repeating the same steps to acquire a reference to an EJB, but it's not always clear what steps need to be done only once. You have several choices of what to do:

  • Look up the home interface and acquire a component interface reference as part of each client invocation of an EJB method

  • Hold the home interface reference in the client and acquire a component interface reference for each call to an EJB

  • Hold the component interface reference in the client

  • Hold a handle to a home or remote interface in the client and use it to reacquire the necessary reference

Note

The local component interface does not support the concept of a Handle . It is only used for remote clients.


The home object is a class that's generated by the container to implement the home interface for an enterprise bean. As you've learned from previous chapters, it's a factory that is responsible for creating (and finding, in the case of entity beans) objects that implement the component interface of the associated bean. These are the stub objects. When a client calls a create or finder method on a home interface reference, several things must happen depending on the type of bean and its current state. One thing to remember is that the home factory giving you a component reference doesn't mean that there is an EJBObject or EJBLocalObject created on the server right at that moment. The server can delay some operations to help with performance. For example, it can delay creating an EJBObject for a remote client until the client actually invokes an operation on the remote interface. With other vendors , all remote clients might actually share an EJBObject that's used for routing all client requests as an aid to scalability of the EJB server.

Note

Don't confuse the concept of sharing an EJBObject with sharing bean instances. A bean instance is only assigned to one client at a given time. It may be shared between client invocations, but two clients are not associated with the same bean instance at the same time.


The lookup of the home interface through JNDI can be quite costly, so you'd like to limit the number of times a client has to perform this operation. The problem is that there's not much guidance from the specification as to how to handle clients caching home and component interfaces. However, there might be a reason to not cache the home interface reference and use it for all clients. The reason is one of security. Several EJB products use the security principal and credential that are used for the JNDI lookup of the home interface as the security principal that is propagated to the container during a method invocation. Although these sets of security contexts are supposed to be used for very different reasons, it still happens. Authentication into JNDI and authentication to the enterprise beans should be handled by completely different mechanisms. However, you should keep in mind that JNDI authentication is still sometimes used as the identity of the caller that gets propagated to the EJB container.

You can still cache the home interface for each client session, but this makes sense only if you plan to remove the component interface reference to the enterprise bean after each call. This is not recommended because the component interface reference is designed to have a lifetime equal to that of a user session. In other words, the component interface reference for an EJB is what you want to cache for each client rather than a home interface reference. Each client can have its own component interface reference and somehow store it where it can be associated with a particular user. For example, in a Web application, it can be stored in the HttpSession for each user. When the user needs to invoke a method on it, the application gets the component interface reference for that particular user and calls the method.



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