COMP 310
Fall 2011

Lec32: ChatApp Design...

Home  Info  Owlspace  Java Resources  Eclipse Resources

Current design issues:

  1. Use case for adding a user
  2. Processing DataPacket<T>
  3. Return value of sending a data packet?   
  4. Comparing remote stubs and serialized objects.
  5. Processing new commands

Multiple chat room support

Multiple Chat Room Support

Comparing IUsers

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:

  1. Your code always performs the comparison:   write a utility method, ala "public boolean compareUsers(IUser user1, IUser user2){...}" that will return true or false depending on if the two stubs are "equal" or not.   The rest of the code always calls this invariant, encapsulated comparison method. 
  2. You do NOT have access to the comparison process:   For instance, you are using a dictionary, where the comparison takes place deep inside the dictionary using the objects' equals() and hashCode() methods.  In that case, you need decorate the IUser with something that overrides the equals() and hashCode() methods to retrieve transparently retrieve the necessary information but without throwing RemoteException. A private class like such will do the trick:
	/**
	 * 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