Construction of Business-Tier Components


Construction of Business- Tier Components

The bigrez.com business tier contains a fair number of entity beans, three stateless session beans, and a single message-driven bean. This section will examine each of these types of beans and highlight key aspects of their design and construction.

Construction of Entity Beans

The top-level parent bean in the property- related set of entity beans is the PropertyBean component. This bean contains basic property information as well as container-managed relationships to all of the room, rate, offer, and reservation beans associated with the property. Please download the PropertyBean.java bean class file from http://www. wiley .com/compbooks/masteringweblogic and examine it before proceeding.

There are a number of sections to note in this class file. First, the class-level EJBGen tags at the top of the file specify required class-level information for the EJB descriptor files, including the name of the JDBC DataSource , the table name, automatic key-generation information, and the JNDI name to use for the local home interface:

 /**  * @ejbgen:entity  *   ejb-name = PropertyEJB  *   prim-key-class = java.lang.Integer  *   data-source-name = BigRezDataSource  *   table-name = PROPERTY  *   default-transaction = Required  *  * @ejbgen:jndi-name  *   local = PropertyHomeLocal  *  * @ejbgen:automatic-key-generation  *   type = NAMED_SEQUENCE_TABLE  *   name = COMMON_SEQUENCE  *   cache-size = 1 

Note that we ve chosen to hard-code this information directly in the tag attributes rather than use a properties file for substitutions in order to keep the example simple and readable. The substitution capability, discussed previously in this chapter, is very powerful and should be used in your applications.

The next section of the bean class file defines a set of finder methods and their underlying EJB-QL definitions using ejbgen:finder tags:

 * @ejbgen:finder  *   signature = Collection findAll()  *   ejb-ql = SELECT OBJECT(o) FROM PropertyEJB as o  *  * @ejbgen:finder  *   signature = Collection findByCity(java.lang.String city)  *   ejb-ql = SELECT OBJECT(o) FROM PropertyEJB o WHERE o.city = ?1 ... 

These tags cause EJBGen to create appropriate method declarations in the home interface file and ejb-ql entries in the ejb-jar.xml descriptor file for each finder method. Services, clients , and controller objects can execute these finder methods to retrieve collections matching PersonBean references using the home interface:

 String city = ...; PropertyHomeLocal propertyhome =      (PropertyHomeLocal)Locator.getHome("PropertyHomeLocal"); Collection props =  propertyhome.findByCity(city);  

The Locator class, described in detail in Chapter 5, is a simple utility class used by bigrez.com to encapsulate the JNDI lookup process for home interfaces and entity bean instances. The class implements a variety of the EJBHomeFactory design pattern by caching home references and providing a reflection-based technique for looking up entity beans by primary key with a single method invocation. Examine the Locator.java file in the downloadable example code to see how these functions are implemented if you are curious .

The next section of PropertyBean.java completes the class-level EJBGen tags by defining the relationships between the Property and other beans in the application:

 * @ejbgen:relation  *   name = Property-Reservations  *   target-ejb = ReservationEJB  *   multiplicity = one  *   cmr-field = reservations  *  * @ejbgen:relation  *   name = Property-RoomTypes  *   target-ejb = RoomTypeEJB  *   multiplicity = one  *   cmr-field = roomTypes  *  * @ejbgen:relation  *   name = Property-Offers  *   target-ejb = OfferEJB  *   multiplicity = one  *   cmr-field = offers  *  */ 

Each relationship is named, and the target EJB component, source-side multiplicity, and container-managed relationship (CMR) field name are specified to complete the definition. Recognize that the multiplicity specified in this tag is the Property multiplicity rather than the target EJB s multiplicity. Each target bean class file will have a corresponding ejbgen:relation tag with the same relationship name and appropriate attributes defining that end of the relationship. For example, the one-to-many, bidirectional relationship between Property and RoomType requires a corresponding ejbgen:relation tag on the RoomTypeBean class file:

 * @ejbgen:relation  *   name = Property-RoomTypes  *   target-ejb = PropertyEJB  *   multiplicity = many  *   cmr-field = property  *   fk-column = PROPERTY_ID  *   cascade-delete = true 

This tag in RoomTypeBean also specifies the foreign-key column name because the relationship is defined in the database using a parent foreign key in the child table, in this case PROPERTY_ID . The cascade-delete attribute is also set in this child class file, activating the container-based cascade-delete logic discussed in Chapter 6.

Continuing in the PropertyBean class file, the next section defines the class as a subclass of our simple base class, BaseEntity , and provides the required ejbCreate() and ejbPostCreate() methods. As discussed in Chapter 6, attributes are normally set in ejbCreate() and relationships are set in ejbPost Create() , a practice we ve followed in this class.

Following these create-related methods is a series of get and set methods for each of the container-managed attributes in the class. Each set of methods is prefixed by the appropriate EJBGen tags to declare the desired interface on which to place the methods, whether the attribute is part of the primary key, and what database column the attribute maps to in the persistent store. For example, consider the section for the description attribute:

 /**      * @ejbgen:cmp-field column = DESCRIPTION      * @ejbgen:local-method      */     public abstract String getDescription();     /** @ejbgen:local-method */     public abstract void setDescription(String description); 

This specifies that both getDescription() and setDescription() should be placed in the EJB s local interface, and it defines the column in the database table to be DESCRIPTION .

After the get and set methods for the simple container-managed attributes come the methods for accessing and modifying the CMR fields:

 /**      * @ejbgen:cmr-field      * @ejbgen:local-method      */     public abstract Collection getReservations();     /** @ejbgen:local-method */     public abstract void setReservations(Collection reservations);     /**      * @ejbgen:cmr-field      * @ejbgen:local-method      */     public abstract Collection getRoomTypes();     /** @ejbgen:local-method */     public abstract void setRoomTypes(Collection roomtypes);     ... 

Because the ejbgen:relation tag at the top of the class file declared a cmr-field attribute for each relation, there must be a corresponding get and set method for each one. As before, the EJBGen tags in front of each method define the interface on which to place the get or set method ”in this case, the EJB s local interface.

The bean class also includes special methods useful for returning the contents of relationships in a new, normal collection object rather than returning the internal container-managed collection directly to the caller. These methods are declared to return a Collection and are placed on the local interface for the bean:

 /**  * @ejbgen:local-method  */ public Collection getRoomTypesReadOnly() {     return makeReadOnlyList(getRoomTypes()); } 

The makeReadOnlyList() method, defined in BaseEntity.java , simply iterates through the relationship collection and creates a normal ArrayList collection containing the references:

 protected Collection makeReadOnlyList(Collection cmrlist)  {     Collection rolist = new ArrayList();     Iterator i = cmrlist.iterator();     while (i.hasNext()) {         rolist.add(i.next());     }     return rolist; } 

A technique similar to this will be employed in some beans to create and return a sorted collection of bean references from a container-managed relationship. Unless these relationship collections are sorted in memory, the results will be returned in a nondeterministic manner based on the database access path for the underlying query.

Finally, two ejbHome methods are defined to fetch lists of valid state codes and city names as a crude but effective way to fill the associated drop-lists in the property search page. These methods use a custom SQLHelper utility class to execute simple SQL statements and return collections of strings.

That s all there is to the PropertyBean class file. The EJBGen utility uses this file to create the PropertyLocal interface class, the PropertyHomeLocal home interface class, and all of the ejb-jar.xml , weblogic-ejb-jar.xml , and weblogic-cmp-rdbms-jar.xml descriptor elements related to this bean. All of the other entity beans are constructed in the same manner and use many of the same tags and techniques.

The downloadable example code includes full listings of all entity beans in the bigrez.com example application. Many additional examples of relationships and other entity bean features are contained in these bean files, but space does not permit us to cover them in detail.

Construction of Session Beans

The bigrez.com application uses a combination of entity beans and stateless session beans to implement the business tier. In this section, we will examine some of the key stateless session beans used to encapsulate complex business logic. Because we are using direct interaction between the controller components and the entity beans for most query, data retrieval, and data update logic, these stateless session beans do not include create, read, update, and delete methods.

There are three stateless session beans, or services, in the bigrez.com application. The first is the InventorySessionBean , a service encapsulating logic for reading and updating inventory information. The methods in this service are used by the administration Web site to view and manage inventory. Most of these methods accept or return collections of Inventory entity bean references, consistent with the direct interaction approach.

The second service is the OfferSessionBean , a stateless session bean encapsulating the business logic for reading and ordering the targeted offers displayed to the user depending on their current search criteria or property selection. The main method in this service, getOffersForDisplay() , returns a collection of local references to OfferBean objects rather than a set of value objects. The caller then iterates through this collection and retrieves the offer information from each entity bean directly.

The third service is the ReservationSessionBean , a stateless session bean encapsulating complex business logic associated with rate and availability search functions and the creation of the final reservation object at the end of the process. Like the other session beans, the methods on ReservationSessionBean interact with entity bean home interfaces to perform the desired business logic, accepting and returning local references in many cases.

Please examine these session beans in the downloadable example code. A fair amount of complex business logic is encapsulated in these beans, a clear argument for the use of stateless session beans in these particular cases. Logic this complex does not belong in presentation-tier components. Space does not permit a complete walkthrough of the code, but the following list presents key techniques and highlights for the ReservationSessionBean :

  • EJBGen tags at the top of the bean class file are used to define JNDI names and class-level descriptor information. Method-level EJBGen tags are used to indicate which methods should appear on local and remote interfaces.

  • The calculateRates() method has a RoomType entity bean reference as a parameter, along with simple Date parameters, and returns a collection of ReservationRateInfo value objects. Because we are requiring collocation of the Web application and EJB components in a single .ear file, there is no reason to avoid passing entity beans as parameters in service methods.

  • The createReservation() method, on the other hand, uses a ReservationInfo value object as the input parameter, and it constructs and returns a Reservation entity bean to the caller as the result of the method. Again, the choice of parameters and return types is made freely , without requiring value objects due to deployment limitations.

  • The createReservation() method encapsulates a very complex series of steps required to update inventory, create the reservation record in the database, and post a message to an outbound email JMS queue. A variety of entity beans are fetched , created, and updated in this process, demonstrating the ability to perform this activity without resorting to JDBC SQL statements or other techniques.

As long and complex as the ReservationSessionBean and the other two session beans are, they represent the bulk of all business-tier coding required for the bigrez.com example application. The 600 or so lines of code in these three services represent only business logic with no data access or other services. All persistence services and object-relational mapping are performed by the container-managed entity beans themselves . Implementing the pure session fa §ade approach with value objects would require hundreds, if not thousands, of lines of code in the services to implement all of the query, data retrieval, data manipulation, and object-relational mapping functions required for the simple bigrez.com object graph. Direct interaction results in significantly smaller session beans, as evidenced by this example.

Construction of Message-Driven Beans

The bigrez.com application includes a simple message-driven bean, EmailProcessorBean , used to create outbound emails to customers containing reservation information. Class-level ejbgen tags are used to define the required EJB parameters for the bean:

 /**  * @ejbgen:message-driven  *   ejb-name = EmailProcessorEJB  *   destination-jndi-name = BigRezEmailQueue  *   destination-type = javax.jms.Queue  *   initial-beans-in-free-pool = 5  *   max-beans-in-free-pool = 10  *   acknowledge-mode = auto-acknowledge  *   transaction-type = Container  *  * @ejbgen:resource-ref  *   name = jms/BigRezEmailSession  *   jndi-name = BigRezEmailSession  *   type = javax.mail.Session  *   auth = Container  */ 

The onMessage() method simply retrieves the email content in the JMS MapMessage and creates the outbound email using standard JavaMail interfaces:

 public void onMessage(javax.jms.Message message) {     try {         LOG.info(EmailProcessorBean::onMessage() called..);         MapMessage emailMsg = (MapMessage)message;         String emailFrom = reservations@bigrez.com;         String emailTo = emailMsg.getString(TO);         String emailSubject = emailMsg.getString(SUBJECT);         String emailContent = emailMsg.getString(CONTENT);         LOG.info(Preparing email for +emailTo+                   with subject +emailSubject);         javax.mail.Session session = (javax.mail.Session)             jndiContext.lookup(java:comp/env/jms/BigRezEmailSession);         javax.mail.Message msg = new MimeMessage(session);         msg.setFrom(new InternetAddress(emailFrom));         msg.setRecipient(javax.mail.Message.RecipientType.TO,                           new InternetAddress(emailTo));         msg.setSubject(emailSubject);         msg.setSentDate(new Date());         msg.setContent(emailContent, text/plain);         Transport.send(msg);         LOG.info(onMessage complete);     }     catch (JMSException e) {         LOG.error(JMSException sending email confirmation, e);         ejbContext.setRollbackOnly();     }     catch (NamingException e) {         LOG.error(NamingException sending email confirmation, e);         ejbContext.setRollbackOnly();     }     catch (MessagingException e) {         LOG.error(MessagingException sending email confirmation, e);         ejbContext.setRollbackOnly();     } } 

We ve now completed our discussion of the design and construction of the bigrez.com business tier. Noticeably absent from this section is any mention of the EJB-related deployment descriptors. Because we are using EJBGen we never create or hand-edit these descriptors. Good riddance!




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