COMP 310
Fall 2011

Lec33:  Chat App API finalization

Home  Info  Owlspace  Java Resources  Eclipse Resources

HW08 Due Date Pushed Back to Monday, 11/14/2011.

Well-Known Data Types

Change IChatRoom.getUsers()?

What should the return type of this method be? 

Take the Owlspace poll!

Starting up the ChatApp application

Remember that in order to chat, your ChatApp program must be BOTH a RMI client AND a RMI server!

Things that need to get done (NOT A COMPLETE LIST!):

 

Adding Yourself to a Chat Room

  What are the steps to add yourself to a chat room?   Do you add yourself (your IUser stub) locally and then send a message to everyone to add you to their chat rooms or vice versa?

Be careful!  What if you are already in the room?

Identifying IUsers

Question:   Is the UUID value tied to the instance of the IUser or is it tied to the instance of the ChatApp, i.e. the human operator?    That is, if one's model instantiates more than one instance its own IUser implementation, is that a different user or the same user?     Is this an API issue or not?

 

Overriding equals() and hashCode() in a proxy class to enable standard equality tests:

	private class ProxyUser implements IUser, Serializable {
				
		/**
		 * The decoree
		 */
		private IUser stub;
		
		// --- Other methods and fields elided -----------

		/**
		 * Overridden equals() method to compare UUID's
		 * @return  Equal if UUID's are equal.  False otherwise.
		 */
		@Override
		public boolean equals(Object other){
			if(other instanceof IUser) { // make sure that other object is an IUser
				try {
					// Equality of IUsers is same as equality of UUID's.
					return stub.getUUID().equals(((IUser)other).getUUID());
				} catch (RemoteException e) {
					// Deal with the exception without throwing a RemoteException.
					System.err.println("ProxyUser.equals(): error getting UUID: "+ e);
					e.printStackTrace();
					// Fall through and return false
				}
			}
			return false;
		}		

		/**
		 * Overridden hashCode() method to create a hashCode from that is hashCode of the UUID since
		 * equality is based on equality of UUID.
		 * @return a hashCode of the UUID.	
		 */
		@Override
		public int hashCode(){
			try {
				// hashCode is shorter than UUID, but Java spec says that if two objects are equal then
				// their hashCodes must also be equal, which will be true here since equals() is based on 
				// UUID equality.  Java does NOT require that unequal entities have unequal hashCodes. 
				return stub.getUUID().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();  // return some sort of hashCode
			}
		}
	}

 

Unknown Data Type Management Protocol Options:

(Sub-items are a matched set)

  1. Receiver attempts to process a received data packet and discovers that they don't know how to process it.
  2. Receiver returns IUnknownData_XmitStatus object to sender.
    1. Receiver caches the unknown data waiting to process it, OR
    2. Receiver  discards unknown data.
  3.  Sender receives IUnknownData_XmitStatus and sends DataPacket<IAddCommand> to receiver ONLY.
  4. Resending data?
    1. No need to resend if data was cached by receiver.  OR
    2. Resend data
      1. Data is automatically resent  -- sender must remember what data was originally sent.   OR
      2. Sender waits for request to resend data.   -- resend data to everyone?

Use Owlspace poll to decide between paths "A", "B-i" and "B-ii" above.   

 

ICmd2ModelAdapter Interface

import java.awt.Component;

import comp310f11.rmiChat.IUser;

/**
 * Interface between a DataPacketAlgoCmd and the model of a ChatApp system.   Allows a foreign command
 * access to some limited services of its host ChatApp.  
 */
public interface ICmd2ModelAdapter {
	/**
	 * Gets a reference to the local IUser stub which is needed to instantiate IStatus return objects.
	 * @return The local IUser's stub.
	 */
	public abstract IUser getLocalUserStub();
	
	/**
	 * Appends the given string onto a text display somewhere on the host ChatApp's GUI.
	 * @param s A string to display
	 */
	public abstract void append(String s);
	
	/**
	 * Allows the command to give a java.awt.Component to the host ChatApp to be displayed on 
	 * its GUI somewhere. 
	 * @param name  A title for the component, useful for tabs, frame titles, etc.
	 * @param newComp  The component to display.
	 */
	public void addComponent(String name, Component newComp);
}

 

This implies the existence of a method on ADataPacketAlgoCmd:

public abstract void setCmd2ModelAdpt(ICmd2ModelAdapter cmd2ModelAdpt);

Important implementation detail: 

Keeping a field value from being serialized:

As per the above API standard, a ADataPacketAlgoCmd implementaion may have a field of type ICmd2ModelAdapter that holds a reference to current adapter.    When a command is transferred from the sender to the receiver, the command may have been already connected to the sender's model via an ICmd2ModelAdapter implementation created by the sender. 

But when the command is sent to the receiver, the receiver will install its own ICmd2ModelAdapter that connects to its own model and view.   It is not necessary or desirable to serialize and transmit the value of the adapter reference  esp. since such adapters are usually anonymous inner classes. 

To tell Java not to serialize and transmit the value of a field, mark the field with the keyword "transient". 

Example:

private transient ICmd2ModelAdapter cmd2ModelAdpt; 

When this the command is deserialized at the receiver, this field will be null.    Thus, you MUST call setCmd2ModelAdpt() on the new command BEFORE it is installed into the data packet processing visitor (e.g. algo.setCmd())!

 

Java How-To's

 

 

 


© 2011 by Stephen Wong and Scott Rixner