This week we have been looking at using Java TCP Sockets and data streams to build networked applications. Your next programming assignment is to design and build a rental car management system using TCP and appropriate data streams. This is a multi-part assignment. In the last phase of this assignment, you will have the opportunity to add threads and synchronization to this application.
Our application will be a rental car inventory management system. Cars can be added to the pool of cars available to rent. A car can be rented, and a car can be returned after rental. Any employee at the rental agency can do any one of these operations. More than one employee is expected to be performing these operations at the same time, so access to the information about the car inventory will need to be synchronized (when threads are added).
Add Vehicle: The client must provide a unique ID number, the year – make – model info, the type of rental vehicle, and the current mileage. The server will add a new vehicle to its list of available vehicles. The server should verify that the VIN is unique. The client should receive an indication of success or failure from the server.
Get Vehicle Data: The client can request to see the next vehicle’s data. The client must specify a specific state (ie. Available, Rented, Any) and a specific rental type (ie. SUV, Truck, Any). The server must keep track of the client’s position when scanning through the inventory. The server returns the next vehicle’s data which matches the requested search criterion along with any rental information. If nothing matches, the server returns a failure indication to the client.
Rent Vehicle: The client must provide the ID number of the vehicle being rented, along with the renter’s name and driver’s license number. The server must check to make sure the requested vehicle is available, and if so, places the vehicle into the rented state. The server returns an indication of success or failure to the client.
Return Vehicle: The client must provide the ID number of the vehicle being returned, along with the current mileage of the vehicle. The server updates the vehicle’s inventory data accordingly, returning the vehicle to the available state. If successful, the server returns the miles driven by the renter. Otherwise, an error indication is returned.
I am providing you with the source code for the client side GUI. I am doing this so you can start to focus on the networking aspects of this project. The CarInventoryClient.java file, which I am providing, is setup to be part of the default package of a CarInventoryClient project. This means that you need to create a project called CarInventoryClient, and copy the CarInventoryClient.java file into that folder. All other classes needed for the client should be part of this project. This file contains pseudo code to help you with the program logic of the client program.
I am also providing you a CarInventoryServer.java file. This file is setup to be part of the default package of a CarInventoryServer project. This means that you need to create a project called CarInventoryServer, and copy the CarInventoryServer.java file into that folder. All other classes needed for the server should be part of this project. This file contains pseudo code to help you with the program logic needed for phase 2 of the server program. This server is setup with a simple user interface which consists of a scrollable text area and should be used by the server to show what the server is doing. This will help you during development.
For the server, you will need to use a method that uses the SwingUtilities invokeLater method to update the scrollable text area. This is needed because Swing components are not thread safe, and the server will be multithreaded by the time you are finished with this project. The following code is an example of a method that takes a String argument and safely updates a GUI component with the string:
private void displayMessage(String message)
public void run()
The client and server must use TCP as the basis for their communication. A TCP connection should be established between the client and server whenever a client is started. On the server side, once a connection has been established to a client, the server should call a separate method to handle the client communication. This will make adding multithreading easier! This method should take the client socket as an input parameter. This method should setup the data streams using local variables only! The client socket variable MUST NOT BE A MEMBER VARIABLE! Using member variables here would create difficulties for multithreading! The server side should only close the connection when the client has indicated that it has completed its work. Initially, the client handler will be a normal method in the server class. Later on, this will be a special method that enables the server to start a separate thread to handle each client.
For the client and server files I provided, I have set things up so the server name and port # can be passed into the client as command line arguments. The server side only needs a single argument specifying the port number it will use. For debugging purposes, both the client and server can run on the same machine, therefore, you can use localhost as the host name.
The exchange of information needed between the client and the server will be based on the exchange of message objects and will require the use of ObjectInputStreams and ObjectOutputStreams by both the client and server. You must define a Message class that contains the data items you need to exchange between the client and server. When the client wants to communicate with the server, it will create an object of the Message class, fill in the necessary data items, and send the object to the server. This Message class should be placed in a separate file by itself. This Message class can be added to both the client and server projects. Make sure that this class file is identical in both the client and server projects, or things will not work! The Message class should have public data members and no methods, therefore, the member variables can be directly accessed by both the sender and receiver of the message object. The Message class will also need to be Serializable so that it can be transmitted with Object streams.
A few words of warning about using Object streams… make sure that you set up the ObjectOutputStream first and flush it before you try to setup the ObjectInputStream. This must be done on both the client and server side. Also, if your implementation sends the same message object more than once, you may experience some unexpected results. Even though the data inside the object changes between sending it the first and second time, the ObjectOutputStream remembers what it sent the first time, and that is what is received the second time. You can eliminate this problem by calling the reset() method on the ObjectOutputStream before you send the same object a second or third or fourth time.
The server must manage the inventory information. This gets a little tricky when we get to the point where there are multiple client threads trying to rent the same car at the same time. Management of the inventory data will need to limit access to the inventory data to a single thread at a time. In order to make this problem simple to solve, you should build a separate InventoryManager class which provides the methods needed for the server to do the necessary operations. This class will also need to be part of the server project. Methods will be needed to add vehicles, to rent and return vehicles, and to search for vehicles based on status and type.
The InventoryManager must maintain a list of vehicle information that includes rental information. In order to make this part of the project easier, I would recommend storing objects of your Message class in the list, rather than defining a separate class for storing the vehicle data. The InventoryManager could use either a Vector or an ArrayList to store VehicleData objects. Both of these classes will grow to whatever size is needed, based on how many vehicles are added to the inventory.
NOTE: The development approach for this project will be to get things working to support a single client at a time, and then make a few minor changes to support multiple clients simultaneously.
Phase 1: Design the message exchange between the client and the server. For each of the operations described in this document, specify the details of what values the client sends to the server and what possible values the server sends back to the client. Make sure you consider any error returns from the server. Design your Message class based on this specification. Turn in a short written description of the message exchange and your Message class source code. Your written description should be no more than 1 page. This is due by the end of Week 3.
Phase 2: Implement the TCP and Object stream network communication between the client and server. At this point, you should be able to send message objects between the client and the server and vice versa. Have your client send a real add, get, rent, and return message. The server should display the contents of the received message, and return message indicating the requested operation failed. The client should display the returned message content appropriately. Turn in screen shots of the client and server which illustrate the message exchange. Also turn in your client and server source code. This is also due by the end of Week 3.
Phase 3: Complete implementation of the client and the single threaded server. This means implementing the Inventory Manager class and adding code to the server to make use of the Inventory Manager methods. Pseudo code for the Inventory Manager has been provided. Phase 3 will be complete when all functionality to support a single client is working. Take screen shots of successfully adding a vehicle, getting vehicle information, renting a vehicle, and returning a vehicle. These will be turned in at the end of Week 4.
Phase 4: Modify the server to make it multithreaded. This includes changing the Inventory Manager to add synchronization. Take screen shots of the server with multiple clients trying to rent the same car at the same time. Turn in all your client and server source code. This will be turned in at the end of Week 4.
For Week 3, complete phase 1 and 2. Submit a Word document that contains the following: the written description of the message exchange from phase 1, the Message class code from phase 1, screen shots of the output of both the client and the server programs from phase 2, and your source code for the client and server from phase 2. Get a sign off on your cover sheet for Phase 2!
For Week 4, complete phase 3 and 4. Submit a Word document that contains the following: from phase 3 - screen shots of successfully adding a vehicle, getting vehicle information, renting a vehicle, and returning a vehicle, from phase 4 - screen shots of the server with multiple clients trying to rent the same car at the same time, followed by all source code for both client and server. Get a sign off on your cover sheet for Phase 4.