Callback Pattern in 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(); }
1. | Chain Pattern |