Java/Design Pattern/Call Back Pattern
Callback Pattern in Java
<source lang="java">
//[C] 2002 Sun Microsystems, Inc.--- import java.io.IOException; public class RunCallbackPattern {
public static void main(String [] arguments){ System.out.println("Example for the Callback pattern"); System.out.println("This code will run two RMI objects to demonstrate"); System.out.println(" callback capability. One will be CallbackClientImpl,"); System.out.println(" which will request a project from the other remote"); System.out.println(" object, CallbackServerImpl."); System.out.println("To demonstrate how the Callback pattern allows the"); System.out.println(" client to perform independent processing, the main"); System.out.println(" progam thread will go into a wait loop until the"); System.out.println(" server sends the object to its client."); System.out.println(); System.out.println("Running the RMI compiler (rmic)"); System.out.println(); try{ Process p1 = Runtime.getRuntime().exec("rmic CallbackServerImpl"); Process p2 = Runtime.getRuntime().exec("rmic CallbackClientImpl"); p1.waitFor(); p2.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 client and server objects"); System.out.println(); CallbackServerImpl callbackServer = new CallbackServerImpl(); CallbackClientImpl callbackClient = new CallbackClientImpl(); System.out.println("CallbackClientImpl requesting a project"); callbackClient.requestProject("New Java Project"); try{ while(!callbackClient.isProjectAvailable()){ System.out.println("Project not available yet; sleeping for 2 seconds"); Thread.sleep(2000); } } catch (InterruptedException exc){} System.out.println("Project retrieved: " + callbackClient.getProject()); }
} import java.rmi.Naming; import java.rmi.server.UnicastRemoteObject; public class CallbackServerImpl implements CallbackServer{
private static final String CALLBACK_SERVER_SERVICE_NAME = "callbackServer"; public CallbackServerImpl(){ try { UnicastRemoteObject.exportObject(this); Naming.rebind(CALLBACK_SERVER_SERVICE_NAME, this); } catch (Exception exc){ System.err.println("Error using RMI to register the CallbackServerImpl " + exc); } } public void getProject(String projectID, String callbackMachine, String callbackObjectName){ new CallbackServerDelegate(projectID, callbackMachine, callbackObjectName); }
} import java.rmi.Remote; import java.rmi.RemoteException; public interface CallbackServer extends Remote{
public void getProject(String projectID, String callbackMachine, String callbackObjectName) throws RemoteException;
}
import java.net.InetAddress; import java.net.MalformedURLException; import java.net.UnknownHostException; import java.rmi.Naming; import java.rmi.server.UnicastRemoteObject; import java.rmi.NotBoundException; import java.rmi.RemoteException; public class CallbackClientImpl implements CallbackClient{
private static final String CALLBACK_CLIENT_SERVICE_NAME = "callbackClient"; private static final String CALLBACK_SERVER_SERVICE_NAME = "callbackServer"; private static final String CALLBACK_SERVER_MACHINE_NAME = "localhost"; private Project requestedProject; private boolean projectAvailable; public CallbackClientImpl(){ try { UnicastRemoteObject.exportObject(this); Naming.rebind(CALLBACK_CLIENT_SERVICE_NAME, this); } catch (Exception exc){ System.err.println("Error using RMI to register the CallbackClientImpl " + exc); } } public void receiveProject(Project project){ requestedProject = project; projectAvailable = true; } public void requestProject(String projectName){ try{ String url = "//" + CALLBACK_SERVER_MACHINE_NAME + "/" + CALLBACK_SERVER_SERVICE_NAME; Object remoteServer = Naming.lookup(url); if (remoteServer instanceof CallbackServer){ ((CallbackServer)remoteServer).getProject(projectName, InetAddress.getLocalHost().getHostName(), CALLBACK_CLIENT_SERVICE_NAME); } projectAvailable = false; } catch (RemoteException exc){} catch (NotBoundException exc){} catch (MalformedURLException exc){} catch (UnknownHostException exc){} } public Project getProject(){ return requestedProject; } public boolean isProjectAvailable(){ return projectAvailable; }
}
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; public class CallbackServerDelegate implements Runnable{
private Thread processingThread; private String projectID; private String callbackMachine; private String callbackObjectName; public CallbackServerDelegate(String newProjectID, String newCallbackMachine, String newCallbackObjectName){ projectID = newProjectID; callbackMachine = newCallbackMachine; callbackObjectName = newCallbackObjectName; processingThread = new Thread(this); processingThread.start(); } public void run(){ Project result = getProject(); sendProjectToClient(result); } private Project getProject(){ return new Project(projectID, "Test project"); } private void sendProjectToClient(Project project){ try{ String url = "//" + callbackMachine + "/" + callbackObjectName; Object remoteClient = Naming.lookup(url); if (remoteClient instanceof CallbackClient){ ((CallbackClient)remoteClient).receiveProject(project); } } catch (RemoteException exc){} catch (NotBoundException exc){} catch (MalformedURLException exc){} }
}
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; public class CallbackServerWorkThread implements Runnable{
private Thread processingThread; private String projectID; private String callbackMachine; private String callbackObjectName; public CallbackServerWorkThread(String newProjectID, String newCallbackMachine, String newCallbackObjectName){ projectID = newProjectID; callbackMachine = newCallbackMachine; callbackObjectName = newCallbackObjectName; processingThread = new Thread(this); processingThread.start(); } public void run(){ Project result = getProject(); sendProjectToClient(result); } private Project getProject(){ return new Project(projectID, "Test project"); } private void sendProjectToClient(Project project){ try{ String url = "//" + callbackMachine + "/" + callbackObjectName; Object remoteClient = Naming.lookup(url); if (remoteClient instanceof CallbackClient){ ((CallbackClient)remoteClient).receiveProject(project); } } catch (RemoteException exc){} catch (NotBoundException exc){} catch (MalformedURLException exc){} }
} public class Command implements java.io.Serializable{
public static final int GET_PROJECT = 1; public static final int GET_TASK = 2; public static final int CREATE_CONTACT = 4; public static final int ADD_ADDRESS = 8; public static final int REMOVE_ADDRESS = 16; public static final int FINALIZE_CONTACT = 32; private int command; private Object [] arguments; public int getCommand(){ return command; } public Object [] getArguments(){ return arguments; } public void setArguments(Object [] newArguments){ arguments = newArguments; } public void setCommand(int newCommand){ command = newCommand; } public Command(int name, Object [] argumentList){ command = name; arguments = argumentList; }
} import java.util.ArrayList; public class Project implements ProjectItem{
private String name; private String description; private ArrayList projectItems = new ArrayList(); public Project(){ } public Project(String newName, String newDescription){ name = newName; description = newDescription; } public String getName(){ return name; } public String getDescription(){ return description; } public ArrayList getProjectItems(){ return projectItems; } public void setName(String newName){ name = newName; } public void setDescription(String newDescription){ description = newDescription; } public void addProjectItem(ProjectItem element){ if (!projectItems.contains(element)){ projectItems.add(element); } } public void removeProjectItem(ProjectItem element){ projectItems.remove(element); } public String toString(){ return name + ", " + description; }
} import java.net.Socket; import java.util.Date; import java.io.*; public class ServerWorkThread implements Runnable{
private Thread processingThread; private Socket requestSocket; private Command command; public ServerWorkThread(Socket clientRequestSocket){ requestSocket = clientRequestSocket; processingThread = new Thread(this); processingThread.start(); } private void retrieveCommand(){ try{ ObjectInputStream in = new ObjectInputStream(requestSocket.getInputStream()); Object request = in.readObject(); requestSocket.close(); if (request instanceof Command){ command = (Command)request; } } catch (ClassNotFoundException exc){ } catch (IOException exc){ } } protected void processCommand(){ } public void run(){ retrieveCommand(); processCommand(); } public Command getCommand(){ return command; } protected Socket getRequestSocket(){ return requestSocket; }
}
import java.util.ArrayList; public class Task implements ProjectItem{
private String name; private ArrayList projectItems = new ArrayList(); private double timeRequired; public Task(){ } public Task(String newName, double newTimeRequired){ name = newName; timeRequired = newTimeRequired; } public String getName(){ return name; } public ArrayList getProjectItems(){ return projectItems; } public double getTimeRequired(){ return timeRequired; } public void setName(String newName){ name = newName; } public void setTimeRequired(double newTimeRequired){ timeRequired = newTimeRequired; } public void addProjectItem(ProjectItem element){ if (!projectItems.contains(element)){ projectItems.add(element); } } public void removeProjectItem(ProjectItem element){ projectItems.remove(element); }
}
import java.net.ServerSocket; import java.net.Socket; import java.io.IOException; public class ThreadedServer{
private static final int DEFAULT_SERVER_PORT = 2001; private boolean shutdown; private int serverPort = DEFAULT_SERVER_PORT; public void runServer(){ try{ ServerSocket mainServer = new ServerSocket(serverPort); while (!shutdown){ Socket requestSocket = mainServer.accept(); new ServerWorkThread(requestSocket); } } catch (IOException exc){ } } public int getServerPort(){ return serverPort; } public boolean isShutdown(){ return shutdown; } public void setShutdown(boolean isShutdown){ shutdown = isShutdown; } public void setServerPort(int newServerPort){ serverPort = newServerPort; }
}
import java.rmi.Remote; import java.rmi.RemoteException; public interface CallbackClient extends Remote{
public void receiveProject(Project project) throws RemoteException;
} import java.io.Serializable; import java.util.ArrayList; public interface ProjectItem extends Serializable{
public ArrayList getProjectItems();
}
</source>
Chain Pattern
<source lang="java">
//[C] 2002 Sun Microsystems, Inc.--- import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList;
import java.io.File; import java.util.ArrayList; import java.util.Iterator; public class RunChainPattern {
public static void main(String [] arguments){ System.out.println("Example for the Chain of Responsibility pattern"); System.out.println(); System.out.println("This code uses chain of responsibility to obtain"); System.out.println(" the owner for a particular ProjectItem, and to"); System.out.println(" build up a list of project details. In each case,"); System.out.println(" a call to the appropriate getter method, getOwner"); System.out.println(" or getDetails, will pass the method call up the"); System.out.println(" project tree."); System.out.println("For getOwner, the call will return the first non-null"); System.out.println(" owner field encountered. For getDetails, the method"); System.out.println(" will build a series of details, stopping when it"); System.out.println(" reaches a ProjectItem that is designated as a"); System.out.println(" primary task."); System.out.println(); System.out.println("Deserializing a test Project for Visitor pattern"); System.out.println(); if (!(new File("data.ser").exists())){ DataCreator.serialize("data.ser"); } Project project = (Project)(DataRetriever.deserializeData("data.ser")); System.out.println("Retrieving Owner and details for each item in the Project"); System.out.println(); getItemInfo(project); } private static void getItemInfo(ProjectItem item){ System.out.println("ProjectItem: " + item); System.out.println(" Owner: " + item.getOwner()); System.out.println(" Details: " + item.getDetails()); System.out.println(); if (item.getProjectItems() != null){ Iterator subElements = item.getProjectItems().iterator(); while (subElements.hasNext()){ getItemInfo((ProjectItem)subElements.next()); } } }
} 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; }
} class Task implements ProjectItem{
private String name; private ArrayList projectItems = new ArrayList(); private Contact owner; private String details; private ProjectItem parent; private boolean primaryTask; public Task(ProjectItem newParent){ this(newParent, "", "", null, false); } public Task(ProjectItem newParent, String newName, String newDetails, Contact newOwner, boolean newPrimaryTask){ parent = newParent; name = newName; owner = newOwner; details = newDetails; primaryTask = newPrimaryTask; } public Contact getOwner(){ if (owner == null){ return parent.getOwner(); } else{ return owner; } } public String getDetails(){ if (primaryTask){ return details; } else{ return parent.getDetails() + EOL_STRING + "\t" + details; } } public String getName(){ return name; } public ArrayList getProjectItems(){ return projectItems; } public ProjectItem getParent(){ return parent; } public boolean isPrimaryTask(){ return primaryTask; } public void setName(String newName){ name = newName; } public void setOwner(Contact newOwner){ owner = newOwner; } public void setParent(ProjectItem newParent){ parent = newParent; } public void setPrimaryTask(boolean newPrimaryTask){ primaryTask = newPrimaryTask; } public void setDetails(String newDetails){ details = newDetails; } public void addProjectItem(ProjectItem element){ if (!projectItems.contains(element)){ projectItems.add(element); } } public void removeProjectItem(ProjectItem element){ projectItems.remove(element); } public String toString(){ return name; }
} class DataCreator{
private static final String DEFAULT_FILE = "data.ser"; public static void main(String [] args){ String fileName; if (args.length == 1){ fileName = args[0]; } else{ fileName = DEFAULT_FILE; } serialize(fileName); } public static void serialize(String fileName){ try{ serializeToFile(createData(), fileName); } catch (IOException exc){ exc.printStackTrace(); } } private static Serializable createData(){ Contact contact1 = new ContactImpl("Dennis", "Moore", "Managing Director", "Highway Man, LTD"); Contact contact2 = new ContactImpl("Joseph", "Mongolfier", "High Flyer", "Lighter than Air Productions"); Contact contact3 = new ContactImpl("Erik", "Njoll", "Nomad without Portfolio", "Nordic Trek, Inc."); Contact contact4 = new ContactImpl("Lemming", "", "Principal Investigator", "BDA"); Project project = new Project("IslandParadise", "Acquire a personal island paradise", contact2); Task task1 = new Task(project, "Fortune", "Acquire a small fortune", contact4, true); Task task2 = new Task(project, "Isle", "Locate an island for sale", null, true); Task task3 = new Task(project, "Name", "Decide on a name for the island", contact3, false); project.addProjectItem(task1); project.addProjectItem(task2); project.addProjectItem(task3); Task task4 = new Task(task1, "Fortune1", "Use psychic hotline to predict winning lottery numbers", null, false); Task task5 = new Task(task1, "Fortune2", "Invest winnings to ensure 50% annual interest", contact1, true); Task task6 = new Task(task2, "Isle1", "Research whether climate is better in the Atlantic or Pacific", contact1, true); Task task7 = new Task(task2, "Isle2", "Locate an island for auction on EBay", null, false); Task task8 = new Task(task2, "Isle2a", "Negotiate for sale of the island", null, false); Task task9 = new Task(task3, "Name1", "Research every possible name in the world", null, true); Task task10 = new Task(task3, "Name2", "Eliminate any choices that are not coffee-related", contact4, false); task1.addProjectItem(task4); task1.addProjectItem(task5); task2.addProjectItem(task6); task2.addProjectItem(task7); task2.addProjectItem(task8); task3.addProjectItem(task9); task3.addProjectItem(task10); return project; } private static void serializeToFile(Serializable content, String fileName) throws IOException{ ObjectOutputStream serOut = new ObjectOutputStream(new FileOutputStream(fileName)); serOut.writeObject(content); serOut.close(); }
} interface ProjectItem extends Serializable{
public static final String EOL_STRING = System.getProperty("line.separator"); public ProjectItem getParent(); public Contact getOwner(); public String getDetails(); public ArrayList getProjectItems();
} class Project implements ProjectItem{
private String name; private Contact owner; private String details; private ArrayList projectItems = new ArrayList(); public Project(){ } public Project(String newName, String newDetails, Contact newOwner){ name = newName; owner = newOwner; details = newDetails; } public String getName(){ return name; } public String getDetails(){ return details; } public Contact getOwner(){ return owner; } public ProjectItem getParent(){ return null; } public ArrayList getProjectItems(){ return projectItems; } public void setName(String newName){ name = newName; } public void setOwner(Contact newOwner){ owner = newOwner; } public void setDetails(String newDetails){ details = newDetails; } public void addProjectItem(ProjectItem element){ if (!projectItems.contains(element)){ projectItems.add(element); } } public void removeProjectItem(ProjectItem element){ projectItems.remove(element); } public String toString(){ return name; }
} class DataRetriever{
public static Object deserializeData(String fileName){ Object returnValue = null; try{ File inputFile = new File(fileName); if (inputFile.exists() && inputFile.isFile()){ ObjectInputStream readIn = new ObjectInputStream(new FileInputStream(fileName)); returnValue = readIn.readObject(); readIn.close(); } else { System.err.println("Unable to locate the file " + fileName); } } catch (ClassNotFoundException exc){ exc.printStackTrace(); } catch (IOException exc){ exc.printStackTrace(); } return returnValue; }
}
</source>