COMP 310
|
Lec33: Chat App API finalization |
![]() ![]() ![]() ![]() ![]() |
What should the return type of this method be?
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!):
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?
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?
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 } } }
(Sub-items are a matched set)
Use Owlspace poll to decide between paths "A", "B-i" and "B-ii" above.
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())!
© 2011 by Stephen Wong and Scott Rixner