COMP 310
|
Lec32: ChatApp Design... |
Comparing RMI stubs is a tricky business because the stubs are separately serialized objects, so using trying to compare to stubs for equality using the usual equals() method always fails: stub1of User.equals(stub2of User) always returns false.
The only way to compare 2 RMI stubs is to compare all the available public values obtainable through the stubs. There are (at least) two different ways to achieve this, depending on whether or not you have access to the actual comparison process:
/** * Private class to decorate an IUser to override the equals() and hashCode() * methods so that a dictionary, e.g. Hashtable, can properly compare IUsers. * @author swong * */ private class ProxyUser implements IUser, Serializable { /** * Required for proper serialization */ private static final long serialVersionUID = 5682755540794448769L; // regenerate this! /** * The decoree */ private IUser stub; /** * Constructor for the class * @param stub The decoree */ public ProxyUser(IUser stub){ this.stub = stub; } /** * No-op decoration of the getName method. Just pass the request to the decoree. * @return The name of the user. * @throws RemoteException */ @Override public String getName() throws RemoteException { return stub.getName(); } /** * Get the decoree * @return the decoree */ public IUser getStub() { return stub; } /** * No-op decoration of the sendMsg method. Just pass the request to the decoree. * @param data The data to be sent * @param sender The sender of the data * @return The status of the transmission * @throws RemoteException */ @Override public IStatus sendMsg(ADataPacket data, IUser sender) throws RemoteException { return stub.sendMsg(data, sender); } /** * Overriden equals() method to simply compare hashCodes. * @return Equal if the hashCodes are the same. False otherwise. */ @Override public boolean equals(Object other){ return hashCode() == other.hashCode(); } /** * Overriden hashCode() method to create a hashcode from all the accessible values in IUser. * @return a hashCode tied to the values of this IUser. */ @Override public int hashCode(){ try { // Only name is available for now. return stub.getName().hashCode(); } catch (RemoteException e) { // Deal with the exception without throwing a RemoteException. System.err.println("ProxyStub.hashCode(): Error calling remote method on IUser stub: "+e); e.printStackTrace(); return super.hashCode(); } } }
Wrap any incoming IUser objects with a ProxyUser instance and use ProxyUser objects whenever comparisons need to be done.
Strip off the decorator by returning only the stub inside of it when any outside entity requests the IUser object. This keeps the decoration fully private and encapsualated.
For more information on comparing remote objects, please see the Resources web page on Comparing Decentralized Objects.
© 2011 by Stephen Wong and Scott Rixner