Spring Semester 2003


Lecture Notes Twenty-Three: Four building blocks of your web chat application.

1. Customizing your servlet entry point.

Here's a simple way of avoiding .html point-of-entry files:

import 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>"

     ); 

  } 
       

}
2. Understanding the 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.

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% 
If this doesn't work for you ask for help.

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:

setenv CLASSPATH   .:$TOMCAT_HOME/lib/servlet.jar
You will, of course, note the dot-colon, in front.

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:

  1. protocol
  2. host name
  3. port number
  4. file name
  5. reference
Here's a complete example:
http://jupiter.cs.indiana.edu:12345/notice.html#READMEFIRST
(Highlight the URL with your mouse to render it with no colors).

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.

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% 
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 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% 
The first line in color is the part we already understand.

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 Strings.

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.

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% 
Then test it a few times:

  1. javaTwo?a=b&c=d
  2. javaTwo?x=y
  3. javaTwo
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.

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% 
The color is supposed to highlight the various levels of new in the code.

This should open the door for you to understand HttpMessage completely.

3. Threads.

We start with a simple Echo program that has no threads.

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%% 
This illustrates a bit of terminal I/O and a loop.

Let's make the program do two things at the same time.

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% 
We need to explain this, but first let's see it in action.

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% 
You need to run this and experience it to fully comprehend it.

Meanwhile we can tighten the code up a bit.

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
Running this would produce something similar.

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 Observers and Observables 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(); 

    }

} 


Last updated: Apr 8, 2003 by Adrian German for A348/A548