Realization of the Site Administration Use Case Package


The following subsections provide the use case realization for use cases in the Site Administration package. To avoid repetition, we cover only essential use cases that introduce new concepts; for the rest of the use cases, please refer to the implementation on the accompanying CD-ROM. In this section we apply all the business patterns we discussed earlier in this chapter. We also discuss the deployment descriptors required to configure the EJBs that will be created for realizing the Register NPO use case, along with the declarations that specify the transaction semantics for the various EJB methods. We conclude this section with a brief discussion on exceptions in the context of transactions.

Note

The following subsections provide readers with an opportunity to understand class interactions and dependencies visualized through class and analysis-level sequence diagrams. Please refer to Chapter 1 for use case descriptions.

Register NPO Use Case

This section covers the implementation of Register NPO use case. The implementation details described here provide the necessary foundation for other use cases; and the same concepts are reapplied for implementing other use cases.

Discovering Business Interface Methods

The first step in realizing the use case is to identify the methods of the business interface necessary for realizing the use case. We identify the business interface methods by following the flow of events described for the use case. Since the Register NPO is an administration service, applying the business interface pattern described earlier in the section "Implementing the Business Interface Pattern," we define a business interface called SiteAdmin. This interface must provide a method called registerNPO for allowing the presentation tier to register NPO data. Using the data transfer object pattern, the presentation tier provides the required data in an object called NPORegistrationDTO. We can identify the attributes of this DTO from the wire frames identified during the use case elaboration process. The following code fragment shows the required attributes for the NPORegistrationDTO class that represent registration information:

 public class NPORegistrationDTO implements Serializable {     //Instance variables     private String ein = null;     private String npoName = null;     private String adminID = null;     private String address = null;     private String city = null;     private String state = null;     private String zip = null;     private String country = null;     private String activationStatus = null;     ... rest of the code ... } 

Since this DTO will go across the wire using RMI, ensure that it implements the Serializable interface. Once the registration information is created in the GreaterCause data store, the Register NPO use case will also need to maintain this information using the updateNPORegistration and getNPORegistration methods; these additional methods are added to the business interface as well. The following code fragment shows the business methods identified thus far in the business interface SiteAdmin:

 public interface SiteAdmin {     void registerNPO(NPORegistrationDTO detail) throws RemoteException,          RegistrationException;     void updateNPORegistration(NPORegistrationDTO details)         throws RemoteException,NPONotFoundException, GCAppException;     NPORegistrationDTO getNPORegistration(String ein, String adminID)         throws RemoteException, NPONotFoundException,         AdminNotFoundException, GCAppException; } 

The method signatures identified for the business interface shown were selected based on the design decision that we will be employing the services of a stateless session bean. Because the stateless session bean does not maintain any state information, the client must provide all the details necessary for the session bean to service the request; this design may complicate the client logic because the onus is on the client to maintain the application state. In the business interface of SiteAdmin, note two methods are used by the client for getting and updating the registration information; these methods are getNPORegistration and updateNPORegistration. The design of the client has accounted for the fact that both of these methods will be serviced by different session bean instances, therefore the client design will ensure that when updateNPORegistration is invoked, the corresponding parameters (that is, NPORegistrationDTO) will include the ein (EIN is the primary key for the NPO entity bean and is not updatable by the client) in addition to all the other information required by the session bean to service this request. Had we decided to use a stateful session bean instead of a stateless session bean, the update method would not require the ein because the session bean would be aware of the parameters that were supplied when getNPORegistration was invoked for constructing the NPORegistrationDTO. This is further clarified by the sequence diagrams shown in Figure 7-8, 7-9, and 7-10.

Please observe that the business methods declared in the business interface also declare the possible exceptions the business methods may throw to the presentation tier. In addition to the application exceptions, the business methods must also throw RemoteException; this is because the remote interface for the session bean will be extended from this business interface. Recall from the discussion in the section "Implementing the Business Interface Pattern" that the business methods must throw RemoteException if they are to be exposed through a remote interface as required by the EJB 2.0 specification.

Implementing Business Interface

In this section, we discuss the implementation aspects of the business interface SiteAdmin defined in the preceding section. Figure 7-7 shows the class diagram for realizing the Register NPO use case. You will find additional methods on the SiteAdminBean class pertaining to other use cases, which you should ignore for now. Figure 7-7 shows the interactions between various business tier components. The SiteAdmin interface employs the Business Interface pattern; the SiteAdminBean class employs the Session Fa ade pattern; and the NPORegistrationDTO class employs the Data Transfer Object pattern. The SiteAdminBean class employs the services of the EJBHomeFactory class for getting references to domain tier entities such as Admin and NPO entity beans. For brevity, Figure 7-7 does not show application-specific exceptions and the usage of EJBHomeFactory.

click to expand
Figure 7-7: Register NPO class diagram

Figure 7-8 depicts the creation of domain objects Admin and NPO using the DTO supplied by the presentation tier, whereas Figure 7-9 depicts the creation of DTO using the information from the domain objects Admin and NPO. From the sequence diagram, it is apparent that the session fa ade SiteAdmin is responsible for handling all the complexities of creating and managing domain objects while the presentation tier need only make a single call to the session fa ade. For brevity, certain steps are removed from the sequence diagrams and the reader is requested to check the accompanying CD-ROM for the complete source code.

click to expand
Figure 7-8: Sequence diagram for registerNPO

click to expand
Figure 7-9: Sequence diagram for getNPORegistration

SiteAdmin Session Bean Deployment Descriptors

The session bean SiteAdminBean defined in the preceding section needs to be configured for deployment in an EJB container. We use deployment descriptors for providing the configuration information.

There is essentially more than one deployment descriptor associated with the deployment of a session bean. The ejb-jar.xml file contains standard declarations as dictated by the EJB specification. Additionally, the vendor will provide other deployment descriptors that are proprietary in nature. We first discuss the ejb-jar.xml deployment descriptor and the associated semantics. Following snippet provides configuration information for the SiteAdmin session bean.

 <session >    <description>Site Admin Definitions</description>    <ejb-name>SiteAdminEJB</ejb-name>    <home>com.gc.services.admin.SiteAdminHome</home>    <remote>com.gc.services.admin.SiteAdminRemote</remote>    <ejb-class>com.gc.services.admin.SiteAdminBean</ejb-class>    <session-type>Stateless</session-type>    <transaction-type>Container</transaction-type>    <!-- Referencing NPO Entity Bean -->    <ejb-local-ref>       <ejb-ref-name>com.gc.persistence.admin.NPOLocalHome</ejb-ref-name>       <ejb-ref-type>Entity</ejb-ref-type>       <local-home>com.gc.persistence.admin.NPOLocalHome</local-home>       <local>com.gc.persistence.admin.NPOLocal</local>       <ejb-link>NPOEntityEJB</ejb-link>    </ejb-local-ref>    <!-- Referencing Admin Entity Bean -->    <ejb-local-ref>       <ejb-ref-name>com.gc.persistence.admin.AdminLocalHome</ejb-ref-name>       <ejb-ref-type>Entity</ejb-ref-type>       <local-home>com.gc.persistence.admin.AdminLocalHome</local-home>       <local>com.gc.persistence.admin.AdminLocal</local>       <ejb-link>AdminEntityEJB</ejb-link>    </ejb-local-ref> </session> 

Using the ejb-name element, we assign a logical name to the session bean. This logical name must be unique within the ejb-jar.xml file. This name is referenced in other constructs such as the subelements of the container-transaction element and ejb-relation element (refer to the element ejb-name in these constructs). The session EJB is further described using the home, remote, and ejb-class elements that provide the fully qualified class names for the home interface, remote interface, and the bean class, respectively. The session-type element is used for specifying whether the bean is stateful or stateless. Changing the session-type element's values without properly analyzing the impact of the current implementation could produce unpredictable results. The transaction-type element specifies the bean's transaction type, which could be either Bean, implying that the bean is providing transaction demarcation, or Container, implying that the container is providing the transaction demarcation based on the transaction attributes specified as part of the container-transaction element in the ejb-jar.xml file. The transaction-type element must not be specified for entity beans because all entity beans must use container-managed transaction demarcation.

Recall that when a client accesses an EJB in a container, it uses the following code that employs vendor-specific properties for correctly creating an InitialContext. Note that this vendor-specific code is required only when you are accessing EJBs from outside the container.

 //Vendor specific code Hashtable props = new Hashtable(); props.put(InitialContext.INITIAL_CONTEXT_FACTORY,     "weblogic.jndi.WLInitialContextFactory"); props.put(InitialContext.PROVIDER_URL,     "t3://localhost:7001"); InitialContext ctx = new InitialContext(props); SiteAdminHome siteAdminHome = (SiteAdminHome)     javax.rmi.PortalRemoteObject.narrow(     ctx.lookup("ejb/com.gc.services.admin.SiteAdminHome"),SiteAdmin.class); 

The access mechanism shown here is not required when an EJB is accessing another EJB. The session bean SiteAdminBean references NPO and Admin entity beans as part of the implementation of Register NPO use case. The EJB 2.0 specification simplified the access mechanisms when an EJB in a container is accessing another EJB within the same or a different container. To reference an EJB from another EJB, you do not need to specify any JNDI initialization parameters; instead you acquire default JNDI InitialContext as follows:

 Context initialContext = new InitialContext(); 

When default JNDI InitialContext is used, the lookup mechanism will take the following form. In this form, the java:comp/env/ string specifies the default environment naming context.

 NPOHome npoHome = (NPOHome)         initialContext.lookup("java:comp/env/"+NPOHome.class); 

The NPOHome.class is mapped by the container to the value of the ejb-ref-name element within the deployment descriptors; the value of the ejb-ref-name element is subsequently used by the container to get the descriptors of the corresponding EJB. The ejb-ref-name element has a sibling ejb-link element (defined under the parent ejb-local-ref element); this ejb-link element provides the link to the original definition of the entity bean; the value of this element is the logical name given in the ejb-name element of the corresponding entity bean where it was originally defined. Since the NPO entity bean is described in the same ejb-jar.xml file for our sample application, we can simply provide the value NPOEntityEJB for the ejb-link element.

For the session bean deployment descriptors being discussed in this section, notice that the ejb-ref-name element occurs under the ejb-local-ref element; these constructs assist the container in accessing the NPO and Admin entity beans. This concludes the discussion on the deployment descriptors for the SiteAdmin session bean. The JNDI name for the session bean is defined in a vendor-specific deployment descriptor; since we have used the WebLogic Server, the corresponding deployment descriptor is the weblogic-ejb-jar.xml file.

 <!-- SiteAdmin Definition --> <weblogic-enterprise-bean>     <ejb-name>SiteAdminEJB</ejb-name>     <jndi-name>ejb/com.gc.services.admin.SiteAdminHome</jndi-name> </weblogic-enterprise-bean> 

The ejb-name element refers to the ejb-name defined in the ejb-jar.xml file. The jndi-name element represents the JNDI name to be used for accessing the session bean. The EJB 2.0 specification recommends prefixing the JNDI names with "ejb/."

Transaction Semantics for Enterprise Beans

The EJB Specification greatly simplified declarative transaction management. Without this, the developer had to explicitly manage the transactions with fairly complex Java Transaction Service (JTS), which is based on OMG's Object Transaction Service (OTS) API. Explicit transaction management is prone to errors, especially for those who are new to transactional application development. Including transaction semantics in business applications increases the code complexity, which results in high maintenance cost; a change in the transactional behavior will force a change to business logic. The EJB specification allows declarative transaction management through deployment descriptors. The transaction semantics are introduced at the time of deployment, which introduces flexibility in manipulation of transactional behavior of the application without resorting to code changes. For this chapter, we use container-managed transaction demarcation where the container demarcates the transactions based on the instructions provided through the deployment descriptor.

The bean provider may also choose to use programmatic transaction demarcation; this is called bean-managed transaction demarcation. With bean-managed transaction demarcation, the enterprise bean demarcates transactions using the javax.transaction.UserTransaction interface. Accesses to container-managed resources, between UserTransaction.begin() and UserTransaction.commit(), are part of this transaction. Please refer to the EJB specifications or Mastering Enterprise JavaBeans [JavaBeans] for detail information on using programmatic bean-managed transaction demarcation.

Note

The EJB architecture supports flat transactions, implying that a transaction cannot have other nested (child) transactions. We assume that the reader has prior knowledge of what a transaction is and the associated ACID properties.

Scope of a Transaction When using container-managed transaction demarcation, the scope of a transaction is controlled by the transaction attribute specified for the EJB's methods. Following briefly discusses these transaction attributes so that we can understand its impact in the context of our implementation.

Transaction Attributes A transaction attribute is a value associated with a method of a session or entity bean's home or component interface that specifies how the Container must manage transactions for a method when a client invokes the method via the enterprise bean's home or component interface (i.e., local or remote interfaces). EJB specification supports the following values for the transaction attribute when using container-managed transaction demarcation for EJBs:

  • NotSupported When the transaction attribute is set to NotSupported, the container invokes the related enterprise bean method with an unspecified transaction context. When a client is associated with a transaction context, the container suspends the client's transaction context until the enterprise bean's business method returns. This means that the transaction context is not propagated to the bean method. After completion of the bean method's execution, the client's transaction context is resumed. This attribute value is specified when the bean method needs to access a resource that cannot or should not participate in a transaction.

  • Required When the transaction attribute is set to Required, the container must invoke the related enterprise bean method with a valid transaction context. If the client invokes the enterprise bean's method with a transaction context, the same transaction context is propagated to the bean's method. If the client is not associated with a transaction context, the container automatically starts a new transaction before calling the business method. This option is selected when the bean method is changing the state of the application; for example, creating one or more entity beans or updating the value of entity beans, and so on. This option is not necessary if the bean method is just reading the contents from the data store, and the application is not concerned with holding stale data. The Required attribute value is the most widely used option in EJB declarations for injecting transactional semantics into method calls. The registerNPO method of the SiteAdminBean session bean is declared with the Required transaction attribute because the use case requires the creation of a new Admin entity bean and NPO entity bean. Both beans must be successfully created and their relationship established in the same transaction for the transaction to succeed.

  • Supports When the transaction attribute is set to Supports, the container invokes the related enterprise bean method as follows:

    • If the client call is associated with a transaction context, the semantics applicable are similar to the Required case.

    • If the client call is not associated with a transaction context, the semantics applicable are similar to the NotSupported case.

  • RequiresNew When the transaction attribute is set to RequiresNew, the container invokes the related enterprise bean method with a new transaction context. This transaction context is propagated to methods of other enterprise beans. When the client invokes the enterprise bean while the client is already associated with a transaction context, then that transaction is suspended. The bean method starts a new transaction and completes its execution under this new transaction. When the bean method returns, the Container resumes the client's transaction. This option is usually selected if the bean's method cannot participate in the callers transaction context.

  • Mandatory When the transaction attribute is set to Mandatory, the container must invoke the related enterprise bean method in a client's transaction context. If the client calls with a transaction context, the container performs the same steps as described in the Required case; if the client calls without a transaction context, the container throws the javax.transaction.TransactionRequiredException for a remote client, or javax.ejb.TransactionRequiredLocalException for a local client.

  • Never When the transaction attribute is set to Never, the container invokes the related enterprise bean method without a transaction context. If the client calls with a transaction context, the container throws java.rmi.RemoteException for a remote client, or javax.ejb.EJBException for a local client. If the client calls without a transaction context, the container performs the same steps as described in the NotSupported case.

Transaction Attributes for SiteAdmin Session Bean Methods

The transaction attributes for each EJB are defined in deployment descriptors. The descriptors have the flexibility for providing a single transaction attribute for all the methods using the * notation, as shown here:

 <container-transaction>     <method>         <ejb-name>SiteAdminEJB</ejb-name>         <method-name>*</method-name>     </method>     <trans-attribute>Required</trans-attribute> </container-transaction> 

This representation specifies that all methods of SiteAdminEJB will have the transaction attribute of Required. This implies that all the SiteAdminEJB method invocations are always under a transaction context even if the bean method is simply reading the data from data store. The transaction attribute must be set to Required for those methods that affect the persistent state of the application. For example, the transaction attribute is set to Required for the registerNPO and updateNPORegistration methods of the SiteAdmin session bean because these methods change the persistent state of the application. Transaction attributes for individual methods of the SiteAdminBean can be specified as follows.

 <container-transaction>     <method>         <ejb-name>SiteAdminEJB</ejb-name>         <method-name>registerNPO</method-name>     </method>     <method>         <ejb-name>SiteAdminEJB</ejb-name>         <method-name>updateNPORegistration</method-name>     </method>     <trans-attribute>Required</trans-attribute> </container-transaction> 

Handling Exceptions in Transactions

The EJB 2.0 specification introduces conceptual difference between application exceptions and system exceptions. The EJB developer must understand this difference in addition to the relationship between exceptions and transaction semantics.

An application exception is an exception defined in the throws clause of a method of the enterprise bean's home and component interfaces (remote and local interfaces), other than java.rmi.RemoteException or javax.ejb.EJBException. An application exception is a direct or indirect subclass of java.lang.Exception; it must not be defined as a subclass of java.lang.RuntimeException or java.rmi.RemoteException. Application exceptions are used to inform the client about abnormal conditions in the business logic; clients catching such exceptions are expected to recover from the exception and to provide alternative business logic to deal with the situation, provide information to the user about corrective action, or fail gracefully with appropriate logging of the exception and instructions for the client. In our sample application, all the exceptions subclassed from GCAppException are application exceptions. The container also throws application exceptions such as javax.ebj.CreateException, javax.ejb.RemoveException,javax.ejb.FinderException, and so on.

On the other hand, system-level exceptions are created as a result of situations that prevent EJB methods from completing successfully; for example, failure to obtain a database connection, JNDI exceptions, unexpected RemoteException from invocation of other enterprise beans, RuntimeException, JVM errors, and so on. The bean methods must not try to catch these RuntimeExceptions but let them propagate to the container. When a bean method is processing a checked exception and discovers that it cannot recover from the exception, the bean method should throw the javax.ejb.EJBException; EJBException is a subclass of RuntimeException, and therefore it does not have to be listed in the throws clause of business methods. The Container catches all non-application exceptions, logs the exception, marks the transaction for rollback, and subsequently throws a RemoteException (for clients using remote interfaces) or EJBException (for clients using local interfaces). The following code fragment has been excerpted from the getNPORegistration method of the SiteAdmin session bean:

 try {     NPOLocalHome npoHome =    (NPOLocalHome) EJBHomeFactory.getFactory().lookUpLocalHome(        NPOLocalHome.class);     ... Rest of the code ... } catch (NamingException ne) {     throw new EJBException(     "Unable to locate local reference to NPO:", ne); } 

NamingException is thrown by the container during JNDI lookup; since this signifies a configuration issue, the application will throw an EJBException and not an application exception because the client is not expected to recover from this exception.

According to the EJB 2.0 specification, when a system exception is encountered in the business method of an EJB, the container must either mark the transaction for rollback (this is true when the method runs in the context of the caller's transaction), or roll back the transaction started by the container (this is true when the method runs in the context of a transaction that the container started immediately before dispatching the business method). When the container discards an instance of a bean because of a system exception, the container releases all the connections to the resource managers that the instance acquired through resource factories declared in the enterprise bean environment such as JDBC DataSource references, JMS connection factories, JavaMail connection factories, URL connection factories, and so on; the container cannot release "unmanaged" resources that the instance may have acquired directly.

When the business method encounters an application exception, and if the exception is deemed unrecoverable, it is the EJB developer's responsibility to identify and mark the transaction for rollback using setRollbackOnly() on EJBContext; this marks the transaction for rollback. The setRollbackOnly method can be invoked only when bean methods are participating in a transaction context. Observe from the following code fragment that the setRollbackOnly method is invoked prior to throwing the RegistrationException, which is an application exception; the intent here is to mark the transaction for rollback because the NPO entity bean has already been created. Please note that the code shown is slightly modified for explaining the concepts; the actual code can be found in SiteAdminBean implementation.

 try {     AdminLocalHome adminHome =        (AdminLocalHome) EJBHomeFactory.getFactory().lookUpLocalHome(         AdminLocalHome.class);     admin = adminHome.create(adminID, (NPOLocal) npo); } catch (CreateException ce) {     ctx.setRollbackOnly();     throw new RegistrationException("error.CannotCreateAdmin",          "Unable to Register Admin with AdminID:" + adminID, ce); } catch (NamingException ne) {   /* setRollbackOnly() not required because the EJBException is a system exception */     throw new EJBException("Unable to locate local reference to Admin:", ne); } 

The following is a brief discussion of standard application exceptions for entity beans. We discuss this in the context of marking transaction for rollbacks.

  • CreateException This exception is thrown by the container when using container-managed persistence, or this exception can be thrown by the bean developer in the ejbCreate or ejbPostCreate method. The transaction may or may not be marked for rollback, although it is advisable that the bean developer should mark the transaction for rollback to leave the database in a consistent state. When bean-managed transaction is in effect, the session bean method can determine the status of the transaction using the getStatus method on the javax.transaction.UserTransaction interface; when container-managed transaction is in effect, the session bean method can determine the status of the transaction using the getRollbackOnly method of the javax.ejb.EJBContext.

  • DuplicateKeyException This exception is a subclass of CreateException. It is thrown by the ejbCreate method to indicate to the client that the requested entity bean could not be created because an entity bean with the same key already exists. Normally, the ejbCreate method will not mark the client's transaction for rollback; it is left to the client to take corrective measures.

  • FinderException This exception indicates an application-level error occurring in the find methods on the home interface of an entity bean. The bean provider throws this exception to flag an error in the ejbFind method; this exception is not used to indicate entity not found conditions; for entity not found conditions, the bean provider uses the ObjectNotFoundException, which is discussed next. Typically, the bean provider will not mark the client's transaction for rollback; it is left to the client to take corrective measures.

  • ObjectNotFoundException This exception indicates that the requested entity was not found by the ejbFind method. This exception can be thrown only by a finder method that returns a single object. Finder methods that return a collection object do not use this exception; such methods return an empty collection to indicate that no matching objects were found. The EJB container typically does not mark the transaction for rollback. The container or the bean provider does not mark the client's transaction for rollback when ObjectNotFoundException is encountered; it is left to the client to take corrective measures.

  • RemoveException This exception is thrown by the container when using container-managed persistence, or this exception can be thrown by the bean developer in ejbRemove. The client receiving this exception does not generally know if the entity bean was removed or not. The transaction may or may not be marked for rollback, although it is advisable that the bean developer should mark the transaction for rollback to leave the database in a consistent state. When bean-managed transaction is in effect, the bean method can determine the status of the transaction using the getStatus method on the javax.transaction.UserTransaction interface; when container-managed transaction is in effect, the bean method can determine the status of the transaction using the getRollbackOnly method of javax.ejb.EJBContext.




Practical J2ee Application Architecture
Practical J2EE Application Architecture
ISBN: 0072227117
EAN: 2147483647
Year: 2003
Pages: 111
Authors: Nadir Gulzar

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