EJB Component Types


The EJB 2.0 specification defines the following types of EJB components :

  • Stateless session bean (SLSB)

  • Stateful session bean (SFSB)

  • Entity bean

  • Message-driven bean (MDB)

Each of these component types fulfills a different design requirement for enterprise-class distributed systems. The following sections review each of these types and look at a few simple examples to complete our discussion of EJB key concepts.

Stateless Session Beans

Stateless session bean (SLSB) components are designed to service requests using a classic stateless request/response style. Setting aside complexities related to bean life cycle and pooling, an SLSB is not unlike a shared static class used as a service (like the PersonService class in Chapter 2). The SLSB has a set of methods , exposed through local or remote interfaces, that can be called by clients to request particular services. Data is passed to the SLSB methods using method parameters, and results are returned, typically, through the return type of the method. This is classic request/response design.

Generally speaking, SLSB components are suitable for encapsulating business processes rather than business data. SLSB components often have names like AccountingService or ContractManager , signifying their role as managers or services related to certain business domains. Method names normally make clear the particular service exposed by the interface:

 AccountingServiceLocal aservice = ... // Obtain reference to SLSB float tax =  aservice.calculateTax(income, expenses);  System.out.println("The IRS is only taking $" + tax + " this year!"); 

SLSB components have distinct advantages over simple static classes:

  • EJB developers do not have to write thread-safe code. The EJB container prevents more than one thread in a given bean instance.

  • EJBs provide location transparency in that they can be invoked from other processes.

  • Transaction control and security constraints are implemented by the EJB container and declared using standard descriptor elements. Transaction and security contexts are automatically propagated to SLSB methods without requiring extra method parameters, a common approach in a static class.

Clients are given a particular instance of the SLSB for use during the single request/response cycle, and there is no guarantee that subsequent requests from the same client will be handled by the same instance of the SLSB. In general, SLSB components should not have client-associated instance variables, although it is possible to use instance variables to cache connections to shared resources or shared read-only data if desired. Just recognize that each invocation to the SLSB is independent from past and future invocations from the same client, and you can t make assumptions about the contents of the instance variables .

SLSB components are often used to implement the session fa §ade design pattern discussed briefly in Chapter 3. The business process encapsulated by the SLSB may include complex calculations and interactions with additional EJB components, including both SLSB and entity beans, and the single method defined on the SLSB provides a simplifying fa §ade for this complex process. The SLSB-based fa §ade also provides a convenient mechanism for ensuring transactional integrity. The container is often configured to require or create a transaction whenever the SLSB method is invoked, thereby ensuring that all operations in the method are part of the same transaction.

We ll make use of SLSB and the session fa §ade pattern in the example application in Chapter 7 for selected business processes requiring complex calculations and interactions with multiple EJB components.

Stateful Session Beans

Stateful session bean (SFSB) components combine the request/response mechanism of stateless session beans with the storage of state information between method invocations. Clients are given a dedicated instance of the SFSB to use for multiple method invocations, and subsequent requests from the same client are guaranteed to be handled by the same instance of the SFSB bean. These beans should generally have instance variables that store the intermediate state of the process being modeled by the SFSB. If there are no instance variables, there s no reason to use a stateful session bean.

SFSB components are normally used to implement multistep business processes that require retention of state information from step to step. They fall somewhere between SLSB and entity beans in terms of function and naming, and they often have names like Reservation or ReservationProcess . Method names on SFSB components also tend to fall somewhere between SLSB and entity beans, and they may have set methods for updating the state information in the bean as well as methods that perform business processing:

 ReservationLocal rez = ... // Obtain reference to SFSB component rez.setProperty(...); ... rez.setDates(...); ... rez.setGuestInformation(...); ... String confirmnum = rez.performBooking(); System.out.println(Your confirmation number is:  + confirmnum); 

In this example code, we ve used an SFSB to maintain information about the customer s selections during the reservation process before invoking the final performBooking() method to make the reservation. The set method invocations are shown as if they occurred in the same block of code, but this is not required. As long as the client holds on to and uses the same SFSB reference, the invocations will be processed by the same instance of the SFSB.

Note that the bigrez.com example application, introduced in Chapters 3 and 4, uses a value object placed in the HttpSession to store intermediate results and passes this value object to a method on a stateless session bean to perform the final booking. Essentially , we store the intermediate data in the session rather than just storing a reference to a client-specific SFSB. Both techniques are viable ways to achieve the same effective result, and the choice is up to the architect. When the client is a Web application, we tend to lean toward the HttpSession approach for the simple reason that SFSB components increase the complexity of the overall system and may introduce unnecessary transaction and security processing mandated by the EJB specification. SFSBs really are more appropriate for maintaining a client s server-side state for remote clients ”that is, clients not in the same JVM.

WebLogic Server includes the replication of SFSB data in a cluster, a topic discussed later, so both techniques have the same failover capability as well. When you try to use an SFSB from a Web application client where both the HttpSession and the SFSB are using in-memory replication, the failover scenarios can get a little bit complex. As a result, we tend to recommend using HttpSession objects to hold client session state for Web applications and SFSB only for applications where the client is not a Web application.

Best Practice  

Avoid using stateful session beans for Web application client data more readily stored in the HttpSession . Although both SFSB and HttpSession data are replicated for failover in WebLogic Server, complexity considerations favor the use of HttpSession storage when possible. Use an SFSB for situations where the client is not a Web application.

You should consider three issues with stateful session beans before using them:

  • SFSB components normally disallow concurrent access, although WebLogic Server does include a flag to allow concurrent invocations to block rather than cause an exception. In a Web application multiple requests from the same user may be processed simultaneously , a condition that might require simultaneous access to the client-associated SFSB.

  • If an SFSB throws a RuntimeException the container destroys the instance of the bean and all associated state information is lost, as required by the EJB specification.

  • SFSB components are not appropriate for long- term storage of state. Use entity beans to store data that must survive the client restarting the browser session or returning to the application after an extended period of time.

While there may be specific applications for which the SFSB component is well suited, it is generally best to use HttpSession objects for short-lived, client-specific data and entity beans or other database- backed storage for long-lived data.

Entity Beans

Entity bean components are designed to encapsulate state information and manage the persistence of that state information. Entity beans seem straightforward on the surface: Clients obtain a reference to an entity bean instance representing some persistent business data and invoke get and set methods on the bean to interact with the data. When the client is done with the bean, any changes in state are flushed back to the persistent store. What could be simpler?

The reality is bit more complicated, of course. Before we dive in and review some entity bean details, let s examine the steps in this simple scenario to begin identifying the required methods in an entity bean from the developer s point of view:

  1. First, obtaining a reference to the proper entity bean instance is normally accomplished using a finder method. Finder methods, defined in the home interface and implemented in the bean class, may look up beans by primary key or by any other criteria. Finder methods may return single bean references or collections of beans.

  2. Next , the client interacts with the bean instance using get and set methods or any other methods defined on the bean s interface. The bean state must be loaded from the persistent store before the methods are called, a task that the container either performs itself or tells the bean class to perform by invoking the ejbLoad() method defined in the bean class. Method invocations may alter the state information in the bean instance, and subsequent calls to the same instance will reflect these changes.

  3. Finally, when the client is done with the bean, its contents are flushed back to the persistent store, either automatically by the container or by the container telling the bean to do it via the ejbStore() method defined in the bean class.

Notice that two different mechanisms are used to load and store bean data. These operations are performed automatically by the container, a technique known as container-managed persistence, or by calling methods in the bean class, an option known as bean-managed persistence. The next two sections will describe and contrast these options in more detail.

This simple scenario does not include the creation of a new entity bean or the deletion of one. Once again, the exact mechanism depends on the bean s chosen persistence mechanism. For container-managed persistence (CMP), the container does these automatically; for bean-managed persistence (BMP), the container tells the bean to do it via the ejbCreate() and ejbRemove() life-cycle methods on the bean class.

That s it! From a developer s point of view, entity beans require only a small set of methods on the bean class to perform all of the functions required to encapsulate business data in the entity bean. There are additional life-cycle methods, such as ejbActivate() and ejbPassivate() , required by the EJB container to help manage bean life cycles and instance pooling. Often, these methods do not require any bean-specific code and are defined or stubbed out in a common base class. Table 6.1 outlines the minimum required methods for entity beans and summarizes their role in the process.

Table 6.1:  Methods Required in Entity Bean Classes
start example
end example
 

METHOD

CMP DESCRIPTION

BMP DESCRIPTION

ejbCreate(...)

Implementations of the create methods defined on the home interface. Used to initialize the bean attributes (by calling the set methods) before the container inserts them into the database. The CMP bean must not manipulate the container-managed relationship fields until ejbPostCreate() .

Implementations of the create methods defined on the home interface. Used to initialize the bean attributes (by calling the set methods) and insert the data into the database.

ejbPostCreate(...)

Matches the ejbCreate (...) method. Called by the EJB container after the bean instance has been associated with a primary key and an EJBObject . Normally used to set relationship attributes because these may require the EJBObject reference.

Same as CMP.

ejbFind XXX(...)

Implementations of the finder methods defined on the home interface. Used to obtain a reference to a single bean or a collection of beans matching the desired criteria. Automatically generated by the container from the deployment descriptors.

Implementations of the finder methods defined on the home interface. Used to obtain a reference to a single bean or a collection of beans matching the desired criteria. Must be written to perform the appropriate SQL SELECT statement to return the matching bean(s).

ejbLoad()

Called by the EJB container just after the bean s state has been read from the database. Can be used to modify the representation of the data before methods are invoked.

Called by the EJB container when an instance should read its state information from the persistent store. Must include the necessary SQL SELECT statement code to read data from the database and update the bean attributes to match the database state.

ejbRemove()

Called by the EJB container just before it removes the bean from memory.

Called by the EJB container when an instance should remove itself from the persistent store. Must contain the appropriate SQL DELETE statement code to remove the bean s data from the database.

ejbStore()

Called by the EJB container just before the bean s state will be written back to the database. Can be used to modify the data representation before it is saved to the database.

Called by the EJB container when an instance should save its state information to the persistent store. Must include the appropriate SQL UPDATE statement code to save the bean s current state to the database.

ejbPassivate()

Called by the EJB container just before the bean is passivated because of inactivity or a lack of resources in the bean instance pool.

Same as CMP.

ejbActivate()

Called by the EJB container after the bean is reactivated from a passive state.

Same as CMP.

setEntityContext()

Called by the EJB container at the beginning of the bean life cycle to provide context information.

Same as CMP.

unsetEntity

Context()

Called by the EJB container at the end of the bean life cycle just prior to removal from the bean pool.

Same as CMP.

Attribute Get and

Set Methods

Requires abstract get and set method declarations rather than attribute definitions. The container will generate the actual concrete bean class.

Optional. The bean can do whatever it wants because it controls its own state.

ejbSelect XXX()

Optional. Only for internal use in the bean class and never exposed directly via remote or local interfaces. Methods are automatically generated from deployment descriptors.

Not applicable .

ejbHome XXX()

Optional. Allows adding stateless methods to a bean s home interfaces that return something other than bean references to the current bean. Methods are automatically generated from deployment descriptors.

Optional. Allows adding stateless methods to a bean s home interfaces that return something other than bean references to the current bean. Must include any

SQL code necessary to process the request. Must not access any bean instance variables.

In addition to the required methods in Table 6.1, entity bean classes may include get and set methods for attributes (required for CMP), additional methods allowing clients to request data in other forms such as XML or Composite Value Objects , and home and select methods introduced in the EJB 2.0 specification. We ll build some typical entity beans later in this chapter as examples, and there are some example beans available in the samples installed with the WebLogic Server product. There are also many good books available on EJB with examples of simple entity beans.

Building simple entity beans is not very difficult. The real challenge is building high-performance entity bean applications for complex, realistic business models with many interrelated business objects. The entity bean life cycle that works so well in theory breaks down when you re trying to achieve high transaction rates with complex graphs of business objects unless you are careful to optimize the process using proper transactional controls and all of the tools and features available in your EJB container. As you ll learn when we examine some of the latest features of the WebLogic Server EJB container, achieving high performance with entity beans is all about understanding the bean access patterns, caching, and efficient queries. Features that reuse cached instances of beans and combine multiple operations in a single database invocation yield big performance gains.

We will cover many advanced topics and WebLogic Server-specific features related to entity beans in this chapter. Before we do, however, we need some straightforward entity beans as a foundation for these discussions. Therefore, we ll examine some simple entity beans built using the two techniques available for implementing the required persistence management methods: bean-managed persistence and container-managed persistence .

Bean-Managed Persistence

Bean-managed persistence (BMP) entity beans are beans whose required persistence management methods have been implemented by the developer in the bean class itself. The bean is responsible for managing its own persistence, hence the name . In its simplest form, the bean class implements the required methods using JDBC calls to SELECT , UPDATE , INSERT , or DELETE the persistent data as appropriate. A detailed discussion of the required methods and techniques for developing BMP entity beans is beyond the scope of this book.

The download site (http://www. wiley .com/compbooks/masteringweblogic) contains an example with a simple BMP entity bean, PersonBMPBean , which will be useful as a starting point for the discussions that follow. The example contains the PersonBMPBean class and supporting files along with JSP pages that test the basic create, load, update, and remove behaviors of this BMP entity bean and illustrate both good and bad techniques for interacting with beans from JSP pages. For example, in the efficient page, PersonBMPTest.jsp , the access to the bean is wrapped in a transaction using techniques discussed in Chapter 3:

 <%@ include file=include/BeginTrans.jspf %> <%   out.print(<H2>Looking up Person 101 again..</H2>);   PersonBMPLocal person101b = home.findByPrimaryKey(new Integer(101));   out.print(Name:  + person101b.getSalutation() +   +             person101b.getFirstName() +   +             person101b.getLastName() + <br>);   out.print(<H2>Changing data in person bean</H2>);   person101b.setFirstName(John);   person101b.setLastName(Smith); %> <%@ include file=include/EndTrans.jspf %> 

By including this activity in a transaction the bean is loaded only once at the beginning of the transaction and stored only once at the end of the transaction, and all get and set calls use the same bean instance in memory. The calls made to the bean instance by the container are limited to the following:

 ejbFindByPrimaryKey(101) ejbLoad() ejbStore() 

The other JSP page, PersonBMPTestNoTrans.jsp , performs the same basic code without the use of a transaction. The bean is loaded and stored for each container- managed transaction created as get and set methods are called, resulting in a large number of ejbLoad() and ejbStore() calls.

This example drives home the importance of interacting with entity beans in the context of a transaction, either explicitly created on the client or automatically created by the container in a session fa §ade method declared to use transactions.

Best Practice  

Always access entity beans in the context of a transaction, either created explicitly using the UserTransaction interface or created automatically by the container. Failure to do so will result in multiple load/store cycles and poor performance.

The use of bean-managed persistence is not recommended as a best practice for the majority of applications. There are several reasons, including the following:

JDBC code complexity.     With BMP, the onus of writing all of the database access code is left to the bean developer. At first glance, you might mistake this for a good thing, thinking that you can write better SQL than the container. In some cases, you might even be right. The problem is that JDBC coding can be error-prone and may involve insidious errors that you may not find until production; these errors often cause memory leaks that can crash your application server when the JVM runs out of memory.

Limited ability for optimizations.    The container must treat the BMP entity EJB as a black box because it has no knowledge about the bean s implementation. As such, it must always call the life-cycle methods at the predefined times because the container has no visibility into what happened to the bean during a particular transaction. For example, the container does not know whether the transaction only read data or actually updated it; therefore, it must always invoke ejbStore() at the end of the transaction to tell the bean to save its state. While this example can be overcome by adding intelligence to the bean code to know how to react to ejbStore() calls, we will explore more examples later in the chapter that cannot be overcome.

Maintainability.     With BMP, you have to write all of the code yourself, including the SQL statements to access your database. While this may not seem like a big deal at first, think about a typical large development project where database changes can occur frequently. If the database schema changes, you have to modify your bean code to reflect the changes. With many CMP beans, you need to write very little actual Java code. All of the mapping between the bean attributes and the database is done in the deployment descriptor, making it easy to regenerate the database persistence code after a schema change. In addition, container-managed persistence can also manage relationships with other entity beans. Again, these relationships are described in the deployment descriptor rather than hard-coded in the bean s Java code, making it easier to adapt to change.

Container-managed persistence, the subject of the next section, is a much stronger alternative for entity bean persistence and should be used whenever possible.

Container-Managed Persistence

Container-managed persistence (CMP) entity beans use persistence-related methods generated by the EJB container rather than methods provided by the bean developer, as was the case in BMP entity beans. Both types of beans define the same methods, such as ejbCreate() , ejbLoad() , and ejbStore() , but in CMP entity beans these methods no longer perform the actual persistence operations. Instead, the container calls these standard methods on the bean instance to signal that associated persistence operations have occurred or are about to occur, giving you an opportunity to modify any internal state or log the operation. The actual persistence operations take place in separate, internal bean methods that are code-generated by the EJB container or tools provided by the container vendor.

Bean classes in BMP entity beans were concrete classes with attributes, get and set methods to access those attributes, and a full set of persistence-related methods. In CMP beans, however, the bean class is actually an abstract class with abstract get and set methods, and it has no requirements for any persistence-related methods. The EJB compiler provided by WebLogic Server uses mapping information in descriptor files provided by the developer to generate a concrete subclass of the entity bean class. The code-generated concrete class implements all of the internal persistence-related methods and provides the actual instance attributes and concrete get and set methods.

A complete discussion of CMP entity beans is beyond the scope of this book. The following simple example illustrates the basic requirements for a CMP entity bean and provides a basis for many of the complex topics and WebLogic Server-specific discussions that follow. The bigrez.com example program also uses CMP entity beans for all business objects and relationships and provides a more realistic example.

Listing 6.1 presents the source listing for the CMP entity bean class PersonCMPBean.java . This CMP bean class and all supporting classes and files are available from the download site for your reference.

Listing 6.1:  PersonCMPBean.java.
start example
 package mastering.weblogic.ch06.example2.ejb; import java.util.Collection; import javax.ejb.EJBException; import javax.ejb.EntityContext; import javax.ejb.FinderException; public abstract class PersonCMPBean extends     mastering.weblogic.ch06.example2.ejb.base.BaseEntity {     private static org.apache.log4j.Category LOG =          org.apache.log4j.Category.getInstance("PersonCMPBean");     public java.lang.Integer ejbCreate(Integer pId, String pSalutation,                                        String pFirstName,                                         String pMiddleName,                                        String pLastName)     {         LOG.info("ejbCreate()");         setId(pId);         setSalutation(pSalutation);         setFirstName(pFirstName);         setMiddleName(pMiddleName);         setLastName(pLastName);         return null; // CMP returns NULL     }     public void ejbPostCreate(Integer pId, String pSalutation,                                String pFirstName, String pMiddleName,                               String pLastName)     {         LOG.info("ejbPostCreate()");     }     // define abstract accessor methods for all bean attributes     public abstract Integer getId();     public abstract void setId(Integer pId);     public abstract String getSalutation();     public abstract void setSalutation(String pSalutation);     public abstract String getFirstName();     public abstract void setFirstName(String pFirstName);     public abstract String getMiddleName();     public abstract void setMiddleName(String pMiddleName);     public abstract String getLastName();     public abstract void setLastName(String pLastName); } 
end example
 

Comparing the size of this file with the equivalent BMP source file, PersonBMPBean.java , provides a clear example of the reduction in Java code inherent in the CMP approach. There are some key differences between the BMP and CMP bean classes:

  • PersonCMPBean is defined as an abstract class; PersonBMPBean is concrete.

  • PersonCMPBean defines only abstract get and set methods with no instance variables. The BMP version defined the instance variables themselves as well as concrete get and set methods.

  • PersonCMPBean defines only ejbCreate() and ejbPostCreate() and does not perform any SQL operations in these methods. The other standard entity bean methods can be defined in a base class, in this case BaseEntity , because they are simply callbacks that typically require little or no application code. The BMP version defined all of the required methods and performs all required SQL operations in the bean class.

Listings 6.2 presents the local interface for the CMP entity bean, essentially unchanged from its BMP counterpart .

Listing 6.2:  PersonCMPLocal.java.
start example
 package mastering.weblogic.ch06.example2.ejb; import javax.ejb.EJBLocalObject; public interface PersonCMPLocal extends EJBLocalObject {     public Integer getId();     public String getSalutation();     public void setSalutation(String pSalutation);     public String getFirstName();     public void setFirstName(String pFirstName);     public String getMiddleName();     public void setMiddleName(String pMiddleName);     public String getLastName();     public void setLastName(String pLastName);      } 
end example
 

Listing 6.3 presents the home interface for the CMP entity bean, also essentially unchanged from its BMP counterpart.

Listing 6.3:  PersonCMPHomeLocal.java.
start example
 package mastering.weblogic.ch06.example2.ejb; import javax.ejb.CreateException; import javax.ejb.EJBLocalHome; import javax.ejb.FinderException; public interface PersonCMPHomeLocal extends EJBLocalHome {     public PersonCMPLocal findByPrimaryKey(Integer primaryKey)         throws FinderException;     public PersonCMPLocal create(Integer pId, String pSalutation,                                  String pFirstName, String pMiddleName,                                  String pLastName)         throws CreateException; } 
end example
 

Listing 6.4 presents the standard ejb-jar.xml descriptor file for the CMP entity bean. Like the BMP version, this file contains basic configuration, security, and transaction information. The CMP version also defines the bean attributes, using cmp-field elements, and the primary key for the bean.

Listing 6.4:  ejb-jar.xml.
start example
 <?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC  "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"  "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar>   <enterprise-beans>     <entity>       <ejb-name>PersonCMPEJB</ejb-name>       <local-home>         mastering.weblogic.ch06.example2.ejb.PersonCMPHomeLocal       </local-home>       <local>         mastering.weblogic.ch06.example2.ejb.PersonCMPLocal       </local>       <ejb-class>         mastering.weblogic.ch06.example2.ejb.PersonCMPBean       </ejb-class>       <persistence-type>Container</persistence-type>       <prim-key-class>java.lang.Integer</prim-key-class>       <reentrant>False</reentrant>       <cmp-version>2.x</cmp-version>       <abstract-schema-name>PersonCMPEJB</abstract-schema-name>       <cmp-field><field-name>id</field-name></cmp-field>       <cmp-field><field-name>salutation</field-name></cmp-field>       <cmp-field><field-name>firstName</field-name></cmp-field>       <cmp-field><field-name>middleName</field-name></cmp-field>       <cmp-field><field-name>lastName</field-name></cmp-field>       <primkey-field>id</primkey-field>       <security-identity><use-caller-identity/></security-identity>     </entity>   </enterprise-beans>   <assembly-descriptor>     <security-role>       <role-name>Anonymous</role-name>     </security-role>     <method-permission>       <role-name>Anonymous</role-name>       <method>          <ejb-name>PersonCMPEJB</ejb-name>          <method-name>*</method-name>       </method>     </method-permission>     <container-transaction>       <method>         <ejb-name>PersonCMPEJB</ejb-name>         <method-name>*</method-name>       </method>       <trans-attribute>Required</trans-attribute>     </container-transaction>   </assembly-descriptor> </ejb-jar> 
end example
 

Listing 6.5 presents the WebLogic Server-specific descriptor file, weblogic-ejb-jar.xml , a file used to configure EJB deployments and map generic resource names in ejb-jar.xml to specific names in the environment. In the case of CMP entity beans, the weblogic-ejb-jar.xml file is basically identical to the BMP version except for a persistence element added to indicate the type of persistence being employed in the bean.

Listing 6.5:  weblogic-ejb-jar.xml.
start example
 <?xml version="1.0"?> <!DOCTYPE weblogic-ejb-jar PUBLIC 


Mastering BEA WebLogic Server. Best Practices for Building and Deploying J2EE Applications
Mastering BEA WebLogic Server: Best Practices for Building and Deploying J2EE Applications
ISBN: 047128128X
EAN: 2147483647
Year: 2003
Pages: 125

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