Realization of the Manage Campaigns Use Case Package


The following subsections describe use case realization for use cases in the Manage Campaigns package. Please refer to Chapter 1 and Chapter 2 for use case descriptions of this package.

Create Campaigns Use Case

In this section, we define and implement the components necessary for the implementation of the Create Campaigns use case. In this section we will implement a one-to-many relationship existing between a PortalAlliance entity bean and Campaign entity beans (refer to Figure 7-10) using a collected-valued container-managed relationship PortalAlliance-Campaign. This discussion is continuation of the material discussed in Chapter 6.

click to expand
Figure 7-10: Sequence diagram for updateNPORegistration

Discovering Business Interface Methods

In this use case, we define the Campaign business interface. We pick up the development of this use case from where Chapter 5 left off. There are numerous calls from the presentation tier for satisfying this use case because the process of creating a campaign involves several user interactions; these user interactions include checking existence of a Portal-Alliance (provided by the site administrator) for which campaigns are to be created, followed by search and selection of the desired NPO for which a campaign needs to be created; finally the campaign information is stored in the data store for the given Portal-Alliance. Please refer to Chapters 1 and 2 for complete details of this use case; Chapter 5 exhaustively explains the various user interaction within the context of the Struts framework and the associated Shared Request Handler Pattern. Although we have been progressively building this use case from use case analysis and implementing the presentation tier, nothing precludes us from developing the Create Campaign business-tier functionality in parallel with presentation-tier development; you will recall that the business delegate pattern used in the presentation tier offers the point of integration between the presentation tier and the business tier. Once the development of the presentation tier and business tier is accomplished, the integration between the two tiers is achieved using the business delegate (presentation tier side) and session fa ade (business tier side) with the intervening service locator for getting the references to business-services in the business tier.

We begin by identifying the methods required on the new Campaign business interface. The presentation tier will need the method addNewCampaign on the new business interface to add campaign details. The following code segment shows the method in the business interface.

 public interface Campaign {     void addNewCampaign(CampaignDTO campaign)          throws RemoteException ,NPONotFoundException,          AdminNotFoundException,PortalAllianceNotFoundException,          GCAppException; } 

Observe that this method will require CampaignDTO to carry the campaign information across tiers. CampaignDTO has complete information on the campaign being created, as well as the Portal ID with which the campaign is to be associated. Refer to the accompanying CD-ROM for CampaignDTO implementation. However, before the campaign creation process can proceed, the site administrator has to ensure that the corresponding portal ID is valid and active in the system (from the use cases you will recall that only site administrator has to specify the portal ID; for portal-alliance administrator the portal ID is detected by AdminID association). We must add a method to support checking of the portal ID in support of site administrator process flow.

 public interface SiteAdmin {     ... rest of the methods ...     boolean isPortalIDValid(String portalID)     throws GCAppException, RemoteException; } 

Implementing Business Interface

In Chapter 5, we took the approach of developing each package as a separate subsystem. Building upon this approach, we create all campaign-related components with their own package. Figure 7-11 illustrates a class diagram for realizing this use case.

click to expand
Figure 7-11: Create Campaign class diagram

For realizing the Create Campaign use case, we have several interacting classes and patterns that work harmoniously to provide a cohesive solution. The CampaignBean class implements the Session Fa ade pattern, whose Campaign business interface is exposed to the clients. The DTO pattern is implemented using the CampaignDTO JavaBean. The Campaign domain object (this is different from the Campaign session fa ade and is discussed in Chapter 6) is used for persisting campaign data.

The addNewCampaign method on the CampaignBean will first retrieve references to the PortalAlliance entity bean and NPO entity bean; it then creates a new instance of the Campaign entity bean with the information provided by the CampaignDTO; subsequent to this, the convenience method addCampaign on the PortalAlliance domain-object interface is invoked to add the newly created campaign entity bean to the collection-valued container-managed relationship PortalAlliance-Campaign as shown in Figure 7-11. The PortalAlliance entity bean and related methods are explained in detail in Chapter 6.

The domain model of Figure 6-1 shows the relationship between the Campaign entity bean and the PortalAlliance entity bean. Although a campaign can only be related to a single PortalAlliance, a PortalAlliance can have 0 or more (0.*) campaign(s). With the same token, a campaign can only be associated with a single NPO, while for a given NPO there may be 0 or more campaign(s).

In order to persist these relationships, we must first establish a relationship between the campaign and the NPO entities. Because there should always be an NPO for each campaign (multiplicity of ‘1’ for the npo role provides this constraint), the Campaign entity bean ensures this linkage by accepting a reference to the NPO bean in its create method, as shown here:

 try{     ... Rest of the Code ...     Campaign newCampaign =         campaignHome.create(startDate, endDate,         campaign.getRegionCode(), (NPOLocal)npo);     ... Rest of the Code ... } 

This code segment creates the newCampaign object. Observe that during campaign creation, the primary key value CampaignID is not being provided since the CampaignID is system generated. Once the campaign entity bean is created, it has to be related to the PortalAlliance entity bean. This is accomplished by calling the addCampaign convenience method available on the PortalAlliance domain-object interface of the PortalAlliance entity bean, as shown in the following code. Please refer to Chapter 6 for additional details.

 portalAlliance.addCampaign(newCampaign); 

Update Campaigns Use Case

In this section, we identify and implement the components needed for the realization of the Update Campaigns use case. A large part of this use case was developed in Chapter 5 to address the needs of the presentation tier. The presentation tier expects a collection of CampaignDTO object, which it uses for creating a dynamic view; subsequently the user updates various campaigns, and the presentation tier repackages the updated CampaignDTO(s) and sends it back to the business tier.

Discovering Business Interface Methods

We continue to add to the Campaign business interface discussed in the preceding section; this is to ensure that logically related functionality is encapsulated within the same interface and to avoid unnecessary proliferation of business interfaces. We also use the same CampaignDTO that was used as part of the Create Campaign use case. Therefore, we have most of the essential classes and interfaces already available to us for realizing this use case.

The following interface methods are added to the Campaign interface for realizing the Update Campaigns use case.

 public interface Campaign {     ... Other Methods ...     /* Method takes a Collection of type CampaignDTO from the Presentation Tier*/     void updateCampaigns(Collection campaigns )          throws RemoteException , CampaignNotFoundException, GCAppException;     /* Method provides a Collection of type CampaignDTO to the Presentation Tier*/     Collection getCampaigns(String portalID, String adminID, String regionCode)         throws RemoteException , PortalAllianceNotFoundException,         CampaignNotFoundException, AdminNotFoundException, GCAppException; } 

Implementing the Business Interface

Since we are reusing the same business interface and associated components that were used in the realization of the Create Campaigns use case, the class diagram represented by Figure 7-11 is still relevant for the following discussion.

We now examine some interesting aspects of the getCampaigns business method of the Campaign session bean.

 public Collection getCampaigns(String portalID,String adminID,   String regionCode) ... Rest of the Code ...   if (adminID != null) {       /* This branch applicable only for Portal-Alliance Administrator        * because the Portal ID association is derived from adminID */       Admin admin = getAdmin(adminID); //Get Admin Entity bean       portalAlliance = admin.getAlliance(); //Get PortalAlliance Entity bean   } else if (portalID != null) {       /* This branch applicable only for Site Administrator        * because the portalID is explicitly provided by administrator */        /* Get PortalAlliance Entity bean */        portalAlliance = getPortalAlliance(portalID);   }   /*Collection of Campaign Entity bean references */   Collection campaigns = null;   try {    if (regionCode == null)       campaigns = portalAlliance.getCampaigns();    else       campaigns = portalAlliance.getRegionalCampaigns(regionCode);   } catch (FinderException fe) {     ... rest of the code ...   } ... code for verification appear here ...    /* Finally create a Collection of DTOs */    ArrayList results = new ArrayList();    Iterator itr = campaigns.iterator();    while (itr.hasNext()) {       Campaign campaign = (Campaign) itr.next();       // Get the cmr-field npo (i.e. the NPO Entity bean related to the Campaign)       NPO npo = campaign.getNpo();       CampaignDTO theCampaignDTO =       new CampaignDTO(npo.getEin(), portalAlliance.getPortalID());       theCampaignDTO.setCity(npo.getCity());       theCampaignDTO.setCampaignID(campaign.getCampaignID());       theCampaignDTO.setCountry(npo.getCountry());       theCampaignDTO.setEndDate(campaign.getEndDate().toString());       theCampaignDTO.setNpoName(npo.getNpoName());       theCampaignDTO.setRegionCode(campaign.getRegionCode());       theCampaignDTO.setStartDate(campaign.getStartDate().toString());       theCampaignDTO.setState(npo.getState());       results.add(theCampaignDTO); //Add to the Collection of DTOs   }   return results; } 

In this snippet, observe that the portalID is provided by the presentation tier when the user is a site administrator, whereas an adminID is provided by the presentation tier when the use is a portal-alliance administrator. The code also demonstrates retrieval of the Campaign entity bean collection for the cmr-field campaigns (the campaigns cmr-field is specified in the deployment descriptor subordinate to the ejb-relation element) and subsequent packaging of DTOs in a Collection object for use by the presentation tier.

In Chapter 6, we observed that the PortalAlliance entity bean has a helper getRegionalCampaigns method; this convenience method has been specially designed to accommodate the filtering of campaign entities based on a given region code; please refer to Chapter 6 for a complete discussion on how EJB QL is being used to accomplish this filtering.

In the preceding code snippet, we observed the packaging of DTOs for the presentation tier; the following code snippet for the updateCampaigns method of the campaign session bean illustrates the use of collection of updated DTOs received from the presentation tier, and its effect on the current transaction.

 public void updateCampaigns(Collection campaigns)     throws CampaignNotFoundException, GCAppException {     ... Other Code for checking pre-conditions ...     Iterator itr = campaigns.iterator();     while (itr.hasNext()) {          CampaignDTO campaignDTO = (CampaignDTO) itr.next();         /* Stateless bean expects that the client remember and          * resend the Campaign ID */          if (!campaignDTO.isFieldModified(CampaignDTO.CAMPAIGN_ID)){              ctx.setRollbackOnly();              throw new GCAppException("error.MustProvideCampaignID",                     "Campaign ID must be provide to update campaign");              }              // Get reference to the Campaign entity bean              Campaign campaign =                  getCampaign((Integer) campaignDTO.getCampaignID());              // Set all cmp-fields that need to be changed in the Campaign entity bean              if (campaignDTO.isFieldModified(CampaignDTO.START_DATE))                  campaign.setStartDate(Date.valueOf(campaignDTO.getStartDate()));              if (campaignDTO.isFieldModified(CampaignDTO.END_DATE))                  campaign.setEndDate(Date.valueOf(campaignDTO.getEndDate()));              if (campaignDTO.isFieldModified(CampaignDTO.REGION_CODE))                  campaign.setRegionCode(campaignDTO.getRegionCode());       }     } } 

From this snippet, it is apparent that the stateless nature of the session bean expects that DTOs sent to the client, using the getCampaigns method, must be cached by the client. Once the DTOs are updated by the client, the client must send the complete DTOs back to the campaign session bean's updateCampaigns method and ensure that the primary key campaignID is present in all DTOs for the updates to be successful. Please observe that failure to get a campaignID on any of the DTOs will result in marking of the transaction for rollback.

The campaign updates are expected to be low volume, therefore we did not hesitate using collection-valued portalAlliance.getCampaigns() or portalAlliance.getRegionalCampaigns(regionCode) methods within the getCampaigns method of the CampaignBean. Normally, high-volume read only data must be extracted using patterns like DAO (Data Access Object) [Core] that directly queries the database rather than obtaining a collection of references to the entity bean. EJBs are heavy-weight objects requiring system resources for their creation, life-cycle management, and network overhead involved in their access. However, for updating high volume data, one should not circumvent entity beans since the business logic for ensuring data integrity and consistency resides in the entity bean methods; directly manipulating data would be breaking away from the object-oriented encapsulation technique, which will lead to manageability and modularity issues.

Figure 7-12 depicts the implementation of the updateCampaigns business method defined in the campaign bean's business interface.

click to expand
Figure 7-12: Sequence diagram for updateCampaigns

Note

For marshalling tabular data from a JDBC ResultSet to the client without the hassle of converting it to DTOs and then back to tabular list on the client side, a special technique is demonstrated in the book EJB Design Patterns [EJB Patterns]; the design pattern employed is called Data Transfer Rowset.

Campaign Session Bean Deployment Descriptors

The declarations in the deployment descriptors for the campaign session bean are similar to descriptors we discussed in the section "SiteAdmin Session Bean Deployment Descriptors." This section discusses the transaction-related deployment descriptors for the campaign session bean.

The addNewCampaign and updateCampaigns methods modify the application state by adding or changing the Campaign entity beans, therefore these methods are specified with the transaction attribute value of Required. The getCampaigns method on the PortalAlliance entity bean returns a collection as a result of a one-to-many relationship existing between the PortalAlliance entity bean and Campaign entity beans. The EJB 2.0 specification mandates that the iterator obtained over a collection in a container-managed relationship must be used within the transaction context in which the iterator was obtained; therefore the getCampaigns method of the PortalAlliance entity bean (discussed in Chapter 6) is associated with the transaction attribute value of Mandatory; this constraint automatically enforces a requirement on the getCampaigns method of the campaign session bean to call the getCampaigns method of the PortalAlliance entity bean with a transaction attribute Required. The following segment shows the appropriate configuration semantics for the Campaign session bean and PortalAlliance entity bean.

 <container-transaction>    <method>        <ejb-name>CampaignEJB</ejb-name>        <method-name>addNewCampaign</method-name>    </method>    <method>        <ejb-name>CampaignEJB</ejb-name>        <method-name>updateCampaigns</method-name>    </method>    <method>        <ejb-name>CampaignEJB</ejb-name>        <method-name>getCampaigns</method-name>    </method>    <method>        <ejb-name>CampaignEJB</ejb-name>        <method-name>getFeaturedNPOs</method-name>    </method>    <trans-attribute>Required</trans-attribute> </container-transaction> <container-transaction>     <method>         <ejb-name>PortalAllianceEntityEJB</ejb-name>          <method-name>getCampaigns</method-name>     </method>     <trans-attribute>Mandatory</trans-attribute> </container-transaction> 




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