Requirements
In this iteration of Project 1, you will be building a Client/Server model
that uses your API to allow multiple users (clients) to configure Pizzerias
(server). Your Client/Server application will be via sockets (in the
java.net API) and use serialization for communication between the clients and the server.
The Client will comminucate with a user and the Server will be the repository for
the LinkedHashMap of Pizzerias.
The Server will have the following capabilities:
- Host all PizzaConfigs in a single data structure accessed through your Pizzeria API.
- Receive a Properties object from which to build an PizzaConfig Object and add it to the list.
- Respond to Client requests for retrieving the list of available Pizzerias.
- Respond to Client requests to delete a particular Pizzeria.
- Respond to client Requests for retrieving a configuration by passing back an instance of
PizzeaConfig object. The object should be sent to the client via serialization.
- Respond to Client requests to update a specific Pizzaeria's base price.
- Respond to Client requests to add an option a specific option set.
The UI will provide a menu of the following options to the user:
- Upload a Properties file.
- Show the available Pizzerias.
- Print a Pizzeria.
- Delete a Pizzeria.
- Configure a Pizzeria.
- Update the base price.
-
- Add an option to an existing option set
- For uploading from a file:
- A user will be prompted to provide a path to Properties file. Once the path is provided, the
Client will load the Properties object and pass the Properties object to the Server.
- The Server will parse the Properties Object to create a PizzaConfig object and
add the new Pizzeria or update an existing Pizzeria (using your API).
- For showing the available Pizzerias:
- The UI will use the Client to request the list of Pizzerias from the Server and
the UI will display it to the user.
- Hint: What is this data and what data type is this list? What does this mean the
Server does?
- For printing a Pizzeria:
- A user will be prompted with a list of available Pizzerias on the Server.
- A user can select a particular one and will be shown the base price and all available options.
- Once the user has selected one, the UI will have the Client request it and then the Server will
serialize that PizzaConfig instance back to the Client.
- The UI then displays it.
- For deleting a Pizzeria:
- A user will be prompted with a list of available pizzerias.
- The user can select one and the Client will instruct the Server to delete it.
- For configuring a Pizzeria:
- A user will be prompted with a list of available Pizzerias on the Server from
which to select.
- Once the user has selected one, then the Server will serialize that instance
back to the Client.
- The UI will then use that instance and allow the user to configure the Pizzeria.
Because this is a course-assignment, you do not need to actually provide the ability to
update all aspects of the configuration on the Server, but just demonstrate that you can.
For this assignement, allow the user to:
- Update the base price.
- View the existing option sets, select one, and add an option.
Make sure to account for the fact that multiple users may be updating the same Pizzeria at
the same time. Your API accounts for thread-safe behavior; what must the Client account for?
We can discuss this in class further.
Your first UI is a character-based one as described above. Your second UI will be a Swing GUI.
It will also be a client (you can copy in the needed code).
For your GUI, allow the user to select a Pizzeria from a drop-down,
see the base-price, and then update the base price. Note that the
GUI is much smaller in scope than the character-based UI and will not
have separate screens, but a single screen that supports the
functionality.
Your GUI must re-used the client code (you can copy it into the new project, but will have to make changes twice if it needs updating), so make sure the logic and communication code is de-coupled
from your character-based UI.
Note: The Server in this context only acts as an in-memory storage repository for Pizzerias.
Plan of Attack
Your goal should be to complete most of Step 1 and all of Steps 2-5 (below) after the first week.
Let's start with a recap of what we have built so far. Here is an overview of what you have
done by end of V1.2. You have:
- the model package containing the PizzaConfig, OptionSet and Option classes.
- the exception package containing custom exceptions that provide self-healing code to handle
unexpected inputs.
- the io package containing some file I/O class.
- the wrapper package containing the PizzeriaAPI, ProxyPizzeria, CreatePizzeria and
UpdatePizzeria classes/interfaces.
- the test package containing your test classes.
- (possibly) the util package containing utility classes.
- scaled your system with support for multiple users via thread-safe behavior in your API.
Let's start design for Version 1.3
Step 1: Design your client/server communication protocol.
- Work on the protocol on paper and design something to support the actions your client and
server need to implement.
- Your design should be for a
stateless protocol.
- Note: Your Client and Server MUST comminucate via object serialization.
Step 2: Read a configuration from a properties file.
Here's an example demonstrating how to read data from a Properties file using a Properties object. The properties file is a text file that follows a specific format:
Pizzeria=CMU Pies
BasePrice=5000
Option1=Standard Veg
OptionValue1a=onion
OptionValue1b=cabbage
Option2=Premium Veg
OptionValue2a=red pepper
OptionValue2b=pineapple
Note: this is not the answer for your project, just a sample!
Here is sample code for reading a properties file and processing the values into some local
variables.
Properties props= new Properties();
FileInputStream in = new FileInputStream(filename);
props.load(in); // This loads the entire file in memory.
// OK for this version of the assignment.
String p = props.getProperty("Pizzeria"); // This is how you read a property.
// It is like getting a value from HashTable.
if(!p.equals(null))
{
String price = props.getProperty("BasePrice");
String option1 = props.getProperty("Option1");
String optionValue1a = props.getProperty("OptionValue1a");
...
}
Design the format of your Properties file to support all aspects of creating a Pizzerias.
Add a new function in your existing class in the io package (the one that reads from a text file)
to take and parse a Properties object. Update the rest of the system to support reading in a
Pizzera from a Properites file and adding it to the LHM.
To enable this feature you will update your API to allow adding a Pizzeria from a Properties
object. Where does this method belong in order to be consistent with your API design? Hint: think about your interface design.
Think about the Client/Server aspect of this. What should the Client take care of?
What should the Server take care of? This will help you in your design.
Step 3 & 4: Create your Character-based UI, Design your Client Interface, and Implement a
Test Client
Think about what the Client should do versus what the Server should do.
You will implement it so that the Pizzerias are on the Server - your real client will have no
knowledge of the API; it will ONLY be used by the Server code.
Your Client code will comminucate with the UI (via method calls) and with the Server
(via sockets and using your protocol).
For this step however, you will define the Client interface, use a test client to implement
it, and test your UI and communication with the Client code.
- Create a package called ui (for your character-base User Interface).
- Create a package called client.
- Create an interface called PizzeriaClient. This interface should specify the methods
that the Client will need to communicate with the Server.
- Create a TestClient that implements this interface.
- The test Client will make direct calls to the API. Later you will create the real
Client that will communicate with the Server.
- The hope is that you will have little-to-no changes
in your UI code.
- The better your design demonstrates separation of concerns and loose-coupling, the closer
too this ideal you will be.
- Code the UI (as specified above).
- In your UI, instantiate and use the TestClient (use polymorphism; is there a helpful pattern??).
Step 5: Create a Swing GUI
- Optional: Create a a new project for your GUI.
- Create a package called gui (for your Swing-base Graphical User Interface).
More on these next week
Step 6 & 7 (Phase 2): Create the Real Client and Create the Server code
- Optional: Create a a new project for your Server.
- Create a package called server for your Server code.
Phase 2 notes
Submitting your Work
Please submit your source code, test Properties files, UML,
and a runnable jar for your
project(s).
Grading your submission
- Program Specification/Correctness
- UI is easy to follow.
- No errors, program always works correctly and meets the specification(s).
- The code could be reused as a whole or each routine could be reused.
- Packages are created as described in the Plan of Attack.
- Exposure to LinkedHashMap object is done only through interfaces.
- Client and Server support all functionality needed by the User Interfaces.
- Client and Server classes used Object streams only.
- Only the Server uses the API (in other words, the list of configurations is ONLY on the Server).
- Server supports multiple Clients.
- Readibility
- No errors, code is clean, understandable, and well organized.
- Code has been packaged and authored based on Java Coding Standards.
- Documentation
- The documentation is well written and clearly explains what the code is
accomplishing and how.
- Detailed class diagram is provided of the design.
- Code Efficiency
- No errors, code uses the best approach in every case. The code is extremely
efficient without sacrificing readability and understanding.