Development

UPDATE 1/17/11:  I haven’t had a lot of time to work on this but I’ve gotten a logging service established and fixed the memory leak in the Session State Bean:

package businessLogic;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
import javax.ejb.TimerHandle;
import javax.ejb.TimerService;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceException;
import javax.security.auth.login.LoginException;

import appServices.LogBeanLocal;

import entities.User;
import facade.UserBeanLocal;

/**
 * Session Bean implementation class SessionStateBean
 */
@Stateful(mappedName = "SessionState")
public class SessionStateBean implements SessionStateBeanRemote, TimedObject {
	private List<Session> sessionList;

	@EJB
	private UserBeanLocal userBeanLocal;

	@EJB
	private LogBeanLocal logBeanLocal;

	private SessionContext sc;
	private TimerHandle timerHandle = null;

	// TODO Property
	private boolean pSessionsExpire = true;

	// TODO Property
	private long pSessionCleanupInterval = 86400000L;

	/**
	 * Default constructor.
	 */
	public SessionStateBean() {
		sessionList = new ArrayList<Session>();
		// Property: SessionCleanupInterval in millis
		initializeTimer(pSessionCleanupInterval, pSessionCleanupInterval,
				"SessionTimer");
	}

	public boolean isLoggedIn(String username)
			throws DependecyInjectionException, ValueOutOfBoundsException {
		if (userBeanLocal == null) {
			throw new DependecyInjectionException(
					"userBeanLocal with JNDI name User not injected");
		}

		User user = userBeanLocal.getUserByUsername(username);
		int uid = -1;

		if (user == null) {
			throw new PersistenceException("Entity not found");
		}

		uid = user.getUid();

		if (uid < 0) {
			throw new ValueOutOfBoundsException(
					"User.getUid() should never return a negative value");
		}

		return isLoggedIn(uid);
	}

	public boolean isLoggedIn(int uid) {
		for (Session session : sessionList) {
			if (session.getUid() == uid) {
				return true;
			}
		}

		return false;
	}

	public void logIn(String username, String password, String phpsessid)
			throws LoginException {
		User user = userBeanLocal.getUserByUsername(username);
		String passHash = "";

		if (user == null) {
			throw new LoginException("User not found");
		}

		try {
			passHash = sha1(password);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			System.exit(-1);
		}

		logIn(user.getUid(), passHash, phpsessid);

	}

	public void logOut(String username) throws LoginException {
		User user = userBeanLocal.getUserByUsername(username);

		if (user == null) {
			throw new LoginException("Username not found.");
		}

		logOut(user.getUid());
	}

	public void logOut(int uid) throws LoginException {
		for (Session session : sessionList) {
			if (session.getUid() == uid) {
				sessionList.remove(session);
				logBeanLocal.logMessage("SessionStateBean: user " + uid
						+ " logged out");
				return;
			}
		}

		throw new LoginException("User not logged in.");
	}

	public void killSession(String sessionId) {
		for (Session session : sessionList) {
			if (session.getPhpsessid() == sessionId) {
				sessionList.remove(session);
				logBeanLocal.logMessage("SessionStateBean: killed session "
						+ sessionId);
			}
		}

		throw new EntityNotFoundException("Session not found.");
	}

	public void logIn(int uid, String passHash, String phpsessid)
			throws LoginException {
		User user = userBeanLocal.getUserById(uid);

		if (user == null) {
			throw new LoginException("User not found.");

		}

		if (user.getPassHash() != passHash) {
			throw new LoginException("Wrong password");
		}

		for (Session session : sessionList) {
			if (session.getUid() == uid && session.getPhpsessid() == phpsessid) {
				/*
				 * I'm doing this because I want users to be able to have
				 * multiple sessions open without filling my session table
				 * uselessly.
				 * 
				 * I still haven't decided if I'm going to implement a timeout
				 * or other cleanup system to expire closed sessions since
				 * there's no way for the servlet container to notify us when a
				 * session is no longer active.
				 * 
				 * DONE There's a definite memory leak here as sessions don't
				 * expire. Added timer to kill sessions after they expire.
				 */
				throw new LoginException("Already logged in");
			}
		}

		logBeanLocal.logMessage("SessionStateBean: user " + uid + " logged in");

		Session session = new Session();
		session.setPhpsessid(phpsessid);
		session.setTimestamp(Calendar.getInstance().getTime());
		session.setUid(uid);
		sessionList.add(session);
	}

	private String sha1(String string) throws NoSuchAlgorithmException {
		MessageDigest md;
		md = MessageDigest.getInstance("SHA1");
		md.update(string.getBytes());
		byte hashCode[] = md.digest();

		char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'A', 'B', 'C', 'D', 'E', 'F' };

		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < hashCode.length; i++) {
			sb.append(hexDigit[(hashCode[i] >> 4) & 0x0f]);
			sb.append(hexDigit[hashCode[i] & 0x0f]);
		}

		return sb.toString();
	}

	/**
	 * @param sc
	 *            the sc to set
	 */
	public void setSc(SessionContext sc) {
		this.sc = sc;
	}

	/**
	 * @return the sc
	 */
	public SessionContext getSc() {
		return sc;
	}

	/**
	 * @param timerHandle
	 *            the timerHandle to set
	 */
	public void setTimerHandle(TimerHandle timerHandle) {
		this.timerHandle = timerHandle;
	}

	/**
	 * @return the timerHandle
	 */
	public TimerHandle getTimerHandle() {
		return timerHandle;
	}

	private void initializeTimer(long initialDuration, long intervalDuration,
			String timerName) {
		TimerService ts = sc.getTimerService();
		Timer timer = ts.createTimer(initialDuration, intervalDuration,
				timerName);
		setTimerHandle(timer.getHandle());
	}

	/**
	 * TODO add javadoc
	 */
	public void ejbTimeout(Timer timer) {
		// TODO Property: SessionsExpire=true
		if (pSessionsExpire) {

			// TODO Log messages: SessionStateBean: starting session cleanup
			logBeanLocal
					.logMessage("SessionStateBean: starting session cleanup");

			// cleans up stored session objects after they expire
			Calendar expiryTime = Calendar.getInstance();
			// TODO change this to use properties so we can dynamically set
			// TODO the expiration interval.
			expiryTime.add(Calendar.HOUR, -24);
			Date timestamp = expiryTime.getTime();

			for (Session session : sessionList) {
				if (session.getTimestamp().before(timestamp)) {
					logBeanLocal
							.logMessage("SessionStateBean: deleting session "
									+ session.getPhpsessid());
					sessionList.remove(session);
				}
			}

		}
	}

}

UPDATE 1/3/11: I’ve got one business logic bean done. It’s a Stateful Session Bean that maintains the list of sessions and handles login and logout calls:

package businessLogic;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateful;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceException;
import javax.security.auth.login.LoginException;

import entities.User;
import facade.UserBeanLocal;

/**
 * Session Bean implementation class SessionStateBean
 */
@Stateful(mappedName = "SessionState")
public class SessionStateBean implements SessionStateBeanRemote {
	private List<Session> sessionList;

	@EJB
	private UserBeanLocal userBeanLocal;

	/**
	 * Default constructor.
	 */
	public SessionStateBean() {
		sessionList = new ArrayList<Session>();
	}

	public boolean isLoggedIn(String username)
			throws DependecyInjectionException, ValueOutOfBoundsException {
		if (userBeanLocal == null) {
			throw new DependecyInjectionException(
					"userBeanLocal with JNDI name User not injected");
		}

		User user = userBeanLocal.getUserByUsername(username);
		int uid = -1;

		if (user == null) {
			throw new PersistenceException("Entity not found");
		}

		uid = user.getUid();

		if (uid < 0) {
			throw new ValueOutOfBoundsException(
					"User.getUid() should never return a negative value");
		}

		return isLoggedIn(uid);
	}

	public boolean isLoggedIn(int uid) {
		for (Session session : sessionList) {
			if (session.getUid() == uid) {
				return true;
			}
		}

		return false;
	}

	public void logIn(String username, String password, String phpsessid)
			throws LoginException {
		User user = userBeanLocal.getUserByUsername(username);
		String passHash = "";

		if (user == null) {
			throw new LoginException("User not found");
		}

		try {
			passHash = sha1(password);
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		logIn(user.getUid(), passHash, phpsessid);

	}

	public void logOut(String username) throws LoginException {
		User user = userBeanLocal.getUserByUsername(username);

		if (user == null) {
			throw new LoginException("Username not found.");
		}

		logOut(user.getUid());
	}

	public void logOut(int uid) throws LoginException {
		for (Session session : sessionList) {
			if (session.getUid() == uid) {
				sessionList.remove(session);
			}
		}

		throw new LoginException("User not logged in.");
	}

	public void killSession(String sessionId) {
		for (Session session : sessionList) {
			if (session.getPhpsessid() == sessionId) {
				sessionList.remove(session);
			}
		}

		throw new EntityNotFoundException("Session not found.");
	}

	public void logIn(int uid, String passHash, String phpsessid)
			throws LoginException {
		User user = userBeanLocal.getUserById(uid);

		if (user == null) {
			throw new LoginException("User not found.");

		}

		if (user.getPassHash() != passHash) {
			throw new LoginException("Wrong password");
		}

		for (Session session : sessionList) {
			if (session.getUid() == uid && session.getPhpsessid() == phpsessid) {
				/*
				 * I'm doing this because I want users to be able to have
				 * multiple sessions open without filling my session table
				 * uselessly.
				 *
				 * I still haven't decided if I'm going to implement a timeout
				 * or other cleanup system to expire closed sessions since
				 * there's no way for the servlet container to notify us when
				 * a session is no longer active.
				 *
				 * TODO There's a definite memory leak here as sessions don't
				 * expire.
				 */
				throw new LoginException("Already logged in");
			}
		}

		Session session = new Session();
		session.setPhpsessid(phpsessid);
		session
				.setTimestamp(new Time(Calendar.getInstance().getTimeInMillis()));
		session.setUid(uid);
		sessionList.add(session);
	}

	private String sha1(String string) throws NoSuchAlgorithmException {
		MessageDigest md;
		md = MessageDigest.getInstance("SHA1");
		md.update(string.getBytes());
		byte hashCode[] = md.digest();

		char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'A', 'B', 'C', 'D', 'E', 'F' };

		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < hashCode.length; i++) {
			sb.append(hexDigit[(hashCode[i] >> 4) & 0x0f]);
			sb.append(hexDigit[hashCode[i] & 0x0f]);
		}

		return sb.toString();
	}

}


UPDATE 12/31/10:  I’ve finished the facade session beans for the JPA entities.  Now I’m starting on the session beans for the business logic.

 

UPDATE:  I’ve fixed the primary key issue with the AssignmentBean and I’ve created a facade bean for the Availability class also.  I won’t post that code unless someone asks for it.

I’ve been doing some research into the best way of doing server-side entity management in J2EE.  I decided to go with the classic JPA entities and Stateless Session Beans as a facade.  Here’s some example code I’m actually working on right now:

A JPA entity with a composite natural key and JPA-introduced primary key:

package entities;

import java.io.Serializable;
import javax.persistence.*;

/**
 * The persistent class for the DSASSIGNMENT database table.
 *
 */
@Entity
@Table(name = "DSASSIGNMENT")
public class Assignment implements Serializable {
	private static final long serialVersionUID = 1L;

	@EmbeddedId
	private AssignmentPK id;

	// bi-directional many-to-one association to Participant
	@ManyToOne
	@JoinColumn(name = "GLNUM")
	private Participant dsparticipant;

	// bi-directional many-to-one association to Event
	@ManyToOne
	@JoinColumn(name = "EID")
	private Event dsevent;

	// bi-directional many-to-one association to Part
	@ManyToOne
	@JoinColumn(name = "PID")
	private Part dspart;

	public Assignment() {
	}

	public AssignmentPK getId() {
		return this.id;
	}

	public void setId(AssignmentPK id) {
		this.id = id;
	}

	public Participant getDsparticipant() {
		return this.dsparticipant;
	}

	public void setDsparticipant(Participant dsparticipant) {
		this.dsparticipant = dsparticipant;
	}

	public Event getDsevent() {
		return this.dsevent;
	}

	public void setDsevent(Event dsevent) {
		this.dsevent = dsevent;
	}

	public Part getDspart() {
		return this.dspart;
	}

	public void setDspart(Part dspart) {
		this.dspart = dspart;
	}

}

Here’s the pseudokey class:

package entities;

import java.io.Serializable;
import javax.persistence.*;

/**
 * The primary key class for the DSASSIGNMENT database table.
 *
 */
@Embeddable
public class AssignmentPK implements Serializable {
	// default serial version id, required for serializable classes.
	private static final long serialVersionUID = 1L;

	@Column(name = "GLNUM")
	private String glnum;

	@Column(name = "EID")
	private int eid;

	@Column(name = "PID")
	private int pid;

	public AssignmentPK() {
	}

	public String getGlnum() {
		return this.glnum;
	}

	public void setGlnum(String glnum) {
		this.glnum = glnum;
	}

	public int getEid() {
		return this.eid;
	}

	public void setEid(int eid) {
		this.eid = eid;
	}

	public int getPid() {
		return this.pid;
	}

	public void setPid(int pid) {
		this.pid = pid;
	}

	public boolean equals(Object other) {
		if (this == other) {
			return true;
		}
		if (!(other instanceof AssignmentPK)) {
			return false;
		}
		AssignmentPK castOther = (AssignmentPK) other;
		return this.glnum.equals(castOther.glnum)
				&& (this.eid == castOther.eid) && (this.pid == castOther.pid);

	}

	public int hashCode() {
		final int prime = 31;
		int hash = 17;
		hash = hash * prime + this.glnum.hashCode();
		hash = hash * prime + this.eid;
		hash = hash * prime + this.pid;

		return hash;
	}
}

(It’s a relational class – relates one ritual part to one degree event to one event participant – in other words, it’s the core of the program. The entire purpose is to assign people to parts for events.)

Here’s the SQL code that creates the backing table on the database server:

CREATE TABLE DSASSIGNMENT (
	GLNUM		CHAR(7)			NOT NULL,
	EID			INT	UNSIGNED	NOT NULL,
	PID			INT UNSIGNED	NOT NULL,
	PRIMARY	KEY	(GLNUM,EID,PID),
	FOREIGN	KEY	FK_DSGLNUM	(GLNUM)
		REFERENCES	DSPARTICIPANT	(GLNUM),
	FOREIGN	KEY	FK_DSEID	(EID)
		REFERENCES	DSEVENT	(EID),
	FOREIGN	KEY	FK_DSPID	(PID)
		REFERENCES	DSPART	(PID)
) ENGINE=InnoDB;

Here’s the Local Interface for the Assignment Facade:

package facade;

import java.util.List;

import javax.ejb.Local;

import entities.Assignment;
import entities.Event;
import entities.Part;
import entities.Participant;

@Local
public interface AssignmentBeanLocal {
	public Assignment createAssignment(Participant participant, Event event,
			Part part);

	public Assignment getAssignmentByKey(Participant participant, Event event,
			Part part);

	public List<Assignment> getAssignmentsForParticipant(Participant participant);

	public List<Assignment> getAssignmentsForEvent(Event event);

	public List<Assignment> getAssignmentsForPart(Part part);

	public List<Assignment> getAllAssignments();

	public Assignment updateAssignment(Assignment assignment);

	public void deleteAssignment(Participant participant, Event event, Part part);

}

And here’s the completed Assignment Facade Stateless Session Bean:

package facade;

import java.util.List;

import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import entities.Assignment;
import entities.AssignmentPK;
import entities.Event;
import entities.Part;
import entities.Participant;

/**
 * Session Bean implementation class AssignmentBean
 */
@Stateless(mappedName = "Assignment")
@TransactionManagement(TransactionManagementType.BEAN)
public class AssignmentBean implements AssignmentBeanLocal {
	@PersistenceContext
	EntityManager em;

	/**
	 * Default constructor.
	 */
	public AssignmentBean() {
		// TODO Auto-generated constructor stub
	}

	public Assignment createAssignment(Participant participant, Event event,
			Part part) {
		Assignment assignment = new Assignment();
		AssignmentPK aid = new AssignmentPK();
		aid.setEid(event.getEid());
		aid.setGlnum(participant.getGlnum());
		aid.setPid(part.getPid());
		assignment.setId(aid);
		assignment.setDsparticipant(participant);
		assignment.setDsevent(event);
		assignment.setDspart(part);
		em.persist(assignment);

		return assignment;
	}

	public void deleteAssignment(Participant participant, Event event, Part part) {
		Query query = em
				.createQuery("SELECT a FROM Assignment a WHERE a.dsparticipant = ?1 AND a.dsevent = ?2 AND a.dspart = ?3");
		query.setParameter(1, participant);
		query.setParameter(2, event);
		query.setParameter(3, part);
		Assignment assignment = (Assignment) query.getSingleResult();

		if (assignment == null) {
			throw new PersistenceException("Specified record does not exist.");
		}

		em.remove(assignment);
	}

	public List<Assignment> getAllAssignments() {
		Query query = em.createQuery("SELECT a FROM Assignment a");
		List<Assignment> resultList = query.getResultList();

		return resultList;
	}

	public List<Assignment> getAssignmentsForEvent(Event event) {
		Query query = em
				.createQuery("SELECT a FROM Assignment a WHERE a.dsevent = ?1");
		query.setParameter(1, event);
		List<Assignment> resultList = query.getResultList();
		return resultList;
	}

	public List<Assignment> getAssignmentsForPart(Part part) {
		Query query = em
				.createQuery("SELECT a FROM Assignment a WHERE a.dspart = ?1");
		query.setParameter(1, part);
		List<Assignment> resultList = query.getResultList();
		return resultList;
	}

	public List<Assignment> getAssignmentsForParticipant(Participant participant) {
		Query query = em
				.createQuery("SELECT a FROM Assignment a WHERE a.dsparticipant = ?1");
		query.setParameter(1, participant);
		List<Assignment> resultList = query.getResultList();
		return resultList;
	}

	public Assignment getAssignmentByKey(Participant participant, Event event, Part part) {
		Query query = em.createQuery("SELECT a FROM Assignment a WHERE a.dsparticipant = ?1 AND a.dsevent = ?2 AND a.dspart = ?3");
		query.setParameter(1, participant);
		query.setParameter(2, event);
		query.setParameter(3, part);

		return (Assignment) query.getSingleResult();
	}

	public Assignment updateAssignment(Assignment assignment) {
		return em.merge(assignment);
	}

}

I gave Chad the excuse that I had some software development work to do so I couldn’t play Minecraft.  That was true.  I have a notebook full of the usual software development scribblins, like use case diagrams, design documents, entity-relationship diagrams, state diagrams, and schema designs.  Today I put the schema designs into DDL statements and ran them on the development server:

CREATE TABLE DSLODGE (
	LODGENUM	INT	UNSIGNED	NOT NULL,
	LNAME		VARCHAR(63)		NOT NULL,
	AREA		TEXT,
	ADDRESS		VARCHAR(31),
	CITY		VARCHAR(31),
	STATE		CHAR(2),
	ZIP			VARCHAR(10),
	PRIMARY	KEY	(LODGENUM)
) ENGINE=InnoDB;

CREATE TABLE DSDEGREE (
	DID			INT	UNSIGNED	NOT NULL,
	DNAME		VARCHAR(18)		NOT NULL,
	DABBREV		CHAR(2),
	PRIMARY	KEY	(DID),
	UNIQUE	KEY	UX_DSNAME	(DNAME,DABBREV)
) ENGINE=InnoDB;

CREATE TABLE DSUSER (
	UID			INT	UNSIGNED	NOT NULL AUTO_INCREMENT,
	USERNAME	VARCHAR(31)		NOT NULL,
	PASS_HASH	CHAR(40) BINARY,
	EMAIL		VARCHAR(255),
	NAME		VARCHAR(63)		NOT NULL,
	PRI_LODGE	INT	UNSIGNED,
	PRIMARY KEY	(UID),
	UNIQUE	KEY	UX_DSUSERNAME	(USERNAME),
	FOREIGN	KEY	FK_DSPRI_LODGE	(PRI_LODGE)
		REFERENCES	DSLODGE	(LODGENUM)
) ENGINE=InnoDB;

CREATE TABLE DSSECTION (
	SID			INT	UNSIGNED	NOT NULL AUTO_INCREMENT,
	DID			INT	UNSIGNED	NOT	NULL,
	NAME		VARCHAR(31),
	PRIMARY	KEY	(SID),
	FOREIGN	KEY	FK_DSDID	(DID)
		REFERENCES	DSDEGREE	(DID)
) ENGINE=InnoDB;

CREATE TABLE DSPART (
	PID			INT	UNSIGNED	NOT NULL AUTO_INCREMENT,
	PNAME		VARCHAR(31)		NOT NULL,
	SID			INT	UNSIGNED	NOT NULL,
	PABBREV		CHAR(2),
	PRIMARY	KEY	(PID),
	UNIQUE	KEY	UX_DSABBREV	(PABBREV),
	FOREIGN	KEY	FK_DSSID	(SID)
		REFERENCES	DSSECTION	(SID)
) ENGINE=InnoDB;

CREATE TABLE DSEVENT (
	EID			INT	UNSIGNED	NOT NULL AUTO_INCREMENT,
	EDATE		DATE			NOT NULL,
	ETIME		TIME,
	DID			INT	UNSIGNED	NOT NULL,
	LOCATION	VARCHAR(127),
	LODGENUM	INT	UNSIGNED	NOT NULL,
	CANDIDATE	VARCHAR(63),
	PRIMARY	KEY	(EID),
	FOREIGN	KEY	FK_DSDID	(DID)
		REFERENCES	DSDEGREE	(DID),
	FOREIGN	KEY	FK_DSLODGENUM	(LODGENUM)
		REFERENCES	DSLODGE	(LODGENUM)
) ENGINE=InnoDB;

CREATE TABLE DSPARTICIPANT (
	GLNUM		CHAR(7)			NOT NULL,
	PNAME		VARCHAR(63)		NOT NULL,
	LODGENUM	INT	UNSIGNED,
	AREA		TEXT,
	EMAIL		VARCHAR(255),
	PHONE		VARCHAR(14),
	OFFICE		VARCHAR(31),
	CERTIFIED	BOOLEAN	DEFAULT	FALSE,
	PRIMARY	KEY	(GLNUM),
	FOREIGN	KEY	FK_DSLODGENUM	(LODGENUM)
		REFERENCES	DSLODGE	(LODGENUM)
) ENGINE=InnoDB;

CREATE TABLE DSASSIGNMENT (
	GLNUM		CHAR(7)			NOT NULL,
	EID			INT	UNSIGNED	NOT NULL,
	PID			INT UNSIGNED	NOT NULL,
	PRIMARY	KEY	(GLNUM,EID,PID),
	FOREIGN	KEY	FK_DSGLNUM	(GLNUM)
		REFERENCES	DSPARTICIPANT	(GLNUM),
	FOREIGN	KEY	FK_DSEID	(EID)
		REFERENCES	DSEVENT	(EID),
	FOREIGN	KEY	FK_DSPID	(PID)
		REFERENCES	DSPART	(PID)
) ENGINE=InnoDB;

CREATE TABLE DSPROFICIENCY (
	GLNUM		CHAR(7)			NOT NULL,
	PID			INT	UNSIGNED	NOT NULL,
	CONFIDENCE	SMALLINT,
	PRIMARY	KEY	(GLNUM,PID),
	FOREIGN	KEY	FK_DSGLNUM	(GLNUM)
		REFERENCES	DSPARTICIPANT	(GLNUM),
	FOREIGN	KEY	FK_DSPID	(PID)
		REFERENCES	DSPART	(PID)
) ENGINE=InnoDB;

CREATE TABLE DSAVAILABILITY (
	GLNUM		CHAR(7)			NOT NULL,
	EID			INT	UNSIGNED	NOT NULL,
	NOTES		TEXT,
	AVAILABLE	BOOLEAN	DEFAULT	FALSE,
	PRIMARY	KEY	(GLNUM,EID),
	FOREIGN	KEY	FK_DSGLNUM	(GLNUM)
		REFERENCES	DSPARTICIPANT	(GLNUM),
	FOREIGN	KEY	FK_DSEID	(EID)
		REFERENCES	DSEVENT	(EID)
) ENGINE=InnoDB;
Advertisements

, , ,

  1. #1 by Joshua on December 20, 2010 - 10:22 AM

    TODO: Add a user stateless session bean to handling adding, deleting, and modifying users as well as password resets.

  2. #2 by Joshua on December 20, 2010 - 10:28 AM

    TODO: Add SID to UX_DSABBREV. Otherwise an abbreviation will be unique globally instead of only within a section.

    • #3 by Joshua on December 21, 2010 - 8:11 AM

      Done.

  3. #4 by Joshua on December 22, 2010 - 12:52 PM

    There’s a bug in my Assignment Facade Bean. Can you spot it? I use three parameters in my JPA Query and never fill any of them in before trying to execute it. Did I mention the Bean is nowhere near finished (as if you couldn’t tell from the TODO: comments. :))

    • #5 by Joshua on December 22, 2010 - 2:17 PM

      That bug is fixed now.

  4. #6 by Joshua on December 22, 2010 - 2:37 PM

    The Assignment facade bean is finished (except for removing the TODO tag from the empty constructor). Any criticisms? It validates but I haven’t tested it yet. J2EE unit testing comes later in the development cycle than J2SE unit testing does.

  5. #7 by Andrew D. on December 22, 2010 - 11:00 PM

    I’d comment but databases are one of the programming things that I have to spend a lot of time reviewing, and it hurts my head to do so. So a DB java bean is really not something I want to stare at after I get home from work. Sorry.

    • #8 by Joshua on December 23, 2010 - 7:25 AM

      Ah. Good point. I forget that not everyone is as crazy as me. 🙂

  6. #9 by Joshua on January 3, 2011 - 12:37 PM

    I named the session ID variable phpsessid not because I’m using PHP (I’m not – I’m using JSP) but because I needed to distinguish it from the internal session ID (which is sid).

  7. #10 by Joshua on January 3, 2011 - 12:41 PM

    Hey, Chad? Could we possibly change to a layout that’s at least 80 columns wide? Only my source code is always very compressed horizontally.

    • #11 by Chadwick on January 3, 2011 - 2:41 PM

      Well, I have been looking at some other, variable-width layouts. Some of the new ones are tempting. Would a variable-width work out for you? Otherwise, I think all the fixed-width align roughly to our current size (or narrower).

      • #12 by Joshua on January 3, 2011 - 2:44 PM

        Sure! Variable-length would be great. I like our current one (it goes with Teh Table colors in the banner) but the very narrow width is getting annoying.

    • #13 by Chadwick on January 18, 2011 - 10:35 PM

      I think this new one makes your code display much nicer, but I await your judgment in that regard.

      • #14 by Joshua on January 19, 2011 - 5:06 AM

        I fully agree. I really like the new layout and the comment threads are especially sharp. And the code looks MUCH nicer! Thanks, Chad.

  8. #15 by Joshua on January 4, 2011 - 12:00 PM

    TODO Unit test the SHA1 function before anything else. It needs to return 40 characters of output.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: