Java/Design Pattern/Session Pattern
Session Pattern in 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;
}
}