1 / 55

5.4. Automatic Class File Distribution

5.4. Automatic Class File Distribution. As discussed till now RMI has an unpleasant Limitation: client and registry need access to stubs of remote service accessed; server needs access to stub and skeleton even though user code never directly accesses these classes;

kellyt
Download Presentation

5.4. Automatic Class File Distribution

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 5.4. Automatic Class File Distribution • As discussed till now RMI has an unpleasant • Limitation: • client and registry need access to stubs of remote service accessed; • server needs access to stub and skeleton even though user code never directly accesses these classes; • client and server need access to all classes they will exchange as parameters and return values of the remote method calls, i.e. there is a problem if the server returns an object of a class type the client initially did not know. • Solution: RMI provides automatic distribution of class files. When an unknown class name is encountered, the RMI framework automatically downloads the corresponding class file from a standard location. In JDK 1.2 the mechanisms is exposed through the MarshalledObject class CS 667: 5b. RMI - Zlateva

  2. Where Does RMI Look for Downloading Classes? • When in an RMI framework either the client or the server encounter an unknown class name, they attempt to load as follows: • Preferred location is the local CLASSPATH. • The unknown class is encountered in a remote call, e.g. server does not know parameter type or client does not know the returned type or stub returned from registry: the RMI framework includes the location from which class has been obtained, more specifically the URL if the class has been downloaded from a remote site, or the directory specified in 3 below: • The unknown class is encountered locally, i.e. not during a remote call: RMI attempts to download the class file from the URL specified in the System property java.rmi.server.codebase. This can be used for a central storage location for common local classes. CS 667: 5b. RMI - Zlateva

  3. Automatic Class Downloading (continued) • According to rules 2 and 3 from the previous slide RMI automatically includes class location with the class name it transmits as follows: • if the class has been already downloaded from a remote location, e.g. from a web server, RMI data includes internally the URL from which the class file can be down loaded. This URL is used for the class as well as for any other unknown classes that are needed by this new downloaded class; • Otherwise: • if the class is loaded locally, i.e. from the location set in the System property java.rmi.server.codebase, it is this location that is transmitted as a location from which the class can be downloaded. • Thus, to allow an RMI client to automatically download the stub files for the RMI server, one must specify a codebase from which the class files can be downloaded, e.g. • java –Djava.rmi.server.codebase = • http: //<host>/<downloadDirectory>/ <ServerName> CS 667: 5b. RMI - Zlateva

  4. Make three directories: (HoCo 2000) Example: Deploying the Product Info application - a) Staging Deployment Locally server: contains all files needed to run the server ProductServer.class Product.class ProductImpl.class ProductImpl_Stub.class ProductImpl_Skeleton.class for JDK 1.1 Note:The stub classes must be included as they are needed when the server registers the implementation object. Contrary to popular belief, the server does not locate the stub classes in the download directory even if the codebase is set! download: contains all class files that will be loaded by client and all the classes they depend on. Product.class ProductImpl_Stub.class ProductImpl_Skeleton.class for JDK 1.1 Note: All remote interface classes must be in the download directory, even though they are present at the client site. Otherwise server dies when trying to register server class. CS 667: 5b. RMI - Zlateva

  5. Staging Deployment Locally (continued) client: contains all files needed to start the client ProductClient.class Product.class client.policy (not required for JDK 1.1.) Note: The classes for the remote interfaces (Product) must be deployed, otherwise the client does not load. The interface classes are not downloaded! • Move the download directory to the web documents directory of the web server (A light weight web server with enough functionality to serve class files can be obtained from ftp://java.sun.com/pub/jdk1.1/rmi ); • Start web server; • Start new shell. Make sure the class path is not set to anything. Change to a directory that does not contain class files. Start RMI registry. CS 667: 5b. RMI - Zlateva

  6. Staging Deployment Locally (continued) • Start new shell. • Change to server directory. • Start server, giving URL of download directory as value of the java.rmi.server.codebase property: • java –Djava.rmi.server.codebase = • http: //localhost/download/ ProductServer • Change to client directory. • Start client. • java ProductClient • The client can also specify a codebase if the possibility exists that the server may encounter unknown class types, e.g. in argument type. • If there is a policy file, give the name of the policy file as value of the java.security.policy property: • java –Djava. java.security.policy= client.policy ProductServer CS 667: 5b. RMI - Zlateva

  7. b) Distributing to Remote Sites • Move classes from the download directory to the web server • Start server, giving URL of the web server directory • java.rmi.server.codebase property: • java –Djava.rmi.server.codebase = • http: //<host>/<webServerDirectory>/ ProductServer • In client, change all localhost instances to <host> . Recompile and start client. CS 667: 5b. RMI - Zlateva

  8. 5.5 Security Considerations • Applications, by default, do not have a security manager and code has unlimited access to resources. • dangerous when automatic class file loading is involved as is the case in RMI: a user can place arbitrary code in the class file and thus gain undesired access to recipient (client as well as server) resources. RMI provides the following defense mechanisms: CS 667: 5b. RMI - Zlateva

  9. Server Side Security SecurityManager on server to control access: RMI does not download remote class files if there is no SecurityManager installed on the server side. The SecurityManager must be installed before the object is exposed to remote access; otherwise a SecurityException is thrown during remote method call requiring downloading. The RMI SecurityManager sets the default security policy for RMI applications (not for applets). It is a simple implementation of the SecurityManager class. For code loaded from a class loader, the security manager disables all functions except class definition and access for download, i.e. it permits downloading of remote stub classes, but denies any sensitive operations such as accessing native code, files, etc. If the application needs different levels of access one can subclass the RMISecurityManager and implement appropriate policies. CS 667: 5b. RMI - Zlateva

  10. Client Side Security SecurityManager on client to control activity of dynamic loaded stubs: By default the RMI Security Manager restricts all code from establishing network connections (this is no problem for the server as the access it through the RMI registry). However, the client needs to connect to the RMI registry to contact the server objects. The solution is to provide the client with a policy file (e.g. client.policy) that gives permission for a network connection to particular port(s). (For a general discussion of policy files and their use with RMI see (HoCo 2000, Ch.9 and p.351-2 respectively. ) NOTE: For many applications the ability to remotely download classes is not necessary. In cases where automatic class file distribution is not central to the application, the installation of the RMISecurityManager can and should be omitted. CS 667: 5b. RMI - Zlateva

  11. Policy File Example: client.policy grant { permission java.net.SocketPermission "*:1024-65535", "connect"; permission java.awt.AWTPermission "accessEventQueue"; permission java.net.SocketPermission "localhost:80", "connect"; }; CS 667: 5b. RMI - Zlateva

  12. Registry Security If any hostis allowed access to the naming registry there is danger that its content will be manipulated; The Naming class allows modification of the naming registry (through various naming methods) only if the caller is running on the same machine. Therefore, the name of the registry host should be omitted when manipulating its content, e.g. // <servicePath> if the default port is used, or //:port/<servicePath> if a nonstandard port is used. CS 667: 5b. RMI - Zlateva

  13. java.rmi contains classes related to the client side of RMI; classes used by client to remotely access RMI services; includes interfaces through which remote objects are accessed and mechanisms to locate RMI services on a remote machine. (interface Remote, classes Naming and RMISecurityManager) java.rmi.server contains classes related to the server side of RMI; includes the support classes for exposing an RMI service to direct TCP/IP and proxied HTTP requests. (class UnicastRemoteObject) java.rmi.registry contains classes related to the RMI naming registry; makes it possibleto create, locate and manipulate naming registries. java.rmi.dgc contains classes that support distributed garbage collection. java.rmi.activation (JDK 1.2) contains support for the JDK 1.2 activation mechanism; this mechanisms allows RMI servers not to be running permanently, but instead that they are activated by an activation daemon only when an actual request arrives. Typically the servers are kept in a serialized passive state. 5.6. RMI Related Packages - Overview CS 667: 5b. RMI - Zlateva

  14. Interface Remote – API Specification The Remote interface serves to identify all remote objects. Only a marker interface. Any object that is a remote object must directly or indirectly implement this interface. Only those methods specified in a remote interface are available remotely, i.e. a subclass that does not implement remote can access remotely only methods of its superclass. Implementation classes can implement any number of remote interfaces and can extend other remote implementation classes. CS 667: 5b. RMI - Zlateva

  15. Class Naming – API Specification This is the bootstrap mechanism for obtaining references to remote objects based on Uniform Resource Locator (URL) syntax. The URL for a remote object is specified using the usual host, port and name: rmi://host:port/name host = host name of registry (defaults to current host) port = port number of registry (defaults to the registry port number) name = name for remote object Note: all arguments are optional CS 667: 5b. RMI - Zlateva

  16. Class Naming: Public methods– API Specification bind (String name, Remote obj) Binds the name to the specified remote object. list(String name) Returns an array of strings of the URLs in the registry. lookup(String name) Returns the remote object for the URL. rebind(String name, Remote obj) Rebind the name to a new object; replaces any existing binding. unbind(String name) Unbind the name. CS 667: 5b. RMI - Zlateva

  17. Major Difference in RMI's Handling of: Remote Objects vs. Non-Remote Remote objects are passed Local objects are passed by reference by value 5.7. Parameter Passing in RMI When passing a remote object the client receives a stub object and saves it in an object variable whose type is the same as the remote interface. Through the stub, the client accesses the actual remote object. Any changes the remote method makes to the parameter are reflected in the object, i.e. RMI passes remote objects by reference. However, nonremote (local) objects do not have a stub, e.g. the String returned from the server through the remote interface Product. In order to transport a nonremote object RMI makes a copy and sends the copy through the network. The client gets its own copy of the object, i.e. a call by value is performed. If the client sends a parameter to the remote object, any changes the remote method makes on this parameter are not reflected in the local object. CS 667: 5b. RMI - Zlateva

  18. Notes • Only remote interfaces are accessed through the stub. (A remote interface is any interface that extends Remote); • No local method is accessible through stubs. (A local method is any method that is not defined in a remote interface). • Stubs are generated only for classes that implement a remote interface, and only methods specified in the remote interface are provided in the stub classes. If a subclass does not implement a remote interface while its superclass implements the remote interface, only the superclass methods are accessible through the stub. • RMI uses serialization to transport objects over the network. Thus it can make copies of any objects as long as they are serializable, i.e. instances of a class that implements the Serializable interface. CS 667: 5b. RMI - Zlateva

  19. Passing Local Objects in RMI call vs. Local calls by value by reference Local Objects Are Passed Differently in Remote and Local Method Calls Local calls obtain a reference (memory location in local JVM) to the local object parameters and thus any changes made by the local methods reflect in the parameter. (Recall that primitive types in local calls are passed by value.) But a memory location on the local machine does not do any good to the remote JVM. To make things worse the local object has no stub on the remote JVM through which it could be manipulated. This is why the only way to pass the local object is to make a copy for the remote side CS 667: 5b. RMI - Zlateva

  20. JVM 1 void localMethod (Vector v){ …. } void main(){ localMethod ( velocity ); remoteMethod(velocity); JVM 2 void remoteMethod (Vector v){ …. } Figure: Passing Nonremote Objects velocity velocity RMI (HSH 1999, p.515) CS 667: 5b. RMI - Zlateva

  21. Parameter Passing Summary CS 667: 5b. RMI - Zlateva

  22. Client Server Example: Warehouse gives Product recommendations centralWarehouse . find(Customer c) calls remote / sends arguments returns Vector recommendations with product descriptions • Remote Interface Product • Remote Interface Warehouse • ProductImpl • WarehouseImpl • WarehouseServer • ProductImpl_Stub • WarehouseImpl_Stub • class Customer • Remote Interface Product • Remote Interface Warehouse • WarehouseClient • ProductImpl_Stub • WarehouseImpl_Stub • Customer (HiCo 2002, p.354 ff) CS 667: 5b. RMI - Zlateva

  23. Client Server ProductImpl ProductImpl ProductImpl_Stub ProductImpl_Stub Parameter Passing in Warehouse Example (HoCo2002, p.356) Vector recommendation = centralWarehouse . find(Customer c) returns Vector of recommendations with product descriptions copy Customer Customer copy ArrayList ArrayList CS 667: 5b. RMI - Zlateva

  24. Product – Remote Interface import java.rmi.*; /** interface for remote product objects (HoCo2002, p.357) */ public interface Product extends Remote { /** @returns product description */ String getDescription() throws RemoteException; static final int MALE = 1; static final int FEMALE = 2; static final int BOTH = MALE + FEMALE; } CS 667: 5b. RMI - Zlateva

  25. Warehouse - Remote Interface import java.rmi.*; import java.util.*; /** remote interface for a warehouse with products (HoCo2002, p.357) */ public interface Warehouse extends Remote { /** Gets products that are good matches for a customer. @param c the customer to match @return an array list of matching products */ ArrayList find(Customer c) throws RemoteException; } CS 667: 5b. RMI - Zlateva

  26. /** This is the implementation class for the remote product objects. */ public class ProductImpl extends UnicastRemoteObject implements Product { /** Constructs a product implementation @param n the product name @param s the suggested sex (MALE, FEMALE, or BOTH) @param age1 the lower bound for the suggested age @param age2 the upper bound for the suggested age @param h the hobby matching this product */ public ProductImpl(String n, int s, int age1, int age2, String h) throws RemoteException { name = n; ageLow = age1; ageHigh = age2; sex = s; hobby = h; } ProductImpl.java: constructor CS 667: 5b. RMI - Zlateva

  27. Serializable + Customer -age:int -sex: int -hobbies: String[] +getAge(): int +getSex(): int +hasHobby(String): boolean +reset(): void ProductImpl.java: match() /** Checks whether this product is a good match for a customer. Note that this method is a local method since it is not part of the Product interface. @param c the customer to match against this product @return true if this product is appropriate for the customer */ public boolean match(Customer c) { if (c.getAge() < ageLow || c.getAge() > ageHigh) return false; if (!c.hasHobby(hobby)) return false; if ((sex & c.getSex()) == 0) return false; return true; } CS 667: 5b. RMI - Zlateva

  28. ProductImpl.java:getDescription() public String getDescription() throws RemoteException { return "I am a " + name + ". Buy me!"; } private String name; //product description private int ageLow; //lower bound of age private int ageHigh; //upper bound of age private int sex; private String hobby; } CS 667: 5b. RMI - Zlateva

  29. WarehouseImpl.java: constructor /** This class is the implementation for the remote Warehouse interface. */ public class WarehouseImpl extends UnicastRemoteObject implements Warehouse { /** Constructs a warehouse implementation. */ public WarehouseImpl() throws RemoteException { products = new ArrayList(); coreJavaBook = new ProductImpl("Core Java Book", 0, 200, Product.BOTH, "Computers"); } CS 667: 5b. RMI - Zlateva

  30. /** Reads in a set of product descriptions. Each line has the format name|sex|age1|age2|hobby, e.g. Blackwell Toaster|BOTH|18|200|Household @param reader the reader to read from */ public void read(BufferedReader reader) throws IOException{ String line; while ((line = reader.readLine()) != null){ StringTokenizer tokenizer = new StringTokenizer(line, "|"); String name = tokenizer.nextToken(); String s = tokenizer.nextToken(); int sex = 0; if (s.equals("MALE")) sex = Product.MALE; else if (s.equals("FEMALE")) sex = Product.FEMALE; else if (s.equals("BOTH")) sex = Product.BOTH; int age1 = Integer.parseInt(tokenizer.nextToken()); int age2 = Integer.parseInt(tokenizer.nextToken()); String hobby = tokenizer.nextToken(); add(new ProductImpl(name, sex, age1, age2, hobby)); } } WarehouseImpl.java: read() CS 667: 5b. RMI - Zlateva

  31. /** Finds all products matching customer, aggregates them in ArrayList result @param c the Customer to match @returns result – an ArrayList of matching products */ public synchronized ArrayList find(Customer c) throws RemoteException { ArrayList result = new ArrayList(); // add all matching products for (int i = 0; i < products.size(); i++){ ProductImpl p = (ProductImpl)products.get(i); if (p.match(c)) result.add(p); } // add the product that is a good match for everyone result.add(coreJavaBook); // we reset c just to show that c is a copy of the client object c.reset(); return result; } …. }//end WarehouseImpl.java WarehouseImpl.java: find(Customer) CS 667: 5b. RMI - Zlateva

  32. product.dat Blackwell Toaster|BOTH|18|200|Household ZapXpress Microwave Oven|BOTH|18|200|Household Jimbo After Shave|MALE|18|200|Beauty Handy Hand Grenade|MALE|20|60|Gardening DirtDigger Steam Shovel|MALE|20|60|Gardening U238 Weed Killer|BOTH|20|200|Gardening Van Hope Cosmetic Set|FEMALE|15|45|Beauty Persistent Java Fragrance|FEMALE|15|45|Beauty Rabid Rodent Computer Mouse|BOTH|6|40|Computers Learn Bad Java Habits in 21 Days Book|BOTH|20|200|Computers My first Espresso Maker|FEMALE|6|10|Household JavaJungle Eau de Cologne|FEMALE|20|200|Beauty Fast/Wide SCSI Coffee Maker|MALE|20|50|Computers ClueLess Network Computer|BOTH|6|200|Computers CS 667: 5b. RMI - Zlateva

  33. /** This server program instantiates a remote warehouse objects, registers it with the naming service, and waits for clients to invoke methods. */ public class WarehouseServer{ public static void main(String[] args){ try{ System.out.println ("Constructing server implementations..."); WarehouseImpl w = new WarehouseImpl(); w.read(new BufferedReader(new FileReader("products.dat"))); System.out.println ("Binding server implementations to registry..."); Naming.rebind("central_warehouse", w); System.out.println ("Waiting for invocations from clients..."); } catch(Exception e){ e.printStackTrace(); } } } WarehouseServer.java CS 667: 5b. RMI - Zlateva

  34. WarehouseClient.java /** The client for the warehouse program. */ public class WarehouseClient{ public static void main(String[] args) { System.setProperty("java.security.policy", "client.policy"); System.setSecurityManager(new RMISecurityManager()); JFrame frame = new WarehouseClientFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.show(); } } CS 667: 5b. RMI - Zlateva

  35. /** A frame to select the customer's age, sex, and hobbies, and to show the matching products resulting from a remote call to the warehouse. */ class WarehouseClientFrame extends JFrame{ public WarehouseClientFrame(){ setTitle("WarehouseClient"); setSize(WIDTH, HEIGHT); initUI(); try{ Properties props = new Properties(); String fileName = "WarehouseClient.properties"; FileInputStream in = new FileInputStream(fileName); props.load(in); String url = props.getProperty("warehouse.url"); if (url == null) url = "rmi://localhost/central_warehouse"; centralWarehouse = (Warehouse)Naming.lookup(url); } catch(Exception e){ System.out.println("Error: Can't connect to warehouse. " + e); } } WarehouseClientFrame: constructor CS 667: 5b. RMI - Zlateva

  36. /** Call the remote warehouse to find matching products. */ private void callWarehouse(){ try{ Customer c = new Customer(Integer.parseInt(age.getText()), (male.isSelected() ? Product.MALE : 0) + (female.isSelected() ? Product.FEMALE : 0), new String[] { (String)hobbies.getSelectedItem() }); ArrayList recommendations = centralWarehouse.find(c); result.setText(c + "\n"); for (int i = 0; i < recommendations.size(); i++){ Product p = (Product)recommendations.get(i); String t = p.getDescription() + "\n"; result.append(t); } } catch(Exception e){ result.setText("Exception: " + e); } } WarehouseClientFrame: callWarehouse Remote Call: copy of c sent; copy of recommendations and its entries returned Local Call: Remote Call: remote object p accessed through stub to obtain description CS 667: 5b. RMI - Zlateva

  37. public void actionPerformed(ActionEvent evt) { Object[] hobbyObjects = hobbies.getSelectedValues(); String[] hobbyStrings = new String[hobbyObjects.length]; System.arraycopy(hobbyObjects, 0, hobbyStrings, 0, hobbyObjects.length); Customer c = new Customer(Integer.parseInt(age.getText()), (male.isSelected() ? Product.MALE : 0) + (female.isSelected() ? Product.FEMALE : 0), hobbyStrings); callWarehouse(c); } //UI interface code here private Warehouse centralWarehouse; private JTextField age; private JCheckBox male; private JCheckBox female; private JList hobbies; private JTextArea result; } WarehouseClient.java (continued) CS 667: 5b. RMI - Zlateva

  38. Sockets vs. RMI More efficient Overhead (serialization, synchronization) Transfer of user defined Transparent use of serialization data-structures requires explicit use of serialization Need to explicitly take care RMI calls appear to work like local calls of synchronization tasks when transferring objects in a distributed procedure Code is bulkier, longer Code is more compact, shorter, not very easy to read easier to read Security needs to be RMISecurityManager available implemented in addition 5.8. Sockets vs.RMI CS 667: 5b. RMI - Zlateva

  39. 5.9. Implementing Factories Goal: Instead of having the server running indefinitely create on request a server when needed. Implementation: Through a server factory that will create one or more instances of the server on the fly, make them accessible for the remote client. The result is a dynamical set of remote objects that can interact with each other. A factory is a server that has only one method, and this method returns remote objects that are used as servers by clients. Example: A City Info Server that give information about the city's population, temperatures, etc. CS 667: 5b. RMI - Zlateva

  40. Client Server Example: City Info pop . getPopulation(<cityName>) calls remote / sends arguments returns int for population • Client program CityClient.java • Remote Interface City.java • City_Stub.class • Server CityServer.java • Remote Interface City.java • Remote Interface Implementation CityImpl.java • City_Stub.class (adapted from Mah 2000, p.126,ff) CS 667: 5b. RMI - Zlateva

  41. City.java - Remote Interface import java.rmi.*; /** * @(#)City.java */ public interface City extends Remote{ int getPopulation (String cityName) throws RemoteException; int getTemperature (String cityName) throws RemoteException; } CS 667: 5b. RMI - Zlateva

  42. CityImpl.java - Remote Interface Implementation import java.rmi.*; import java.rmi.server.UnicastRemoteObject; /** * @(#) CityImpl.java */ public class CityImpl extends UnicastRemoteObject implements City { private String name; public CityImpl (String name) throws RemoteException{ super(); this.name = name; } CS 667: 5b. RMI - Zlateva

  43. CityImpl.java (continued) public int getPopulation (String cityName) throws RemoteException{ if (cityName.equals("Boston")){ return 4; }else if (cityName.equals("New York")){ return 20; }else{ return 0; } } public int getTemperature (String cityName) throws RemoteException{ return 5555; } } CS 667: 5b. RMI - Zlateva

  44. import java.rmi.*; import java.rmi.server.UnicastRemoteObject; /** * @(#) CityServer.java */ public class CityServer{ public static void main (String argv []) { System.setSecurityManager(new RMISecurityManager()); try{ CityImpl anyTown = new CityImpl("CityServer"); Naming.rebind("//localhost/CityServer", anyTown); System.out.println("CityServer bound in registry"); } catch (Exception e){ e.printStackTrace(); } } } CityServer.java CS 667: 5b. RMI - Zlateva

  45. CityClient.java import java.rmi.*; /** * @(#) CityClient.java */ public class CityClient { public static void main(String argv[]){ int pop = 0; try{ City anyTown = (City) Naming.lookup("//localhost/CityServer"); pop = anyTown.getPopulation ("Boston"); } catch (Exception e) { e.printStackTrace(); } System.out.println("The population of Boston is " + pop); } } CS 667: 5b. RMI - Zlateva

  46. Client Server Example: City Factory Info cityFactory . getCityServer() objCityServer.getPopulation returns objCityServer returnsint for population • Client CityFtClient.java • Remote Interface CityFactory.java • Remote Interface City2.java • CityFactory_Stub.class • City2_Stub.class • Server CityFtServer.java • Remote Interface CityFactory.java • Remote Interface City2.java • CityFactoryImpl.java • City2Impl.java • CityFactory_Stub.class • City2_Stub.class CS 667: 5b. RMI - Zlateva

  47. City2.java – Remote Interface import java.rmi.*; /** * @(#) City2.java */ public interface City2 extends Remote{ int getPopulation () throws RemoteException; int getTemperature() throws RemoteException; } CS 667: 5b. RMI - Zlateva

  48. import java.rmi.*; import java.rmi.server.UnicastRemoteObject; /** * @(#) City2Impl.java */ public class City2Impl extends UnicastRemoteObject implements City2 { private String cityName; public City2Impl () throws RemoteException{ super(); } public City2Impl(String cityName) throws RemoteException{ super(); this.cityName = cityName; } /* This constructor will be used by the factory method to instantiate a server object for a particular city */ City2Impl.java CS 667: 5b. RMI - Zlateva

  49. public int getPopulation () throws RemoteException{ if (cityName.equals("Boston")){ return 4; }else if (cityName.equals("New York")){ return 20; }else{ return 0; } } public int getTemperature () throws RemoteException{ return 5555; } /* Note: no cityName specified as parameter in the getter methods; the city name is given by the city server */ } City2Impl (continued) CS 667: 5b. RMI - Zlateva

  50. CityFactory.java - Remote Interface import java.rmi.*; /** * @(#) CityFactory.java: defines method to return an object of type remote interface City2 - a 'server' object - for a specific city */ public interface CityFactory extends Remote{ City2 getCityServer (String cityName) throws RemoteException; } CS 667: 5b. RMI - Zlateva

More Related