The Single Most Important Thing You Can Do

is to begin your implementation immediately.
The earlier you begin your implementation, the greater chances you have of actually finishing the project.

Begin With The Basics

Set up your project + package hierarchy (updated 3/8/22)

  1. Accept the GitHub Classroom assignment for the ChatApp assignment (2-3 person assignment team) and clone the repo.
  2. Accept the GitHub Classroom assignment for the ChatApp Design repository (~10+ API design team). Do NOT clone that repo!!
  3. Follow the directions in Canvas to add the ChatApp Design repository as a submodule mapped to the src/common folder.
  4. Push the assignment repo to GitHub.
    • IMPORTANT: Whenever changes have been made to the contents of the common package, ALWAYS push the associated submodule FIRST, then push the main assignment repo!
  5. Create a new package under src, named netid1_netid2, where netid1 is the netID of the team lead (add a netid3 if there is a 3rd person on the team). ALL YOUR CHATAPP IMPLEMENTATION CODE WILL GO IN HERE.
  6. Make sure that your module-info.java file has the necessary entries. See the latest information in Canvas for the current requirements!

Set up the main MVC

  1. Set up an MVC, same as you've done six times now.
  2. Implement the JFrame View class. Your ChatApp view should have components for at least the following capabilities (depending on your API, the view may need to have more than just this):
    • Using the discovery server.
    • Creating a new chatroom.
    • Seeing the users you're connected to.
    • Seeing a list of the chatrooms you're connected to.
    • If you're supporting invites to chatrooms, a way to invite a selected user to a chatroom.
    • If you're supporting request-to-join for chatrooms, a way to see what chatrooms are available on the network, and to join one.
    • A panel (I'd recommend a tabbed pane) into which chatrooms can be installed as needed.
      • The provided.utils.view package provides convenience classes that make it easy to create tabbed UIs with exactly the functionality needed for this assignment.
    • A button to quit the application. ALWAYS USE THIS WHEN EXITING YOUR CHATAPP.
  3. Create any methods you need in your adapters (at a minimum, the ability to send the quit instruction to the model) and connect them through the Controller.
  4. Test any methods you've created so far and ensure they work.

Set up the mini-MVC

  1. Create packages somewhere in your project under the netid1_netid2 package that will contain the components for a chatroom mini-MVC. Set up a mini-mvc in those packages. The important differences between a mini-MVC and a normal MVC are
    • The mini-controller should not have a main method, since it should never be run on its own.
    • The mini-view should be a JPanel, not a JFrame, since you should be able to place it within the main view.
    • There should be adapters that allow a communication pathway between the main mvc and mini-mvc. The exact form of this pathway is up to you.
  2. Implement the mini View class. Your chatroom view should have components for at least the following capabilities (depending on your API, the view may need to have more than just this):
    • Leaving a chatroom.
    • Sending a text message.
    • Displaying all the text messages that have been sent in the room so far.
    • Sending a message whose type is not API-defined.
  3. Create any methods you need in your adapters (at a minimum, the ability to send the leave chatroom instruction to the mini-model) and connect them through the mini-controller.

Connecting the main- and mini-MVCs

  1. Give the model a way to tell the controller to create a new chatroom. Two good implementations of this are:
    • Create a method in the model-to-view adapter that adds a chatroom. Rather than passing this along to the view, have the controller intercept this call and create the chatroom.
    • Create a model-to-controller adapter with a method to create a chatroom.
  2. The implementation of this method should look something like:
    • Create an adapter that allows the mini-controller to access methods on the main model.
    • Construct a new mini-controller and give it this adapter. Start the mini- controller. This should start the mini-model and mini-view.
    • The mini-controller, upon construction, should create an adapter that allows the main model to access methods on it. Retrieve this adapter and send it to the main model for later use.
    • Retrieve the mini-view from the mini-controller and send it to the main view for installation.
  3. Connect the buttons in the main MVC such that creating a chatroom tells the main model to construct a new chatroom MVC.
  4. Connect the buttons in the mini-MVC such that the 'leave chatroom' button tells the main model to delete that chatroom from both its internal store as well as remove it from the view. A common mistake is only removing the chatroom's view and forgetting to actually leave it. These are two different things, and you must do both.

Next Steps

Start using your API!

  1. At a minimum, instantiate your connection-level remote objects in your main MVC.
  2. Stub them, bind them to your registry, and establish an initial connection between two ChatApp instances from people in the same group.
  3. Include some way to communicate - even printing out to the other person's console will indicate at least rudimentary connection capabilities and reassure you that everything is working properly.

FAQ

Questions I've been getting a lot


What exactly is API-dependent?

The simple answer is: anything that deals with network communication. In practice, it's a little more complex than that - the API does have to define exactly what's sent across the network and how it's sent, but it also needs to define expected behaviors and processes.
For example, the API could specify that no user can disconnect from the network without notifying everyone else of their departure.


What's a well-known message type?

A well-known message is simply one that, right out of the box, everyone using your API will have to implement. For example, if an IStringMessage is defined as a well-known type, that means that everyone has to implement their own command to support it. Nobody on the network should ever have to request/send the command that processes it.


What's the deal with commands, datapackets, and the extended visitor?

In terms of the Visitor Design Pattern, a datapacket is a host and the extended visitor is, well, the visitor. Fundamentally, this means that when you receive a datapacket, all you need to do to process it is call:
datapacket.execute(visitor)
Delving a little more into specifics, the visitor is like a container for commands. Each command 'installed' in the visitor handles a specific case, or type, of input. In this case, each command will handle a different message type from the datapacket.
A command is just an algorithm that processes a message in some way.


Remote vs Serializable Objects

Remote Objects Stubs Serializable Objects
Cannot be sent across the network Can be sent across the network Can be sent across the network
Exist as a standalone object Created from and dependent on remote objects Exist as a standalone object
Can do their own processing Cannot do their own processing - call back to the original remote object to do processing for them Can do their own processing

Synchronous vs Asynchronous Message-Sending

Synchronous Asynchronous
Sender waits for a response from the receiver Sender does not wait for a response from the receiver
Generally non-void return types Generally void return type
Sending and receiving requests/commands usually not done on different threads Sending and receiving requests/commands must be done on different threads