Mega Code Archive

 
Categories / Java / Design Pattern
 

Transaction Pattern Demo

//[C] 2002 Sun Microsystems, Inc.--- import java.io.IOException; import java.io.Serializable; import java.rmi.Naming; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; public class RunTransactionPattern {   private static Calendar dateCreator = Calendar.getInstance();   public static void main(String[] arguments) {     System.out.println("Example for the Transaction pattern");     System.out.println("This code example shows how a Transaction can");     System.out         .println(" be applied to support change across a distributed");     System.out.println(" system. In ths case, a distributed transaction");     System.out.println(" is used to coordinate the change of dates in");     System.out.println(" appointment books.");     System.out.println("Running the RMI compiler (rmic)");     System.out.println();     try {       Process p1 = Runtime.getRuntime().exec("rmic AppointmentBook");       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();     try {       Process 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 three appointment books");     System.out.println();     AppointmentBook apptBookOne = new AppointmentBook();     AppointmentBook apptBookTwo = new AppointmentBook();     AppointmentBook apptBookThree = new AppointmentBook();     System.out.println("Creating appointments");     System.out.println();     Appointment apptOne = new AppointmentImpl(         "Swim relay to Kalimantan (or Java)", new ArrayList(),         new LocationImpl("Sidney, Australia"), createDate(2001, 11, 5,             11, 0));     Appointment apptTwo = new AppointmentImpl(         "Conference on World Patternization", new ArrayList(),         new LocationImpl("London, England"), createDate(2001, 11, 5,             14, 0));     Appointment apptThree = new AppointmentImpl(         "Society for the Preservation of Java - Annual Outing",         new ArrayList(), new LocationImpl("Kyzyl, Tuva"), createDate(             2001, 11, 5, 10, 0));     System.out.println("Adding appointments to the appointment books");     System.out.println();     apptBookOne.addAppointment(apptThree);     apptBookTwo.addAppointment(apptOne);     apptBookOne.addAppointment(apptTwo);     apptBookTwo.addAppointment(apptTwo);     apptBookThree.addAppointment(apptTwo);     System.out.println("AppointmentBook contents:");     System.out.println();     System.out.println(apptBookOne);     System.out.println(apptBookTwo);     System.out.println(apptBookThree);     System.out.println();     System.out.println("Rescheduling an appointment");     System.out.println();     System.out.println();     boolean result = apptBookThree.changeAppointment(apptTwo, getDates(         2001, 11, 5, 10, 3), lookUpParticipants(new String[] {         apptBookOne.getUrl(), apptBookTwo.getUrl(),         apptBookThree.getUrl() }), 20000L);     System.out.println("Result of rescheduling was " + result);     System.out.println("AppointmentBook contents:");     System.out.println();     System.out.println(apptBookOne);     System.out.println(apptBookTwo);     System.out.println(apptBookThree);   }   private static AppointmentTransactionParticipant[] lookUpParticipants(       String[] remoteUrls) {     AppointmentTransactionParticipant[] returnValues = new AppointmentTransactionParticipant[remoteUrls.length];     for (int i = 0; i < remoteUrls.length; i++) {       try {         returnValues[i] = (AppointmentTransactionParticipant) Naming             .lookup(remoteUrls[i]);       } catch (Exception exc) {         System.out             .println("Error using RMI to look up a transaction participant");       }     }     return returnValues;   }   private static Date[] getDates(int year, int month, int day, int hour,       int increment) {     Date[] returnDates = new Date[increment];     for (int i = 0; i < increment; i++) {       returnDates[i] = createDate(year, month, day, hour + i, 0);     }     return returnDates;   }   public static Date createDate(int year, int month, int day, int hour,       int minute) {     dateCreator.set(year, month, day, hour, minute);     return dateCreator.getTime();   } } interface Location extends Serializable {   public String getLocation();   public void setLocation(String newLocation); } class LocationImpl implements Location {   private String location;   public LocationImpl() {   }   public LocationImpl(String newLocation) {     location = newLocation;   }   public String getLocation() {     return location;   }   public void setLocation(String newLocation) {     location = newLocation;   }   public String toString() {     return location;   } } interface Contact extends Serializable {   public static final String SPACE = " ";   public String getFirstName();   public String getLastName();   public String getTitle();   public String getOrganization();   public void setFirstName(String newFirstName);   public void setLastName(String newLastName);   public void setTitle(String newTitle);   public void setOrganization(String newOrganization); } class ContactImpl implements Contact {   private String firstName;   private String lastName;   private String title;   private String organization;   public ContactImpl() {   }   public ContactImpl(String newFirstName, String newLastName,       String newTitle, String newOrganization) {     firstName = newFirstName;     lastName = newLastName;     title = newTitle;     organization = newOrganization;   }   public String getFirstName() {     return firstName;   }   public String getLastName() {     return lastName;   }   public String getTitle() {     return title;   }   public String getOrganization() {     return organization;   }   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 String toString() {     return firstName + SPACE + lastName;   } } interface Appointment extends Serializable {   public static final String EOL_STRING = System       .getProperty("line.separator");   public Date getStartDate();   public String getDescription();   public ArrayList getAttendees();   public Location getLocation();   public void setDescription(String newDescription);   public void setLocation(Location newLocation);   public void setStartDate(Date newStartDate);   public void setAttendees(ArrayList newAttendees);   public void addAttendee(Contact attendee);   public void removeAttendee(Contact attendee); } class AppointmentImpl implements Appointment {   private Date startDate;   private String description;   private ArrayList attendees = new ArrayList();   private Location location;   public AppointmentImpl(String newDescription, ArrayList newAttendees,       Location newLocation, Date newStartDate) {     description = newDescription;     attendees = newAttendees;     location = newLocation;     startDate = newStartDate;   }   public Date getStartDate() {     return startDate;   }   public String getDescription() {     return description;   }   public ArrayList getAttendees() {     return attendees;   }   public Location getLocation() {     return location;   }   public void setDescription(String newDescription) {     description = newDescription;   }   public void setLocation(Location newLocation) {     location = newLocation;   }   public void setStartDate(Date newStartDate) {     startDate = newStartDate;   }   public void setAttendees(ArrayList newAttendees) {     if (newAttendees != null) {       attendees = newAttendees;     }   }   public void addAttendee(Contact attendee) {     if (!attendees.contains(attendee)) {       attendees.add(attendee);     }   }   public void removeAttendee(Contact attendee) {     attendees.remove(attendee);   }   public int hashCode() {     return description.hashCode() ^ startDate.hashCode();   }   public boolean equals(Object object) {     if (!(object instanceof AppointmentImpl)) {       return false;     }     if (object.hashCode() != hashCode()) {       return false;     }     return true;   }   public String toString() {     return "  Description: " + description + EOL_STRING + "  Start Date: "         + startDate + EOL_STRING + "  Location: " + location         + EOL_STRING + "  Attendees: " + attendees;   } } class AppointmentBook implements AppointmentTransactionParticipant {   private static final String TRANSACTION_SERVICE_PREFIX = "transactionParticipant";   private static final String TRANSACTION_HOSTNAME = "localhost";   private static int index = 1;   private String serviceName = TRANSACTION_SERVICE_PREFIX + index++;   private HashMap appointments = new HashMap();   private long currentTransaction;   private Appointment currentAppointment;   private Date updateStartDate;   public AppointmentBook() {     try {       UnicastRemoteObject.exportObject(this);       Naming.rebind(serviceName, this);     } catch (Exception exc) {       System.err           .println("Error using RMI to register the AppointmentBook "               + exc);     }   }   public String getUrl() {     return "//" + TRANSACTION_HOSTNAME + "/" + serviceName;   }   public void addAppointment(Appointment appointment) {     if (!appointments.containsValue(appointment)) {       if (!appointments.containsKey(appointment.getStartDate())) {         appointments.put(appointment.getStartDate(), appointment);       }     }   }   public void removeAppointment(Appointment appointment) {     if (appointments.containsValue(appointment)) {       appointments.remove(appointment.getStartDate());     }   }   public boolean join(long transactionID) {     if (currentTransaction != 0) {       return false;     } else {       currentTransaction = transactionID;       return true;     }   }   public void commit(long transactionID) throws TransactionException {     if (currentTransaction != transactionID) {       throw new TransactionException("Invalid TransactionID");     } else {       removeAppointment(currentAppointment);       currentAppointment.setStartDate(updateStartDate);       appointments.put(updateStartDate, currentAppointment);     }   }   public void cancel(long transactionID) {     if (currentTransaction == transactionID) {       currentTransaction = 0;       appointments.remove(updateStartDate);     }   }   public boolean changeDate(long transactionID, Appointment appointment,       Date newStartDate) throws TransactionException {     if ((appointments.containsValue(appointment))         && (!appointments.containsKey(newStartDate))) {       appointments.put(newStartDate, null);       updateStartDate = newStartDate;       currentAppointment = appointment;       return true;     }     return false;   }   public boolean changeAppointment(Appointment appointment,       Date[] possibleDates,       AppointmentTransactionParticipant[] participants, long transactionID) {     try {       for (int i = 0; i < participants.length; i++) {         if (!participants[i].join(transactionID)) {           return false;         }       }       for (int i = 0; i < possibleDates.length; i++) {         if (isDateAvailable(transactionID, appointment,             possibleDates[i], participants)) {           try {             commitAll(transactionID, participants);             return true;           } catch (TransactionException exc) {           }         }       }     } catch (RemoteException exc) {     }     try {       cancelAll(transactionID, participants);     } catch (RemoteException exc) {     }     return false;   }   private boolean isDateAvailable(long transactionID,       Appointment appointment, Date date,       AppointmentTransactionParticipant[] participants) {     try {       for (int i = 0; i < participants.length; i++) {         try {           if (!participants[i].changeDate(transactionID, appointment,               date)) {             return false;           }         } catch (TransactionException exc) {           return false;         }       }     } catch (RemoteException exc) {       return false;     }     return true;   }   private void commitAll(long transactionID,       AppointmentTransactionParticipant[] participants)       throws TransactionException, RemoteException {     for (int i = 0; i < participants.length; i++) {       participants[i].commit(transactionID);     }   }   private void cancelAll(long transactionID,       AppointmentTransactionParticipant[] participants)       throws RemoteException {     for (int i = 0; i < participants.length; i++) {       participants[i].cancel(transactionID);     }   }   public String toString() {     return serviceName + " " + appointments.values().toString();   } } interface AppointmentTransactionParticipant extends Remote {   public boolean join(long transactionID) throws RemoteException;   public void commit(long transactionID) throws TransactionException,       RemoteException;   public void cancel(long transactionID) throws RemoteException;   public boolean changeDate(long transactionID, Appointment appointment,       Date newStartDate) throws TransactionException, RemoteException; } class TransactionException extends Exception {   public TransactionException(String msg) {     super(msg);   } }