Steps to integrating with the web server (S.0) Keep Calm! Only a tiny bit of new code is needed! (S.1) Understand the web server framework (S.2) Understand the example server (S.3) Incorporate your SDLParser (S.4) Optional components (S.5) Document version ---------- ((S.0)) Keep Calm! Only a tiny bit of new code is needed! ((S.0.1)) If you want get 'hands on' fast to orient yourself and reduce anxiety, you can jump ahead to (S.3.2) to try out the sample code -- BUT MAKE SURE YOU READ AND UNDERSTAND THE REST OF THIS SPEC TOO! ---------- ((S.1)) Understand the web server framework ((S.1.1)) Packages ((S.1.1.1)) The web server is broken into two main packages -- - com.putable.siteriter.server, which contains the general web server framework, to be used without modification, and - com.putable.siteriter.example, which contains demonstration classes that use the general web server framework. Files in com.putable.siteriter.example can be copied and modified and tailored as you see fit -- although do note that much of the code they contain can be used AS IS! ((S.1.2)) There are three main classes in the com.putable.siteriter.server framework: - Server: A concrete class responsible for accepting web browser connections from the network. - AbstractConnection: An abstract class handling everything to do with a single web browser connection, except actually generating the response. (ExampleConnection.java is a concrete class that extends this.) - ConnectionFactory: An interface describing how to make new AbstractConnections. (ExampleConnection.java contains an implementation of this.) ((S.1.3)) Events in the server processing ((S.1.3.1)) When a Server is constructed, it is passed a reference to (an implementation of) a ConnectionFactory, which is stores for later use. (The Server will usually also be provided with a 'port number', which it also stores. If not, it will try to use port 80, the standard http port. However, that will usually fail unless the program is run with privileges. Supply a port number larger than 1000 to avoid that.) ((S.1.3.2)) Later, when Server.run() is called, the server begins listening on the specified port (if possible). ((S.1.3.2.1)) The Server sits in a loop, listening to the network, waiting for a web browser to make contact. ((S.1.3.2.2) When a contact is made, the Server calls its stored (implementation of a) ConnectionFactory to build a (concrete class that extends) AbstractConnection. ((S.1.3.2.3)) Then the Server starts a new Thread, which calls AbstractConnection.run() to handle the details of the connection. (See (S.1.4) for details.) Meanwhile, the Server returns to (S.1.3.2.1). ((S.1.4)) Events in connection processing ((S.1.4.1)) Via its ConnectionFactory, the Server builds a new instance of AbstractConnection for every web request it receives. (In the example server, the ExampleConnectionFactory builds instances of ExampleConnection.) ((S.1.4.2)) The processing performed by an AbstractConnection begins when its run() method is called. Through some private helper methods, the AbstractConnection performs a few key steps, in order: ((S.1.4.2.1)) First, it builds a Writer to be used later to send the response back to the requesting web browser. ((S.1.4.2.2)) It determines what URL is being requested, and then reads (and discards) any other 'http headers'. ((S.1.4.2.3)) It logs information about the request, if configured. ((S.1.4.2.4)) Finally, it calls its abstract 'respond(String)' method to produce and output the response and complete the web connection processing. ---------- ((S.2)) Understand the example server ((S.2.1)) The example server is in package com.putable.siteriter.example. There are four main classes in the package: - ExampleServer: This class contains the main() method. You run Exampleserver to start the server - ExampleSDLParserImpl: This is a stub implementation of an SDLParser. In a real SiteRiter, you would replace this with your own SDLParser implementation. - ExampleConnection: This class extends AbstractConnection and performs the guts of connection processing. A real SiteRiter can use this class virtually unchanged (unless an implementor wants to make 'extra credit' improvements.) - ExampleConnectionFactory: This tiny implementation of ConnectionFactory simply builds instances of ExampleConnections, and can be used unchanged in a real SiteRiter. ---------- ((S.3)) Incorporate your SDLParser ((S.3.1)) These are some sample steps about how to incorporate your SDLParser into the web server framework. Your Mileage May Vary. ((S.3.2)) First, ensure the example server is working. Try running ExampleServer, which will try to listen to the network on port 8000. ((S.3.2.1)) Get SiteRiterFull.jar from the project page. That jar file is configured to be runnable as an application. Assuming you have a vaguely recent Java installed properly, you should be able to observe an interaction something like this: $ java -jar SiteRiterFull.jar Message: Listening on port 8000 ((S.3.2.1.1)) If you instead get something like this: $ java -jar SiteRiterFull.jar Exception in thread "main" com.putable.siteriter.server.ServerException: Can't start on 8000 at com.putable.siteriter.server.Server.run(Server.java:51) at com.putable.siteriter.example.ExampleServer.loadAndRun(ExampleServer.java:53) at com.putable.siteriter.example.ExampleServer.main(ExampleServer.java:77) $ then something has gone wrong and need to be debugged. Typically the problem is there is something else already using port 8000 on your machine -- perhaps another instance of the ExampleServer, for example, run by you or by someone else. ((S.3.2.2)) Once you get the 'Message: Listening on port 8000' message, use a web browser on the same machine and try visiting 'http://localhost:8000/foo', or 'http://127.0.0.1:8000/bar' or similar URLs. ((S.3.2.2.1)) The resulting web pages should contain either 'Hello' or 'Goodbye' and nothing else. That's the lame-o maximo com.putable.siteriter.example.ExampleSDLParserImpl.java at work. ((S.3.2.3)) Stop the web server, via ^C if you ran in from the command line, or via the 'red box' in the Eclipse console or Debug window. ((S.3.3)) Refactor (a copy) of package com.putable.siteriter.example to follow the deliverable requirements. ((S.3.4)) Replace ExampleSDLParser.java with your implementation. Ensure the ExampleServer ctor is building your SDLParser implementation. ((S.3.5)) Modify the ExampleServer main method to accept a file path as a command line argument, and arrange for that file to be loaded into your SDLParser implementation as an SDL Rules File. ((S.3.5)) Run the (renamed by you) ExampleServer app, just as in (S.3.2), passing the path name of a legal Rule File on the command line (or in the 'Run -> Run Configurations.. -> YourFooServer -> Arguments -> Program Arguments' box in Eclipse). Now see your own SiteRiter pages displayed in your web browser. ((S.3.6)) Before finishing, demonstrate your refactoring fu by also changing the class names to some more appropriate names not involving 'Example'. ((S.3.7)) Note there are three 'FIXME' tags scattered through the Example Server implementation. _All_ conforming SiteRiter implementations must deal with _all three_ of those FIXME's. ---------- ((S.4)) Optional components ((S.4.1)) Scattered through the Example Server code are several 'TODO' markers (not to be confused with 'FIXME' markers). A SiteRiter implementation that implements ALL such TODO's will be eligible for up to 5% extra credit. ---------- ((S.5)) Document version ((S.5.1)) This is version 1.0, released Sun Sep 15 01:50:14 2013.