Java/Design Pattern/Session Pattern
Session Pattern in Java
<source lang="java">
//[C] 2002 Sun Microsystems, Inc.--- import java.io.IOException; import java.io.Serializable; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.HashMap; public class RunSessionPattern {
public static void main(String[] arguments) { System.out.println("Example for the Session pattern"); System.out .println("This demonstration will show how a Session can be used"); System.out .println(" to organize a series of actions between a client and"); System.out.println(" server."); System.out .println("In this case, clients will use sessions to coordinate"); System.out.println(" edits of Contact addresses."); System.out.println(); System.out.println("Running the RMI compiler (rmic)"); System.out.println(); try { Process p1 = Runtime.getRuntime().exec("rmic SessionServerImpl"); p1.waitFor(); } catch (IOException exc) { System.err .println("Unable to run rmic utility. Exiting application."); System.exit(1); } catch (InterruptedException exc) { System.err .println("Threading problems encountered while using the rmic utility."); } System.out.println("Starting the rmiregistry"); System.out.println(); Process rmiProcess = null; try { rmiProcess = Runtime.getRuntime().exec("rmiregistry"); Thread.sleep(15000); } catch (IOException exc) { System.err .println("Unable to start the rmiregistry. Exiting application."); System.exit(1); } catch (InterruptedException exc) { System.err .println("Threading problems encountered when starting the rmiregistry."); } System.out .println("Creating the SessionServer and two SessionClient objects"); System.out.println(); SessionServer serverObject = new SessionServerImpl(); SessionClient clientOne = new SessionClient(); SessionClient clientTwo = new SessionClient(); System.out.println("Creating sample Contacts and Addresses"); System.out.println(); Contact firstContact = new ContactImpl("First", "Contact", "primo", "OOI", null); Contact secondContact = new ContactImpl("Second", "Contact", "secondo", "OOI", null); Address workAddress = new AddressImpl("Work address", "5440 Division", "Fargo", "ND", "54321"); Address homeAddress = new AddressImpl("Home address", "40 Planar Way", "Paris", "TX", "84301"); System.out .println("Adding a contact. Both clients will attempt to edit"); System.out .println(" the same contact at first, which will result in a"); System.out.println(" SessionException."); try { clientOne.addContact(firstContact); clientTwo.addContact(firstContact); } catch (SessionException exc) { System.err.println("Exception encountered:"); System.err.println(exc); } try { System.out .println("Adding a different contact to the second client"); clientTwo.addContact(secondContact); System.out .println("Adding addresses to the first and second clients"); clientTwo.addAddress(workAddress); clientOne.addAddress(homeAddress); clientTwo.addAddress(workAddress); clientTwo.addAddress(homeAddress); System.out.println("Removing address from a client"); clientTwo.removeAddress(homeAddress); System.out.println("Finalizing the edits to the contacts"); clientOne.rumitChanges(); clientTwo.rumitChanges(); System.out.println("Changes finalized"); clientTwo.addContact(firstContact); } catch (SessionException exc) { System.err.println("Exception encountered:"); System.err.println(exc); } System.out.println("The following lines will show the state"); System.out.println(" of the server-side delegate, which in this"); System.out.println(" example represents a persistent data store."); System.out.println(); System.out.println("Contact list:"); System.out.println(SessionServerDelegate.getContacts()); System.out.println("Address list:"); System.out.println(SessionServerDelegate.getAddresses()); System.out.println("Edit contacts:"); System.out.println(SessionServerDelegate.getEditContacts()); }
} interface Address extends Serializable {
public static final String EOL_STRING = System .getProperty("line.separator"); public static final String SPACE = " "; public static final String COMMA = ","; public String getType(); public String getDescription(); public String getStreet(); public String getCity(); public String getState(); public String getZipCode(); public void setType(String newType); public void setDescription(String newDescription); public void setStreet(String newStreet); public void setCity(String newCity); public void setState(String newState); public void setZipCode(String newZip);
} class AddressImpl implements Address {
private String type; private String description; private String street; private String city; private String state; private String zipCode; public AddressImpl() { } public AddressImpl(String newDescription, String newStreet, String newCity, String newState, String newZipCode) { description = newDescription; street = newStreet; city = newCity; state = newState; zipCode = newZipCode; } public String getType() { return type; } public String getDescription() { return description; } public String getStreet() { return street; } public String getCity() { return city; } public String getState() { return state; } public String getZipCode() { return zipCode; } public void setType(String newType) { type = newType; } public void setDescription(String newDescription) { description = newDescription; } public void setStreet(String newStreet) { street = newStreet; } public void setCity(String newCity) { city = newCity; } public void setState(String newState) { state = newState; } public void setZipCode(String newZip) { zipCode = newZip; } public boolean equals(Object o) { if (!(o instanceof AddressImpl)) { return false; } else { AddressImpl address = (AddressImpl) o; if (street.equals(address.street) && city.equals(address.city) && state.equals(address.state) && zipCode.equals(address.zipCode)) { return true; } return false; } } public String toString() { return street + EOL_STRING + city + COMMA + SPACE + state + SPACE + zipCode + EOL_STRING; }
} class SessionServerImpl implements SessionServer {
private static final String SESSION_SERVER_SERVICE_NAME = "sessionServer"; public SessionServerImpl() { try { UnicastRemoteObject.exportObject(this); Naming.rebind(SESSION_SERVER_SERVICE_NAME, this); } catch (Exception exc) { System.err .println("Error using RMI to register the SessionServerImpl " + exc); } } public long addContact(Contact contact, long sessionID) throws SessionException { return SessionServerDelegate.addContact(contact, sessionID); } public long addAddress(Address address, long sessionID) throws SessionException { return SessionServerDelegate.addAddress(address, sessionID); } public long removeAddress(Address address, long sessionID) throws SessionException { return SessionServerDelegate.removeAddress(address, sessionID); } public long finalizeContact(long sessionID) throws SessionException { return SessionServerDelegate.finalizeContact(sessionID); }
} interface SessionServer extends Remote {
public long addContact(Contact contact, long sessionID) throws RemoteException, SessionException; public long addAddress(Address address, long sessionID) throws RemoteException, SessionException; public long removeAddress(Address address, long sessionID) throws RemoteException, SessionException; public long finalizeContact(long sessionID) throws RemoteException, SessionException;
} class SessionServerDelegate {
private static final long NO_SESSION_ID = 0; private static long nextSessionID = 1; private static ArrayList contacts = new ArrayList(); private static ArrayList addresses = new ArrayList(); private static HashMap editContacts = new HashMap(); public static long addContact(Contact contact, long sessionID) throws SessionException { if (sessionID <= NO_SESSION_ID) { sessionID = getSessionID(); } if (contacts.indexOf(contact) != -1) { if (!editContacts.containsValue(contact)) { editContacts.put(new Long(sessionID), contact); } else { throw new SessionException( "This contact is currently being edited by another user.", SessionException.CONTACT_BEING_EDITED); } } else { contacts.add(contact); editContacts.put(new Long(sessionID), contact); } return sessionID; } public static long addAddress(Address address, long sessionID) throws SessionException { if (sessionID <= NO_SESSION_ID) { throw new SessionException( "A valid session ID is required to add an address", SessionException.SESSION_ID_REQUIRED); } Contact contact = (Contact) editContacts.get(new Long(sessionID)); if (contact == null) { throw new SessionException( "You must select a contact before adding an address", SessionException.CONTACT_SELECT_REQUIRED); } if (addresses.indexOf(address) == -1) { addresses.add(address); } contact.addAddress(address); return sessionID; } public static long removeAddress(Address address, long sessionID) throws SessionException { if (sessionID <= NO_SESSION_ID) { throw new SessionException( "A valid session ID is required to remove an address", SessionException.SESSION_ID_REQUIRED); } Contact contact = (Contact) editContacts.get(new Long(sessionID)); if (contact == null) { throw new SessionException( "You must select a contact before removing an address", SessionException.CONTACT_SELECT_REQUIRED); } if (addresses.indexOf(address) == -1) { throw new SessionException("There is no record of this address", SessionException.ADDRESS_DOES_NOT_EXIST); } contact.removeAddress(address); return sessionID; } public static long finalizeContact(long sessionID) throws SessionException { if (sessionID <= NO_SESSION_ID) { throw new SessionException( "A valid session ID is required to finalize a contact", SessionException.SESSION_ID_REQUIRED); } Contact contact = (Contact) editContacts.get(new Long(sessionID)); if (contact == null) { throw new SessionException( "You must select and edit a contact before committing changes", SessionException.CONTACT_SELECT_REQUIRED); } editContacts.remove(new Long(sessionID)); return NO_SESSION_ID; } private static long getSessionID() { return nextSessionID++; } public static ArrayList getContacts() { return contacts; } public static ArrayList getAddresses() { return addresses; } public static ArrayList getEditContacts() { return new ArrayList(editContacts.values()); }
} interface Contact extends Serializable {
public static final String SPACE = " "; public static final String EOL_STRING = System .getProperty("line.separator"); public String getFirstName(); public String getLastName(); public String getTitle(); public String getOrganization(); public ArrayList getAddresses(); public void setFirstName(String newFirstName); public void setLastName(String newLastName); public void setTitle(String newTitle); public void setOrganization(String newOrganization); public void addAddress(Address address); public void removeAddress(Address address);
} class ContactImpl implements Contact {
private String firstName; private String lastName; private String title; private String organization; private ArrayList addresses = new ArrayList(); public ContactImpl() { } public ContactImpl(String newFirstName, String newLastName, String newTitle, String newOrganization, ArrayList newAddresses) { firstName = newFirstName; lastName = newLastName; title = newTitle; organization = newOrganization; if (newAddresses != null) { addresses = newAddresses; } } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public String getTitle() { return title; } public String getOrganization() { return organization; } public ArrayList getAddresses() { return addresses; } public void setFirstName(String newFirstName) { firstName = newFirstName; } public void setLastName(String newLastName) { lastName = newLastName; } public void setTitle(String newTitle) { title = newTitle; } public void setOrganization(String newOrganization) { organization = newOrganization; } public void addAddress(Address address) { if (!addresses.contains(address)) { addresses.add(address); } } public void removeAddress(Address address) { addresses.remove(address); } public boolean equals(Object o) { if (!(o instanceof ContactImpl)) { return false; } else { ContactImpl contact = (ContactImpl) o; if (firstName.equals(contact.firstName) && lastName.equals(contact.lastName) && organization.equals(contact.organization) && title.equals(contact.title)) { return true; } return false; } } public String toString() { return firstName + SPACE + lastName + EOL_STRING + addresses; }
} class SessionClient {
private static final String SESSION_SERVER_SERVICE_NAME = "sessionServer"; private static final String SESSION_SERVER_MACHINE_NAME = "localhost"; private long sessionID; private SessionServer sessionServer; public SessionClient() { try { String url = "//" + SESSION_SERVER_MACHINE_NAME + "/" + SESSION_SERVER_SERVICE_NAME; sessionServer = (SessionServer) Naming.lookup(url); } catch (RemoteException exc) { } catch (NotBoundException exc) { } catch (MalformedURLException exc) { } catch (ClassCastException exc) { } } public void addContact(Contact contact) throws SessionException { try { sessionID = sessionServer.addContact(contact, 0); } catch (RemoteException exc) { } } public void addAddress(Address address) throws SessionException { try { sessionServer.addAddress(address, sessionID); } catch (RemoteException exc) { } } public void removeAddress(Address address) throws SessionException { try { sessionServer.removeAddress(address, sessionID); } catch (RemoteException exc) { } } public void commitChanges() throws SessionException { try { sessionID = sessionServer.finalizeContact(sessionID); } catch (RemoteException exc) { } }
} class SessionException extends Exception {
public static final int CONTACT_BEING_EDITED = 1; public static final int SESSION_ID_REQUIRED = 2; public static final int CONTACT_SELECT_REQUIRED = 3; public static final int ADDRESS_DOES_NOT_EXIST = 4; private int errorCode; public SessionException(String cause, int newErrorCode) { super(cause); errorCode = newErrorCode; } public SessionException(String cause) { super(cause); } public int getErrorCode() { return errorCode; }
}
</source>