Notes and Updates:
Right-Click -> Project Properties -> Java Build Path -> Libraries Tab
The API documentation contains most of the details for this project. Here you will find a general overview.
For this project, you will write a simple web server in Java. Your web sever will execute Servlets that create web pages on-the-fly. When users connect to your web server, they will indicate which Servlet(s) to run as part of the URL. Your web server will create and invoke those Servlet(s) and produce a response.
There are several tasks to complete for this project, all described below in this writeup:
For this project, you will write a web server that listens on a particular port and produces a response. Your web server will be invoked from the command line. Because we may have multiple students running on the same machine, we can't have everyone using port 80 for their web server. So to avoid any conflicts, your web server should listen on port 33xxx, where xxx is the last three digits of your class account number. For example, if your account is cs433014, your server should listen on port 33014. Your WebServer should also accept an override port as a command-line argument, e.g.
The WebServer class that we have provided is currently implemented to echo back the received HTTP command. You will have to change this to invoke Servlets instead, as described more below. Please refer to the API documentation for the WebServer's runWebServer method for details on the HTTP request format. As an example, given the following HTTP request
GET /MyServlet/A/Path?Option1+Option2 HTTP/1.0Invoking findRequestURL will return
/MyServlet/A/Path?Option1+Option2and with this example URL, MyServlet is the servlet name, A/Path is the path, and Option1+Option2 is the option.
One subtlety is that the option argument to a Servlet's doGet method must be decoded using the java.net.URLDecoder.decode method found in the Java API. Further details can be found in the API documentation for the Servlet interface.
After parsing the HTTP request, your web server will obtain an instance of the appropriate Servlet from the ServletFactory class -- specifically by invoking the getServlet method with the servlet name as an argument. The ServletFactory should implement the Singleton design pattern. In particular, the constructor of the factory should be private, and the static method getInstance should be invoked to return an instance of of ServletFactory. Every time this method is called, it should return the same instance (i.e., it shouldn't create a new instance with each call).
The ServletFactory class manages Servlet creation so that every unique servlet name has one and only one instance ever created for it. So if a client requests the servlet HelloWorld twice, the first time ServletFactory will create a new instance, but the second time ServletFactory should return the same instance it created before. Be careful: Cache:Browse and Cache:Cache:Browse are two different servlets.
You must implement three new Servlets:
As an example, the following URL
/Cache:Browse/index.html
would invoke Browse and output the contents of index.html. This output would be stored in some data structure (of your own design.)
A subsequent request of the same form
/Cache:Browse/index.html
would also return the same output. However, this time, Cache should not have delegated to the Browse servlet. Instead, it should have checked its internal data structure for previously cached output for that URL.
You must also write test cases to turn in as part of your project. These should be stored in the class StudentTests, whose skeleton we have provided. You should write tests that exercise the functionality not already covered by the PublicTests. The aim is for you to get used to writing formal test cases when you program.
To evaluate the quality of your test cases, we will use the Clover code coverage tool. The higher the coverage of your test cases, the better your grade. In particular, the points awarded on the submit server for Public and Release tests total to 96 points. The remaining 4 points are assigned based on code coverage and quality of the unit tests that you provide in StudentTests.