First, let's start by digesting some web-technology buzzwords:
Ajax, Angular, Apache, ASP, AWS, clientserver, Cookies, Certificates, ColdFusion, CGI, CSS, Forms, Get, HTML, HTTP, Java, Javascript, JQuery, JSon, JSP, NAB, Perl, Post, TCP/IP, SOAP, SSI, SSL, XML.
Exercise 1: Which one of these is not a web technology buzzword?
What is HTML?
Four ways of building an HTML website:
Exercise 2:
What is CGI?
Exercise 3:
How does a webserver call a CGI program? Three possible ways:
<html> <head> <title> Hello World </title> </head> <body> Hello World! (plain HTML text). <% Dim str str = "Hello World (from Visual Basic string)" Response.write (str) %> </body> </html>
Before this is sent out by the webserver, the code is executed, which writes "in place".
The HTML actually received by the requesting browser is:
<html> <head> <title> Hello World </title> </head> <body> Hello World! (plain HTML text). Hello World (from Visual Basic string) </body> </html>
Exercise 4: Find a webpage that uses Javascript or Visual Basic.
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class HelloWorld extends HttpServlet { public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Set the content type of the response. resp.setContentType ("text/html"); // Create a PrintWriter to write the response. PrintWriter out = new PrintWriter (resp.getOutputStream()); // The first part of the response. out.println ("<html>"); out.println ("<head><title> Test </title></head>"); out.println ("<body>"); // The greeting. out.println ("Yo, Hello World!"); // Last part. out.println ("</body>"); out.println ("</html>"); out.flush(); // Screen I/O System.out.println ("Inside servlet ... servlet complete"); } public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet (req, resp); } }
https://www.ask.com/web?q=houseHere, the text field contains house.
Now let's write Java - a simple servlet that writes "Hello World!" to
the browser: (source file)
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class HelloWorld extends HttpServlet { public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Set the content type of the response. resp.setContentType ("text/html"); // Extract the PrintWriter to write the response. PrintWriter out = resp.getWriter (); // The first part of the response. out.println ("<html>"); out.println ("<head><title> Test </title></head>"); out.println ("<body>"); // The greeting. out.println ("Yo, Hello World!"); // Last part. out.println ("</body>"); out.println ("</html>"); out.flush(); // Screen I/O System.out.println ("Inside servlet ... servlet complete"); } public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Default, for now. doGet (req, resp); } }
Note:
// Set the content type of the response. resp.setContentType ("text/html");
out.println ("<html>"); out.println ("<head><title> Test </title></head>");
out.flush();
System.out.println ("Inside servlet ... servlet complete");
Exercise 5: Modify the HelloWorld example to print something else and test it using these instructions.
Next, let us create an HTML Form, and have a servlet pick up the
Form data entered by the user.
First, an HTML page with a form:
<html> <head><title>Test Post</title> <body> <form action="http://unix.seas.gwu.edu:40013/servlets/TestForm" method="post"> Enter a string: <input type="text" name="param1"> And then press "Go": <input type="submit" value="Go"> </form> </body> </html>
Next, the TestForm.java servlet: (source)
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; public class TestForm extends HttpServlet { public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Set the content type of the response. resp.setContentType ("text/html"); // Extract the PrintWriter to write the response. PrintWriter out = resp.getWriter (); // The first part of the response. out.println ("<html>"); out.println ("<head><title> Test </title></head>"); out.println ("<body>"); // Now get the parameters and output them back. out.println ("Request parameters: "); Enumeration e = req.getParameterNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); String value = req.getParameter (name); if (value != null) out.println ("<li> name=[" + name + "] value=[" + value + "]"); else out.println ("<li> name=[" + name + "] did not have a value"); } // Last part. out.println ("</body>"); out.println ("</html>"); out.flush (); } public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost (req, resp); } }
Note:
Enumeration e = req.getParameterNames();
Enter a string: <input type="text" name="param1">
String whatTheUserTyped = req.getParameter ("param1");
Exercise 6: Compile and test the above servlet using your assigned port number with these instructions.
Exercise 7: PART I: Change the HTML page by adding the following inside the "body"
<input type="hidden" name="hidden1" value="hiddenvalue1">Use the same servlet as above (TestForm.java) as the form action. You should see the hidden parameter.
Important observations about HTTP and webservers:
Using hidden parameters to maintain user information in webpages:
For example, suppose this is the login page:
After logging in, the user sees:
Upon clicking on "Fortune", say, the result is something like:
Note:
Let us build this application step by step:
http://unix.seas.gwu.edu:40013/servlets/examples/TestLogin
<html> <head><title>Test Login</title> <body> <form action="http://unix.seas.gwu.edu:40013/servlets/examples/TestLogin" method="post"> Enter username: <input type="text" name="username"> <input type="submit" value="login"> <input type="hidden" name="page" value="loginpage"> </form> </body> </html>
public class TestLogin extends HttpServlet { static final boolean debug = false; public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Set the content type of the response. resp.setContentType ("text/html"); // Extract the PrintWriter to write the response. PrintWriter out = resp.getWriter (); // The first part of the response. out.println ("<html>"); out.println ("<head><title> Test Login</title></head>"); out.println ("<body>"); // Write out the action, since that's common to all. out.println ("<form action=\"http://unix.seas.gwu.edu:40013/servlets/examples/TestLogin\" method=\"post\">"); // Get the page info from hidden fields: String whichPage = req.getParameter ("page"); String userName = req.getParameter ("username"); if (debug) { // During debugging, it helps to print out the parameters in the response. printParams (out, req); } // Determine action based on which page fired the request. if (whichPage.equalsIgnoreCase ("loginpage")) { handleLoginPage (out, userName); } else if (whichPage.equalsIgnoreCase ("menupage")) { handleMenuPage (out, userName, req); } else { handleError (out); } // End the form. out.println ("</form>"); // Last part. out.println ("</body>"); out.println ("</html>"); out.flush(); // Screen I/O System.out.println ("Inside servlet ... servlet complete"); } public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // We need to implement POST because the forms are written as such. doGet (req, resp); } void handleLoginPage (PrintWriter out, String userName) { out.println ("Hello " + userName + "! Choose from these options: "); // The two buttons. out.println ("<input type=\"submit\" name=\"Time\" value=\"Time\">"); out.println ("<input type=\"submit\" name=\"Fortune\" value=\"Fortune\">"); // Write out the extracted username: out.println ("<input type=\"hidden\" name=\"username\" value=\"" + userName + "\">"); out.println ("<input type=\"hidden\" name=\"page\" value=\"menupage\">"); } void handleMenuPage (PrintWriter out, String userName, HttpServletRequest req) { // Check which button was pressed: String timeButtonPressed = req.getParameter ("Time"); out.println (userName + ", "); if (timeButtonPressed != null) { // Time event. Date d = new Date (); out.println ("the date/time is: " + d + "."); } else { // Fortune event. String fortune = ""; if ( (int)userName.charAt(0) % 2 == 0) { fortune = "go out, meet people. Tomorrow is going to be great for you."; } else { fortune = "stay at home. Tomorrow is going to be a lousy day for you."; } out.println (fortune); } } void handleError (PrintWriter out) { out.println ("Enter username: <input type=\"text\" name=\"username\">"); out.println ("<input type=\"submit\" value=\"login\">"); out.println ("<input type=\"hidden\" name=\"page\" value=\"loginpage\">"); } // For debugging: void printParams (PrintWriter out, HttpServletRequest req) { out.println ("<p><hr><p> Request parameters: <ul>"); Enumeration e = req.getParameterNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); String value = req.getParameter (name); if (value != null) out.println ("<li> name=[" + name + "] value=[" + value + "]"); else out.println ("<li> name=[" + name + "] did not have a value"); } out.println ("</ul><hr>"); } }
<html> <head><title> Test Login</title></head> <body> <form action="http://unix.seas.gwu.edu:40013/servlets/examples/TestLogin" method="post"> Hello Morpheus! Choose from these options: <input type="submit" name="Time" value="Time"> <input type="submit" name="Fortune" value="Fortune"> <input type="hidden" name="username" value="Morpheus"> <input type="hidden" name="page" value="menupage"> </form> </body> </html>
We will use this example to illustrate session tracking:
Note that we've added a "back" button to go back to the menu page.
public class PageCount extends HttpServlet { static final boolean debug = false; public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... // Extract page count: String pageCountStr = req.getParameter ("pagecount"); int pageCount = -1; try { pageCount = Integer.parseInt (pageCountStr.trim()); } catch (NumberFormatException e) { // Handle exception ... } pageCount ++; // Write out hidden field: out.println ("<input type=\"hidden\" name=\"pagecount\" value=\"" + pageCount + "\">"); // Write out page count message: out.println ("<br> <font color=\"#FF0000\">You have made " + pageCount + " page requests</font>"); // ... } public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // We need to implement POST because the forms are written as such. doGet (req, resp); } // ... (as before) ... }Note:
<html> <head><title>Test Login</title> <body> <form action="http://unix.seas.gwu.edu:40013/servlets/examples/PageCount" method="post"> Enter username: <input type="text" name="username"> <input type="submit" value="login"> <input type="hidden" name="page" value="loginpage"> <input type="hidden" name="pagecount" value="0"> </form> </body> </html>
Exercise 8: Run the above servlet. Make sure you use your assigned port number. Use two browsers to simultaneously login with the same username. Alternate between them. What do you notice?
About session tracking:
Let's modify the servlet to handle "page counts" using server-side session tracking:
public class SessionPageCount extends HttpServlet { // Store session info (page count) by username in hashtable. Hashtable sessionTable = new Hashtable (); public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... // Check if session exists: Integer pageCount = (Integer) sessionTable.get (userName); if (pageCount == null) { // Create a new page count. pageCount = new Integer (0); } pageCount = new Integer (1 + pageCount.intValue()); sessionTable.put (userName, pageCount); out.println ("<br> <font color=\"#FF0000\">You have made " + pageCount + " page requests</font>"); // We don't really need this, but we'll use it for confirmation: out.println ("<input type=\"hidden\" name=\"pagecount\" value=\"" + pageCount + "\">"); // ... } public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // We need to implement POST because the forms are written as such. doGet (req, resp); } // ... }
Some improvements:
// An instance of this for each user: class SessionInfo { int pageCount; // We'll now put the counter here. long startTime; // For timeout's. } public class SessionPageCount2 extends HttpServlet { // Store session info (page count) by username in hashtable. Hashtable sessionTable = new Hashtable (); public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... // Get the page info from hidden fields: String whichPage = req.getParameter ("page"); String userName = req.getParameter ("username"); // First extract session info. SessionInfo session = (SessionInfo) sessionTable.get (userName); // Check if inactive session. if (session != null) { long minutesSince = (System.currentTimeMillis() - session.startTime) / (1000*60); // See if user has been inactive for more than 1 minute. if (minutesSince >= 1) { out.println ("Session timed out. Please login again."); out.println ("</form></body></html>"); out.flush (); return; } } else { // Make session. session = new SessionInfo (); session.pageCount = 0; session.startTime = System.currentTimeMillis (); } // Active session. Continue ... // Determine action based on which page fired the request. if (whichPage.equalsIgnoreCase ("loginpage")) { handleLoginPage (out, userName); } else if (whichPage.equalsIgnoreCase ("menupage")) { handleMenuPage (out, userName, req); } else if (whichPage.equalsIgnoreCase ("featurepage")) { // Back button on Time or Fortune page handleLoginPage (out, userName); } else { handleError (out); } // Page count. session.pageCount ++; // Put updated page count back in table, and write out to page: sessionTable.put (userName, session); out.println ("<br> <font color=\"#FF0000\">You have made " + session.pageCount + " page requests</font>"); // We don't really need this, but we'll use it for confirmation: out.println ("<input type=\"hidden\" name=\"pagecount\" value=\"" + session.pageCount + "\">"); // ... } public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // We need to implement POST because the forms are written as such. doGet (req, resp); } // ... }
What is persistence?
As an example, let us make the "page counts" persistent for users:
// Use an instance of this class for each user. class SessionInfo { int pageCount; // Number of pages accessed. long startTime; // Time at which session started in milliseconds. } public class SessionPageCount3 extends HttpServlet { // Store session info (page count) by username in hashtable. Hashtable sessionTable = new Hashtable (); public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... String userName = req.getParameter ("username"); // First extract session info. SessionInfo session = (SessionInfo) sessionTable.get (userName); // Check if inactive session. if (session != null) { long minutesSince = (System.currentTimeMillis() - session.startTime) / (1000*60); if (minutesSince >= 1) { out.println ("Session timed out. Please login again."); out.println ("</form></body></html>"); out.flush (); return; } } else { // Make session. session = new SessionInfo (); // Get current page count, if it exists, from file. File f = new File (userName); if (! f.exists()) { // Create one and write zero. f.createNewFile (); PrintWriter pw = new PrintWriter (new FileWriter(f)); pw.println (0); pw.close (); } // Read from file. LineNumberReader lnr = new LineNumberReader (new FileReader (f)); String pageCountStr = lnr.readLine (); try { session.pageCount = Integer.parseInt (pageCountStr.trim()); } catch (NumberFormatException e) { session.pageCount = 0; } lnr.close (); // Record the start of the session. session.startTime = System.currentTimeMillis (); } // Active session. Continue ... // ... (some code not shown) ... // Page count stuff. session.pageCount ++; sessionTable.put (userName, session); out.println ("<br> <font color=\"#FF0000\">You have made " + session.pageCount + " page requests</font> in your lifetime"); // Write current count to file: File outFile = new File (userName); outFile.delete (); PrintWriter pw = new PrintWriter (new FileWriter (userName)); pw.println (session.pageCount); pw.close (); // ... } // ... }
The topic of session tracking is complex:
Consider this example:
public class VisitorCount extends HttpServlet { // Count the total number of users: int numLogins = 0; public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ... as before ... } // ... void handleLoginPage (PrintWriter out, String userName) { // Login count. // Deliberately slow it down for users that start with "M". if (userName.startsWith ("M")) { try { Thread.sleep (5000); } catch (InterruptedException e) { // Handle exception ... } } numLogins ++; out.println ("Number of people who logged in before you: " + numLogins + ""); out.println ("Hello " + userName + "! Choose from these options: "); // ... } }
Exercise 9:
Run the above servlet. Make sure you use your assigned port number.
Use two browsers to simultaneously login with two different
usernames, the first one should start with "M" and the second
one should NOT. Login first with the "M" name, and immediately
afterwards, login with the second.
Explain the result.