Java/Design Pattern/Transaction Pattern

Материал из Java эксперт
Перейти к: навигация, поиск

Transaction Pattern Demo

   <source lang="java">

//[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].rumit(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);
 }

}


      </source>