G |
Session Beans |
|
Get |
Get |
Example: The Rock Survey, Take 1 |
At this point, you should take a moment to look over The Rock Survey Application, because we will revisit it several times in the course of the tutorial. As you can see, the application requires that data be maintained across four Web pages, so a stateful session bean is the right choice to manage and maintain state and data. In this first go around, the data is not actually persisted anywhere after the client completes the survey; we'll handle that in later iterations. In anticipation, the persist() method exists, but for the moment it does nothing more than return true.
The RockSurveyBean maintains and validates Rock Survey data, and returns a data object that also contains any error information for the client's use. As with the stateless session bean example, RockSurveyBean implements the SessionBean interface. Let's take a look:
import javax.ejb.*;
public class RockSurveyBean implements SessionBean
{
...
public RockSurveyBean() {} // end constructor
// required by the specification contract
public void ejbCreate() {} // end ejbCreate
// required for SessionBean implementation
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext sc) {}
...
} // end class RockSurveyBean
For the Rock Survey application, only remote interfaces are defined. The extension of the remote home interface is very basic, with only one create() method:
import javax.ejb.*;
import java.rmi.RemoteException;
public interface RockSurveyRemoteHome extends EJBHome
{
// required
RockSurveyRemote create()
throws RemoteException,
CreateException;
} // end RockSurveyRemoteHome
The create() and remove() methods, except for the name of the bean (and the component interface returned from create()), are identical to those for the client in Example: A Metric Conversion Program. There are two things to note in the application:
jspInit() and destroyed in jspDestroy(), each of which occurs exactly once in the life of a servlet. That's because the application made use of the same bean (from its perspective) for the life of the application. Here, a stateful session bean is allocated to, and tracks state for, the duration of the entire conversation for each individual client, by definition. For that reason, on the first page the code checks if the servlet session object was newly created, and, if so, creates a new RockSurveyBean. The bean is destroyed when the session is invalidated at the end of the survey.
RockSurveyBean as the user moves from page to page. To resolve this issue, the bean reference is stored in and retrieved from the servlet's session object.
Next up is the remote component interface:
import java.rmi.RemoteException;
import javax.ejb.*;
public interface RockSurveyRemote extends EJBObject
{
public RockSurveyData getData()
throws RemoteException;
public boolean persist()
throws RemoteException;
public RockSurveyData setUserData(
String sGenderIn, String sLastNameIn,
String sMaritalIn, String sPostalIn )
throws RemoteException;
public RockSurveyData setRockData(
String sCountIn, String sLocationIn,
String sMeasureIn, String sPreferenceIn,
String sWeightIn )
throws RemoteException;
} // end RockSurveyRemote
Notice that the component interface for RockSurveyBean only exposes those methods the client needs to get, set, and persist the data. RockSurveyData is a helper class that effectively contains a read-only copy of the data, with a complete set of getXXX() methods, and any information about errors. Because the data is gathered over several pages, there are two setXXX() methods — one for general user information, the other for the actual survey data. The RockSurveyData class always returns all of the currently available data.
You may wonder why I went to the trouble of creating the RockSurveyData class when all of the information is available from RockSurveyBean. The answer has to do with a topic you will hear much discussed in EJB developer circles: fine-grained versus coarse-grained access. The classic example of fine-grained access is a data object representing a row with, say, 50 columns and having 50 getters and 50 setters. A coarse-grained version might return the entire row or multiple rows from one method.
Because the Rock Survey uses remote interfaces, RockSurveyBean is a remote component, which means each method invocation is a distributed call, as discussed earlier. Fine-grained access with distributed calls is a performance killer. Since Web page data retrieval is inherently page oriented, RockSurveyBean's get and set methods are oriented toward a page of data. The RockSurveyData class is the vehicle to carry the data in a coarse-grained manner. Once the application has a RockSurveyData instance, it can call getXXX() as usual, but against a local object, avoiding performance hits as much as possible.
|
|