User Tools

Site Tools


middleware:devel:ed:design-patterns

ED Design Patterns

Author Daniel Fisher
Date 2007/06/04

The purpose of this document is to describe some of the design patterns used in the ED business components.
Most of these are very simple, but aid in understanding the business processes.

Registry Classes

These classes should exist for every component in each project.
For instance, both PidManager and PersonManager have an implementation of Registry classes in the registry-manage project.
The purpose of this class is to hide the implementation details of using entity beans from the session bean components.
This makes the business logic in the session beans much easier to read.

RegistryFinder

Each instance of RegistryFinder must extend edu.vt.middleware.j2ee.common.CommonRegistryFinder.
This will provide access to all the general finder methods and reduce duplication of finder methods across projects.

Entity bean details should be completely hidden from calling parties.
Therefore methods should not accept entity beans as parameters and should never return entity beans as results.
Below is sample code that demonstrates how a RegistryFinder class should be implemented:

public final class RegistryFinder extends CommonRegistryFinder
{
  /** Log for this class */
  private static final Log LOG = LogFactory.getLog(RegistryFinder.class);
 
 
  /** 
   * <p>
   * Default constructor.
   * </p>
   */
  public RegistryFinder()
  {
    super(MYConstants.JNDI_PROPERTIES_FILE);
  }
 
 
  /** 
   * <p>
   * This returns whether the supplied UID exists in the registry.
   * </p>
   *
   * @param uid Long
   * @return boolean
   */
  public boolean personExists(final Long uid)
  {
    boolean exists = false;
    if (this.getLocalVTPeople(uid) != null) {
      exists = true;
    }
    return exists;
  }
 
 
  /**
   * <p>
   * This returns the birthdate for the supplied UID.
   * Returns null if no birthdate exists for the supplied UID.
   * </p>
   *
   * @param uid Long
   * @return PersonName
   */
  public Calendar getPersonBirthdate(final Long uid)
  {
    final LocalVTPeople bean = this.getLocalVTPeople(uid);
    Calendar birthdate = Calendar.getInstance();
    if (bean == null || bean.getBirthdate() == null) {
      birthdate = null;
    } else {
      birthdate.setTime(bean.getBirthdate());
    }
    return birthdate;
  }
 
 
  /**
   * <p>
   * This returns the VT email account sequence numbers for the supplied UID.
   * </p>
   *
   * @param uid Long
   * @return List - of account sequence numbers
   */
  public List getVTEmailAccounts(final Long uid)
  {
    final LocalVTPeopleEaddressesAction action =
      this.getLocalVTPeopleEaddressesAction();
    final Collection addresses = action.findByVtPeopleSeqnoAndType(
        uid, EaddressTypes.VT_ACCOUNT);
    final List seqnos = new ArrayList();
    if (addresses != null && addresses.size() > 0) {
      final Iterator i = addresses.iterator();
      while (i.hasNext()) {
        final LocalVTPeopleEaddresses bean = (LocalVTPeopleEaddresses) i.next();
        seqnos.add(bean.getVtPeopleEaddrSeqno());
      }
    }
    return seqnos;
  }
}

RegistryUpdater

Each instance of RegistryUpdater must extend edu.vt.middleware.j2ee.common.CommonRegistryFinder.
(Should it just extend the RegistryFinder class?…)
This will provide access to all the general finder methods and reduce duplication of finder methods across projects.

Entity bean details should be completely hidden from calling parties.
Therefore methods should not accept entity beans as parameters and should never return entity beans as results.
Below is sample code that demonstrates how a RegistryUpdater class should be implemented:

public final class RegistryUpdater extends CommonRegistryFinder
{
  /** Log for this class */
  private static final Log LOG = LogFactory.getLog(RegistryUpdater.class);
 
 
  /** 
   * <p>
   * Default constructor.
   * </p>
   */
  public RegistryUpdater()
  {
    super(MYConstants.JNDI_PROPERTIES_FILE);
  }
 
 
  /**
   * <p>
   * This attempts to add a PID entry for the supplied UID.
   * </p>
   *
   * @param uid to add pid entry for
   * @param pid to add
   * @param aup whether the acceptable use policy
   * was accepted
   * @param statusCode user status type code
   * @param transitionCode user transition type code
   * @throws ApplicationServerException if the method fails
   * @throws CreateFailedException if the PID cannot be added
   */
  public void addPersonPid(final Long uid,
                           final String pid,
                           final Boolean aup,
                           final String statusCode,
                           final String transitionCode)
    throws ApplicationServerException
  {
    final LocalVTUseridsAction action = this.getLocalVTUseridsAction();
    final LocalVTUserids id = action.create(
      uid, UseridTypes.VT_PID, pid, aup, statusCode, transitionCode);
    if (id == null) {
      final String msg = "Could not create UUPID for UID "+uid;
      if (LOG.isErrorEnabled()) {
        LOG.error(msg);
      }
      throw new CreateFailedException(msg);
    }
    if (LOG.isInfoEnabled()) {
      LOG.info("Created UUPID entry "+pid+" for UID "+uid);
    }
    id.setCreatedBy(PMConstants.CREATOR_ID);
    id.setCreatedDate(new Timestamp(System.currentTimeMillis()));
  }
 
 
  /**
   * <p>
   * This attempts to remove the PID entries for the supplied UID,
   * including any passwords.
   * </p>
   *
   * @param uid to remove pid entry for
   * @throws ApplicationServerException if the method fails
   * @throws FinderFailedException if the PID cannot be found
   * @throws RemoveFailedException if the PID cannot be removed
   */
  public void removePersonPid(final Long uid)
    throws ApplicationServerException
  {
    final LocalVTUserids id = this.getLocalVTUserids(uid);
    try {
      id.remove();
      if (LOG.isInfoEnabled()) {
        LOG.info("Removed PID for UID "+uid);
      }
    } catch (RemoveException e) {
      if (LOG.isErrorEnabled()) {
        LOG.error("Could not remove PID "+id.getUserid()+
                  " for UID "+uid, e);
      }
      throw new RemoveFailedException(e);
    }
  }
 
 
  /**
   * <p>
   * This attempts to set the shelve date of the PID entries for
   * the supplied UID.
   * </p>
   *
   * @param uid to modify shelve date for
   * @param timestamp to set
   * @throws ApplicationServerException if the method fails
   * @throws FinderFailedException if the PID cannot be found
   */
  public void setPersonPidShelveDate(final Long uid, final Timestamp timestamp)
    throws ApplicationServerException
  {
    final LocalVTUserids id = this.getLocalVTUserids(uid);
    id.setShelveDate(timestamp);
    id.setModifiedBy(PMConstants.CREATOR_ID);
    id.setModifiedDate(new Timestamp(System.currentTimeMillis()));
  }
 
 
  /**
   * <p>
   * This returns the LocalVTUserids bean for the supplied
   * UID that contains the UUPID.
   * A ApplicationServerException is thrown if the UUPID
   * cannot be found or the person has more than one UUPID.
   * </p>
   *
   * @param uid
   * @return LocalVTUserids
   * @throws ApplicationServerException if the method fails
   * @throws FinderFailedException if the PID cannot be found or this person
   * has more than one PID
   */
  private LocalVTUserids getLocalVTUserids(final Long uid)
    throws ApplicationServerException
  {
    final LocalVTUseridsAction action = this.getLocalVTUseridsAction();
    final Collection ids = action.findByVtPeopleSeqnoAndType(
      uid, UseridTypes.VT_PID);
    if (ids == null || ids.isEmpty()) {
      final String msg = "Could not find UUPID record for UID "+uid;
      if (LOG.isErrorEnabled()) {
        LOG.error(msg);
      }
      throw new FinderFailedException(msg);
    } else if (ids.size() > 1) {
      final String msg = "Person with UID "+uid+" has "+ids.size()+" PIDs.";
      if (LOG.isErrorEnabled()) {
        LOG.error(msg);
      }
      throw new FinderFailedException(msg);
    }
    return (LocalVTUserids) ids.iterator().next();
  }
}

Validator classes

These classes should exist for every component in each project.
For instance, both PidManager and PersonManager have an implementation of a Validator class in the registry-manage project.
The purpose of this class is to keep validation logic out of the session beans and reduce the number of lines of code each session bean contains.
This makes the business logic in the session beans much easier to read.

Validator must be implemented as utility classes, therefore they should contain no public constructor and all methods must be static.
Below is sample code that demonstrates how a Validator class should be implemented:

public final class Validator
{
  /** Log for this class */
  private static final Log LOG = LogFactory.getLog(Validator.class);
 
 
  /** 
   * <p>
   * Default constructor.
   * </p>
   */
  private Validator() {}
 
 
  /** 
   * <p>
   * This returns whether the supplied PID is valid.
   * </p>
   *
   * @param pid to verify
   * @return whether the supplied PID is valid
   */
  public static boolean isValidPid(final String pid)
  {
    boolean valid = false;
    if (pid != null) {
      // PIDs must be between 3-8 characters long
      if (pid.length() >= PMConstants.PID_MIN_LENGTH &&
          pid.length() <= PMConstants.PID_MAX_LENGTH)
      {
        // PIDs must start with a letter, and be composed of only alpha-nums.
        if (pid.matches("[\\p{Alpha}][\\p{Alnum}]+")) {
          valid = true;
        }
      }
    }
    return valid;
  }
}
middleware/devel/ed/design-patterns.txt · Last modified: 2015/06/01 12:02 (external edit)