Appendix E. Subsystem Façade Pattern Specification

Context

A set of database-stored business entities needs to be made accessible.

Problem

Database-stored business entities and services need to be exposed to remote clients. However, this could result in a tight coupling between the clients and the business entities, making maintenance or updates difficult. Also, having the database access code mixed with the business code would make the migration to a new database difficult.

Forces

• Simplify the interaction with clients external to the subsystem by hiding the complexity of the internal entities.

• Allow looser coupling with the database provider as data retrieval and updates are abstracted via JPA managers.

• Improve maintenance and portability by hiding subsystem internals and abstracting database access.

Solution

Group related business entities into a subsystem and use a Session Façade to encapsulate the business entities. Remote clients interact with the Session Façade via a coarse-grained service. Access to the database is abstracted away by the Business Entity Manager.

Figure E.1 shows the structural view of the participating elements.

Figure E.1. Static view of the Subsystem Façade participants

image

The participants are as follows:

Subsystem. The subsystem contains the business entities that the façade is shielding.

Session Façade. The Session Façade is used to hide subsystem business entities and expose coarse-grained services. Some of the basic exposed services provide access to a subsystem entity based on its id as well as retrieving all entities of a given type.

Business Entity. The Business Entity role is to carry data that is exchanged and manipulated by the Session Façade.

Business Entity Manager. The Business Entity Manager is used to create, update, retrieve, and delete business entities from the data source.

Datasource: The Datasource represents the connection to the database that is used to store the entities.

Figure E.2 shows a behavioral view of the participants. The client calls the createEntity() operation of the Session Façade. The Session Façade creates a new Business Entity and sets the entity’s attributes. The Session Façade then creates a new Business Entity Manager and calls the create operation that inserts the new entity into the database via the Datasource.

Figure E.2. Behavioral view of the Subsystem Façade participants

image

Sample Code

This section shows an example application of the pattern. Figure E.3 gives an overview of the different classes involved, and the listings that follow detail the associated code.

Figure E.3. Overview of the sample participants

image

Listing E.1 shows an example of a Session Façade with the creation of a JPA manager (BidManager), the retrieval of a specific entity based on its id (getBid), and the retrieval of all entities (getAllBids).

Listing E.1. Session Façade Example: AuctionManagementFacade.java

package auctionmanagement.facade;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.PersistenceException;
import auctionmanagement.entities.Auction;
import auctionmanagement.entities.Bid;
import auctionmanagement.entities.Payment;
import auctionmanagement.entities.controller.AuctionManager;
import auctionmanagement.entities.controller.BidManager;
import auctionmanagement.entities.controller.PaymentManager;

/**
* Session Bean implementation class AuctionManager
*/
@Stateless
public class AuctionManagementFacade implements AuctionFacadeInterface {
   private AuctionManager auctionManager = new AuctionManager();
   private BidManager bidManager = new BidManager();
   private PaymentManager paymentManager = new PaymentManager();

   /**
    * Default constructor.
    */

   public AuctionManagementFacade() {
      // TODO Auto-generated constructor stub
   }

   public Auction getAuction(long auctionId)
     throws PersistenceException {
      return auctionManager.findAuctionByAuctionId(auctionId);
   }

   public List<Auction> getAllAuctions()
     throws PersistenceException{
      return auctionManager.getAllAuctions();
   }
   public Bid getBid(long bidId)
     throws PersistenceException {
      return bidManager.findBidByBidId(bidId);
   }

   public List<Bid> getAllBids() throws PersistenceException {
      return bidManager.getAllBids();
   }

   public Payment getPayment(long paymentId)
     throws PersistenceException {
      return paymentManager.findPaymentByPaymentId(paymentId);
   }

   public List<Payment> getAllPayments()
     throws PersistenceException {
      return paymentManager.getAllPayments();
   }

   // Add your business methods here
}

Listing E.2 shows the details of the Bid.java JPA entity with declaration of JPA queries (getBidByUserid, getAllBids, getAllBidsOrdered), the entity ID (bidid), one attribute (userid), their getters and setters, as well as the entity serial ID (serialVersionUID).

Listing E.2. Business Object Example: Bid.java

package auctionmanagement.entities;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;

@Entity
@NamedQueries({
@NamedQuery(name="getBidByUserid",
   query = "SELECT b FROM Bid b WHERE b.userid = :userid"),
@NamedQuery(name="getAllBids", query = "SELECT b FROM Bid b"),
@NamedQuery(name="getAllBidsOrdered",
   query = "SELECT b FROM Bid b ORDER BY b.bid_id")})

public class Bid implements Serializable {
   @Id
   @Column(name="BID_ID")
   private long bidid;
   private long userid;
   private static final long serialVersionUID = 1L;

   public long getBidid() {
      return this.bidid;
   }

   public long getUserid() {
      return userid;
   }

   public void setUserid(long userid) {
      this.userid = userid;
   }

   public void setBidid(long bidid) {
      this.bidid = bidid;
   }

}

Listing E.3 shows the details of the BidManager.java JPA manager with the retrieval of a JPA entity manager (getEntityManager), entity CRUD operations (createBid, findBidByBidid, updateBid, and deleteBid), attribute queries (getBidByUserid), and operations to retrieve the entities (getAllBids, getAllBidsOrdered).

Listing E.3. Business Object Manager Example: BidManager.java

package auctionmanagement.entities.controller;

import java.sql.Timestamp;
import users.entities.Bidder;
import auctionmanagement.entities.Auction;
import auctionmanagement.entities.Bid;
import com.ibm.jpa.web.JPAManager;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
import javax.persistence.RollbackException;
import com.ibm.jpa.web.NamedQueryTarget;
import com.ibm.jpa.web.Action;
import javax.persistence.Persistence;
import javax.persistence.Query;
import java.lang.String;
import java.util.List;

@JPAManager(targetEntity=auctionmanagement.entities.Bid.class)
@SuppressWarnings("unchecked")
public class BidManager {

   public BidManager() {

   }

   private EntityManager getEntityManager() {
      EntityManagerFactory emf = Persistence
        .createEntityManagerFactory("AuctionManagement");
         return emf.createEntityManager();
   }

   @Action(Action.ACTION_TYPE.CREATE)
   public String createBid(Bid bid) throws PersistenceException {
       EntityManager em = getEntityManager();
       try {
           em.getTransaction().begin();
           em.persist(bid);
           em.getTransaction().commit();
       } catch (PersistenceException  ex) {
           if (ex instanceof RollbackException){
               try {
                   if (em.getTransaction().isActive()) {
                       em.getTransaction().rollback();
                   }
               } catch (PersistenceException e) {
                   e.printStackTrace();
                   throw e;
               }
           } else {
               throw ex;
           }
       } finally {
           em.close();
       }

       return "";
   }

   @Action(Action.ACTION_TYPE.DELETE)
   public String deleteBid(Bid bid) throws PersistenceException {
       EntityManager em = getEntityManager();
       try {
           em.getTransaction().begin();
           bid = em.merge(bid);
           em.remove(bid);
           em.getTransaction().commit();
       } catch (PersistenceException  ex) {
           if (ex instanceof RollbackException){
               try {
                   if (em.getTransaction().isActive()) {
                       em.getTransaction().rollback();
                   }
               } catch (PersistenceException e) {
                   e.printStackTrace();
                   throw e;
               }
           } else {
               throw ex;
           }
       } finally {
           em.close();
       }
       return "";
   }

   @Action(Action.ACTION_TYPE.UPDATE)
   public String updateBid(Bid bid) throws PersistenceException {
       EntityManager em = getEntityManager();
       try {
           em.getTransaction().begin();
           bid = em.merge(bid);
           em.getTransaction().commit();
       } catch (PersistenceException  ex) {
           if (ex instanceof RollbackException){
               try {
                   if (em.getTransaction().isActive()) {
                       em.getTransaction().rollback();
                   }
               } catch (PersistenceException e) {
                   e.printStackTrace();
                   throw e;
               }

           } else {
               throw ex;
           }
       } finally {
           em.close();
       }
       return "";
   }

   @Action(Action.ACTION_TYPE.FIND)
   public Bid findBidByBidId(long bidId) {
      Bid bid = null;
      EntityManager em = getEntityManager();
      try {
          bid = (Bid) em.find(Bid.class, bidId);
      } finally {
          em.close();
      }
      return bid;
   }

   @Action(Action.ACTION_TYPE.NEW)
   public Bid getNewBid() {
       Bid bid = new Bid();
       return bid;
   }

   @NamedQueryTarget("getBidByBidTime")
   public List<Bid> getBidByBidTime(Timestamp bidTime) {
       EntityManager em = getEntityManager();
       List<Bid> results = null;
       try {
           Query query = em.createNamedQuery("getBidByBidTime");
           query.setParameter("bidTime", bidTime);
           results = (List<Bid>) query.getResultList();
       } finally {
           em.close();
       }
       return results;
   }

   @NamedQueryTarget("getBidByAuction")
   public List<Bid> getBidByAuction(Auction auction) {
       EntityManager em = getEntityManager();
       List<Bid> results = null;
       try {
           Query query = em.createNamedQuery("getBidByAuction");

           query.setParameter("auction", auction);
           results = (List<Bid>) query.getResultList();
       } finally {
           em.close();
       }
       return results;
   }

   @NamedQueryTarget("getBidByBidder")
   public List<Bid> getBidByBidder(Bidder bidder) {
       EntityManager em = getEntityManager();
       List<Bid> results = null;
       try {
           Query query = em.createNamedQuery("getBidByBidder");
           query.setParameter("bidder", bidder);
           results = (List<Bid>) query.getResultList();
       } finally {
           em.close();
       }
       return results;
   }

   @NamedQueryTarget("getAllBids")
   public List<Bid> getAllBids() {
       EntityManager em = getEntityManager();
       List<Bid> results = null;
       try {
           Query query = em.createNamedQuery("getAllBids");
           results = (List<Bid>) query.getResultList();
       } finally {
           em.close();
       }
       return results;
   }

   @NamedQueryTarget("getAllBidsOrdered")
   public List<Bid> getAllBidsOrdered() {
       EntityManager em = getEntityManager();
       List<Bid> results = null;
       try {
           Query query = em.createNamedQuery("getAllBidsOrdered");
           results = (List<Bid>) query.getResultList();
       } finally {
           em.close();
       }
       return results;
   }
}

Pattern Composition

The Subsystem Façade pattern is a compound pattern that is composed of the Session Façade and the Data Access Object patterns1 as shown in Figure E.4.

Figure E.4. Subsystem Façade composed patterns

image

In Figure E.4 we see that the two composed patterns are linked through the BusinessObject parameter. The SessionFaçade shields one or more (1..*) BusinessObjects. We also see that for each BusinessObject there is one corresponding DataAccessObject. The BusinessObjects bound to the SessionFaçade and DataAccessObject BusinessObject parameters are the entities owned by the subsystem.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset