![]() |
![]() Fall Semester 2002 |
1. Customizing your servlet entry point.
Here's a simple way of avoiding .html
point-of-entry files:
2. Understanding theimport javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class Chat extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.getWriter().println( "<html><head><title>WebChat</title></head><body bgcolor=white>" + "<form method=POST action=/examples/servlet/Chat>Type your name here: " + "<input type=text name=namefield size=10> <p> then push <input " + " type=submit value=Proceed> (or hit Enter) </form></body></html>" ); } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.getWriter().println( "<html><body bgcolor=white><h1>Hello, <font color=blue>" + req.getParameter("namefield") + "</font>!</h1>" + " <applet code=ChatApplet " + "codebase=\"http://burrowww.cs.indiana.edu:21xx/chat\"\n" + " width=400 height=400> \n" + " <param name=user value=\"" + req.getParameter("namefield") + "\"> \n" + " </applet>" + " </body></html>" ); } }
HttpMessage
class. Let's do some experiments.
Go under your chat
directory and create a lecture13
directory.
Let's make sure we can write, compile, and run Java programs here first.
If this doesn't work for you ask for help.burrowww.cs.indiana.edu% emacs A.java burrowww.cs.indiana.edu% cat A.java public class A { public static void main(String[] args) { System.out.println("Hello, this is A. "); B b = new B(); b.greetings(); } } burrowww.cs.indiana.edu% emacs B.java burrowww.cs.indiana.edu% cat B.java public class B { void greetings() { System.out.println("Hello, I am an object of type B."); } } burrowww.cs.indiana.edu% javac A.java burrowww.cs.indiana.edu% java A Hello, this is A. Hello, I am an object of type B. burrowww.cs.indiana.edu%
One thing that you may want to change would be to add the current directory to your CLASSPATH.
I changed my line in ~/.cshrc
as follows:
You will, of course, note the dot-colon, in front.setenv CLASSPATH .:$TOMCAT_HOME/lib/servlet.jar
I also sourced my ~/.cshrc
(or log out and log back in).
Once we know this works let's move on to experiments.
java.net.URL
A Uniform Resource Locator (URL) is a string that describes how to locate a resource on the Internet. In general a URL consists of the following components:
(Highlight the URL with your mouse to render it with no colors).http://jupiter.cs.indiana.edu:12345/notice.html#READMEFIRST
The java.net.URL
represents URLs and provides methods to construct and obtain components
of the URL (its protocol, host name, port number, etc.) In addition, it provides methods that, after a
URL has been created, uses the URL to retrieve the resource identified by the URL. It also supports
lower-level methods such as opening a connection or input stream to the server that is managing the
resource identified by the URL.
Here's documentation about it.
Now let's create a server side resource.
Go to your cgi-bin
and create a resource.
Then test it. Now, just like we did in the HTTP experiments before, we try to access the resource from the command line. But we write a Java program to do that for us:burrowww.cs.indiana.edu% emacs javaOne burrowww.cs.indiana.edu% cat javaOne #!/usr/bin/perl print "Content-type: text/html\n\nHello, and how are you doing?\n"; burrowww.cs.indiana.edu%
The first line in color is the part we already understand.burrowww.cs.indiana.edu% emacs Test1.java burrowww.cs.indiana.edu% cat Test1.java import java.net.*; import java.io.*; public class Test1 { public static void main(String[] args) { try { URL servlet = new URL("http://burrowww.cs.indiana.edu:20006/cgi-bin/javaOne"); URLConnection con = servlet.openConnection(); con.setUseCaches(false); InputStream in = con.getInputStream(); BufferedInputStream buf = new BufferedInputStream(in); DataInputStream data = new DataInputStream(buf); System.out.println(data.readLine()); } catch (Exception e) { // ignore for the moment... } } } burrowww.cs.indiana.edu%
Let's explain the remaining part.
openConnection()
opens a connection to the location identified by this
URL.
The object returned is of type java.net.URLConnection
so we need to look that one up too.
Here's documentation about it.
Lines 2 and 3 in color will open the connection and set it up.
Once the connection is open the resource has been tapped into, and it replies.
So it sends back information and we need to get ready to read it.
The remaining lines are basic Java I/O that set up an input line so we can read String
s.
The whole thing works.
Let's look at something more complicated.
Let's do GET and POST.
First, let's set up a more powerful resource.
Then test it a few times:burrowww.cs.indiana.edu% emacs javaTwo burrowww.cs.indiana.edu% cat javaTwo #!/usr/bin/perl if ($ENV{REQUEST_METHOD} eq 'GET') { $in = $ENV{QUERY_STRING}; } else { read(STDIN, $in, $ENV{CONTENT_LENGTH}); } print "Content-type: text/html\n\n"; @in = split(/&/, $in); foreach $e (@in) { ($a, $b) = split(/=/, $e); print "param $a has value $b "; } print "\n"; burrowww.cs.indiana.edu%
You can also test it with POST but that takes longer, with a form, though you should do it.
Now let's access the resource through a program.
The color is supposed to highlight the various levels of new in the code.burrowww.cs.indiana.edu% emacs Test2.java burrowww.cs.indiana.edu% cat Test2.java import java.net.*; import java.io.*; import java.util.*; public class Test2 { public static void main(String[] args) { try { URL servlet = new URL("http://burrowww.cs.indiana.edu:20xxx/cgi-bin/javaTwo"); Properties props = new Properties(); props.put("a", "b"); props.put("c", "d"); String queryString = "?" + toEncodedString(props); System.out.println(queryString); System.out.println(servlet.toExternalForm()); servlet = new URL(servlet.toExternalForm() + queryString); URLConnection con = servlet.openConnection(); con.setUseCaches(false); InputStream in = con.getInputStream(); BufferedInputStream buf = new BufferedInputStream(in); DataInputStream data = new DataInputStream(buf); System.out.println(data.readLine()); } catch (Exception e) { // ignore for the moment... } } private static String toEncodedString(Properties args) { StringBuffer buf = new StringBuffer(); Enumeration names = args.propertyNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); String value = args.getProperty(name); buf.append(URLEncoder.encode(name) + "=" + URLEncoder.encode(value)); if (names.hasMoreElements()) buf.append("&"); } return buf.toString(); } } burrowww.cs.indiana.edu% javac Test2.java Note: Test2.java uses or overrides a deprecated API. Recompile with "-deprecation" for details. 1 warning burrowww.cs.indiana.edu% java Test2 ?c=d&a=b http://burrowww.cs.indiana.edu:20006/cgi-bin/javaTwo param c has value d param a has value b burrowww.cs.indiana.edu%
This should open the door for you to understand HttpMessage
completely.
3. Threads.
We start with a simple Echo
program that has no threads.
This illustrates a bit of terminal I/O and a loop.burrowww.cs.indiana.edu%% emacs Test3.java burrowww.cs.indiana.edu%% cat Test3.java import java.io.*; public class Test3 { public static void main(String[] args) { System.out.println("Hello, this is Echo!"); DataInputStream data = new DataInputStream(new BufferedInputStream(System.in)); try { String line = data.readLine(); while (! (line.equals("bye"))) { System.out.println(":-) You typed: " + line); line = data.readLine(); } System.out.println("Good-bye!"); } catch (Exception e) { } } } burrowww.cs.indiana.edu%% javac Test3.java Note: Test3.java uses or overrides a deprecated API. Recompile with "-deprecation" for details. 1 warning burrowww.cs.indiana.edu%% java Test3 Hello, this is Echo! How are you doing, Echo? :-) You typed: How are you doing, Echo? And so did you. :-) You typed: And so did you. I know that... :-) You typed: I know that... Well, I have to go now. :-) You typed: Well, I have to go now. You don't seem to care... :-) You typed: You don't seem to care... bye Good-bye! burrowww.cs.indiana.edu%%
Let's make the program do two things at the same time.
We need to explain this, but first let's see it in action.burrowww.cs.indiana.edu% emacs Test4.java burrowww.cs.indiana.edu% cat Test4.java import java.io.*; public class Test4 { public static void main(String[] args) { System.out.println("Hello, this is Echo!"); Thread thread = new Thread(new WhiteRabbit()); thread.start(); DataInputStream data = new DataInputStream(new BufferedInputStream(System.in)); try { String line = data.readLine(); while (! (line.equals("bye"))) { System.out.println(":-) You typed: " + line); line = data.readLine(); } System.out.println("Good-bye!"); } catch (Exception e) { } } } class WhiteRabbit implements Runnable { public void run() { while (true) { System.out.println(" " + new java.util.Date()); System.out.println(" " + "Oh, my goodness, I'm late, I'm late!..."); try { Thread.sleep(5000); } catch (Exception e) { } } } } burrowww.cs.indiana.edu% javac Test4.java Note: Test4.java uses or overrides a deprecated API. Recompile with "-deprecation" for details. 1 warning burrowww.cs.indiana.edu%
You need to run this and experience it to fully comprehend it.burrowww.cs.indiana.edu% java Test4 Hello, this is Echo! Tue Feb 20 14:09:50 EST 2001 Oh, my goodness, I'm late, I'm late!... Here I am :-) You typed: Here I am Tue Feb 20 14:09:55 EST 2001 Oh, my goodness, I'm late, I'm late!... Oh, and the rabbit is here Tue Feb 20 14:10:00 EST 2001 Oh, my goodness, I'm late, I'm late!... . :-) You typed: Oh, and the rabbit is here. I think I can typ Tue Feb 20 14:10:05 EST 2001 Oh, my goodness, I'm late, I'm late!... e at the same time the rabbit is compl Tue Feb 20 14:10:10 EST 2001 Oh, my goodness, I'm late, I'm late!... aining about time. :-) You typed: I think I can type at the same time the rabbit is complaining about time. Nifty Tue Feb 20 14:10:15 EST 2001 Oh, my goodness, I'm late, I'm late!... ! :-) You typed: Nifty! Parallel proce Tue Feb 20 14:10:20 EST 2001 Oh, my goodness, I'm late, I'm late!... ssing! :-) You typed: Parallel processing! By Tue Feb 20 14:10:25 EST 2001 Oh, my goodness, I'm late, I'm late!... e! :-) You typed: Bye! burrowww.cs.indiana.edu%
Meanwhile we can tighten the code up a bit.
Running this would produce something similar.burrowww.cs.indiana.edu% emacs Test5.java burrowww.cs.indiana.edu% pwd /nfs/paca/home/user1/dgerman/apache/jakarta-tomcat-3.2.1/webapps/ROOT/chat/lecture13 burrowww.cs.indiana.edu% cat Test5.java import java.io.*; public class Test5 implements Runnable { public static void main(String[] args) { System.out.println("Hello, this is Echo!"); Thread thread = new Thread(new Test5()); thread.start(); DataInputStream data = new DataInputStream(new BufferedInputStream(System.in)); try { String line = data.readLine(); while (! (line.equals("bye"))) { System.out.println(":-) You typed: " + line); line = data.readLine(); } System.out.println("Good-bye!"); } catch (Exception e) { } } public void run() { while (true) { System.out.println(" " + new java.util.Date()); System.out.println(" " + "Oh, my goodness, I'm late, I'm late!..."); try { Thread.sleep(5000); } catch (Exception e) { } } } } burrowww.cs.indiana.edu% javac Test5.java Note: Test5.java uses or overrides a deprecated API. Recompile with "-deprecation" for details. 1 warning
Your applet does the same thing. (Except, being an object, it
has the run
method already).
It needs to constantly retrieve information from the server, and it does that in an infinite loop.
If for some reason it times out it sends the request again.
Should it be sent some message that was posted, it shows it to the user, then sends a GET again.
If we were not to run this in parallel the user would never be able to type anything in the tex field.
Try implementing this without the thread, and you will see the white rabbit will not let you do anything.
4. How Observer
s and Observable
s work.
import java.util.*; class Test { public static void main(String[] args) { Monitor m1 = new Monitor("One "); Monitor m2 = new Monitor("Two "); Monitor m3 = new Monitor("Three"); Performer p = new Performer(); p.addObserver(m1); p.addObserver(m2); p.addObserver(m3); p.doSomething(); } } class Monitor implements Observer { String name; public Monitor(String name) { this.name = name; } public void update (Observable o, Object arg) { System.out.println( name + ": " + ((Integer)arg).intValue() ); } } class Performer extends Observable { int n = 0; public void doSomething() { n += 1; setChanged(); notifyObservers(new Integer(n)); clearChanged(); } }