COMP 310
|
Lec32: ChatApp Design... |
![]() ![]() ![]() ![]() ![]() ![]() |
Weekend advice: Write code to try to get your proposed API to work.
(See the Java Resources web page on How To Make Mini-MVC's Inside a Main MVC)
Update 12/2015: Java 8 RMI stubs do support equals() and hashCode() comparisons, up to a point and can be used successfully as keys in hash tables, etc. See the Java Resource site page on Comparing Deserialized Objects for more information and possible restrictions. This will eliminate the need for the various solutions discussed below for many, but not all situations.
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 Deserialized Objects.
© 2015 by Stephen Wong