Rental Car Client / Server
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.
The Distributed
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).
Per Vehicle Data:
ID number
which uniquely identifies it (ie. VIN).
Year / Make
/ Model info (ie. 2004 Toyota Camry)
Rental Type
– Truck, Luxury Car, Mid Size Car, Compact Car
Mileage at
Last Check-out or Check-in
Rental
Status: Available, Rented
Renter’s
Name and Driver’s License Number
Server Inventory
Data:
List of
rented and available vehicles in the current inventory
Operations provided
by the server:
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.
User Interfaces
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)
{
SwingUtilities.invokeLater(
new Runnable()
{
public void run()
{
outputTextArea.append(message);
}
}
);
}
Networking
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.
Data Management
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.
Phases of the Programming Project
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.