CS11 Advanced Java Lab 6 - Networked Boggle!

This week you will update your Boggle application to operate as a client to a networked Boggle server. After this lab you should be able to start multiple Boggle clients and have them connect to your server. Clients can then start rounds of Boggle, play each other, and then find out what their final scores are.

All of the communication for this week's lab will take place using Java's Remote Method Invocation (RMI) mechanism. This simplifies the server implementation a lot, because we don't need to create a specific protocol for our clients and server to communicate with each other. However, we do need to be sure to adhere to all of RMI's conditions and constraints.

Because writing a Boggle server that can handle multiple concurrent connections is actually pretty complex, you will get to use an existing implementation of the Boggle server this week. All of the server logic is implemented in such a way that you should be able to just drop the implementation into your project.

However, the Boggle server doesn't actually support RMI yet! You will need to update the server code to support RMI calls, and you will need to update your client to establish an RMI connection to the server.

Here are the files that you get to use this week:

All of these files are pretty well documented, so you should be able to read through them to get a good idea of what is going on.

Server Tasks

Here are your tasks for the Boggle server code:

  1. Update the BoggleServer interface so that it can be used as an RMI remote interface. Remember that all remote interfaces must satisfy these conditions:
  2. Next, update the Boggle server so that it can actually expose its remote interface via an RMI registry. Add a main() method to the BoggleServerApp class, that performs the following steps:

    Of course, just about all of these operations could fail in some catastrophic way, so wrap all of these operations with a try/catch block that will print a helpful error message (preferably including the exception details and the stack-trace) if a problem occurs. Similarly, print a message like "Boggle server is ready." if all steps complete successfully.

And that's it! When you compile and run your Boggle server, it should now be exposed on an RMI registry listening to port 1099. Make sure these steps work correctly before going on, or else there is no point in trying to get the Boggle client to talk to the server.

Client Tasks

Once the Boggle server is exposed via RMI, you must also update your Swing Boggle application to use the server instead of running standalone. Because the server is exposed via RMI, the Boggle client must contact the RMI registry and then retrieve the stub for the Boggle server's BoggleServer interface. Fortunately, this is a very simple process.

  1. Update your Boggle application's main method to take 1 or 2 arguments:

    If the user doesn't get these arguments correct, make sure to print out a helpful usage message.

  2. Next, your main() method should retrieve the Boggle server's stub. Use the java.rmi.registry.LocateRegistry class again to connect to the registry, but this time use the static getRegistry(String) method that takes a hostname. (Note that this method defaults to using port 1099, which is why we used this port earlier for the server.)

    Once you have retrieved a Registry reference, use the lookup(String) method to retrieve the Boggle server's remote interface. You will pass in the same name that you used with the bind() method earlier. The result can be cast to BoggleServer since the stub implements this interface. (Note that it cannot be cast to BoggleServerApp, however!)

    Again, these steps could fail horribly, so wrap them in a try/catch block that prints an error on failure, and then terminates the program. There is no reason for the program to continue if it cannot contact the server!

  3. Finally, the main() method should construct an instance of your application, and pass both the username and the BoggleServer stub as arguments to your application's constructor. The app-object needs to save these values in order to make the proper RMI calls to the server. Don't store them as static values; that is just gross!

Once your client application can contact the Boggle server's RMI registry, you are ready to incorporate the RMI server calls into the client's controller.

  1. When the "Start Game" button is pressed, you need to update the controller code to call the Boggle server's startGame() method with the username specified on the command-line. This method will block until the server is ready to start a game, and the return-value will be the Boggle board to use. Use this Boggle board instead of one that the client generates.

    Pretty much everything else will stay the same in this method, except that the RMI call could throw exceptions! So, do the server-call first, and only do the other operations (e.g. enabling the "Add Word" and "Clear Word" buttons) if the server call doesn't report any exceptions. (The easy way to do this is to wrap the entire "start game" functionality in a single try/catch block, with the server-call first, so that any exception at the start will just skip all the other processing.)

  2. The client application knows that the round is over when the timer finally expires. When this happens, an ActionEvent will be fired and your controller will perform the "game over" operations.

    Update this "game over" code to make a call to the server's gameOver() method, passing both the client's username and the word-list that the client generated. Again, this method will block until all playing clients have reported their results. The server will compute the overall game results at this point, then return a GameResults object that clients can then look at.

    Just like with the "start game" operation, this RMI call could fail, so you need to handle the exceptions properly. However, unlike the "start game" code, the game is over whether you can talk to the server or not! So only wrap the RMI call in the try block, and still perform the UI update operations whether the RMI call works or not.

Once you have completed and debugged all of this functionality, you should be able to start 2-5 Boggle clients, making sure to specify unique usernames, and then have them connect to your Boggle server. When clients start a round, all clients should end up with the exact same Boggle board, and at the end of the round, all clients should submit their own word-lists to the server.

Pretty awesome! Now there is only one more step to get this system fully operational.

Boggle Server Game Logic

There is one more thing for you to complete on your Boggle server; you must implement the game logic that handles scoring a single round of Boggle. In the GameResults class there is a computeResults() method that takes a list of ClientInfo objects. You need to implement this method, as outlined in the comment contained within this method. The process is pretty simple:

And that should be it! Once you have this functionality, the entirety of the Boggle game should now be implemented.

Done with Lab 6...

Once this is all done, make sure you have committed your work, and leave your efforts in your ~/cs11/advjava/lab6 directory.


Copyright (C) 2008, California Institute of Technology. All rights reserved.
Last updated May 14, 2008.