Bruce Eckel’s Thinking in Java | Contents | Prev | Next |
Now
let’s consider creating an application to run on the Web, which will show
Java in all its glory. Part of this application will be a Java program running
on the Web server, and the other part will be an applet
that’s downloaded to the browser. The applet collects information from
the user and sends it back to the application running on the Web server. The
task of the program will be simple: the applet will ask for the email address
of the user, and after verifying that this address is reasonably legitimate (it
doesn’t contain spaces, and it does contain an ‘@’ symbol)
the applet will send the email address to the Web server. The application
running on the server will capture the data and check a data file in which all
of the email addresses are kept. If that address is already in the file, it
will send back a message to that effect, which is displayed by the applet. If
the address isn’t in the file, it is placed in the list and the applet is
informed that the address was added successfully.
let’s consider creating an application to run on the Web, which will show
Java in all its glory. Part of this application will be a Java program running
on the Web server, and the other part will be an applet
that’s downloaded to the browser. The applet collects information from
the user and sends it back to the application running on the Web server. The
task of the program will be simple: the applet will ask for the email address
of the user, and after verifying that this address is reasonably legitimate (it
doesn’t contain spaces, and it does contain an ‘@’ symbol)
the applet will send the email address to the Web server. The application
running on the server will capture the data and check a data file in which all
of the email addresses are kept. If that address is already in the file, it
will send back a message to that effect, which is displayed by the applet. If
the address isn’t in the file, it is placed in the list and the applet is
informed that the address was added successfully.
Traditionally,
the way to handle such a problem is to create an HTML
page with a text field and a “submit” button. The user can type
whatever he or she wants into the text field, and it will be submitted to the
server without question. As it submits the data, the Web page also tells the
server what to do with the data by mentioning the Common
Gateway Interface (CGI) program that the server should run after receiving this
data. This CGI program is typically written in either Perl or C (and sometimes
C++, if the server supports it), and it must handle everything. First it looks
at the data and decides whether it’s in the correct format. If not, the
CGI program must create an HTML page to describe the problem; this page is
handed to the server, which sends it back to the user. The user must then back
up a page and try again. If the data is correct, the CGI program opens the data
file and either adds the email address to the file or discovers that the
address is already in the file. In both cases it must format an appropriate
HTML page for the server to return to the user.
the way to handle such a problem is to create an HTML
page with a text field and a “submit” button. The user can type
whatever he or she wants into the text field, and it will be submitted to the
server without question. As it submits the data, the Web page also tells the
server what to do with the data by mentioning the Common
Gateway Interface (CGI) program that the server should run after receiving this
data. This CGI program is typically written in either Perl or C (and sometimes
C++, if the server supports it), and it must handle everything. First it looks
at the data and decides whether it’s in the correct format. If not, the
CGI program must create an HTML page to describe the problem; this page is
handed to the server, which sends it back to the user. The user must then back
up a page and try again. If the data is correct, the CGI program opens the data
file and either adds the email address to the file or discovers that the
address is already in the file. In both cases it must format an appropriate
HTML page for the server to return to the user.
As
Java programmers, this seems like an awkward way for us to solve the problem,
and naturally, we’d like to do the whole thing in Java. First,
we’ll use a Java applet to take care of data validation at the client
site, without all that tedious Web traffic and page formatting. Then
let’s skip the Perl CGI script in favor of a Java application running on
the server. In fact, let’s skip the Web server altogether and simply make
our own network connection from the applet to the Java application on the server!
Java programmers, this seems like an awkward way for us to solve the problem,
and naturally, we’d like to do the whole thing in Java. First,
we’ll use a Java applet to take care of data validation at the client
site, without all that tedious Web traffic and page formatting. Then
let’s skip the Perl CGI script in favor of a Java application running on
the server. In fact, let’s skip the Web server altogether and simply make
our own network connection from the applet to the Java application on the server!
As
you’ll see, there are a number of issues that make this a more
complicated problem than it seems. It would be ideal to write the applet using
Java 1.1
but that’s hardly practical. At this writing, the number of users running
Java 1.1-enabled browsers is small, and although such browsers are now commonly
available, you’ll probably need to take into account that a significant
number of users will be slow to upgrade. So to be on the safe side, the applet
will be programmed using only Java 1.0
code. With this in mind, there will be no JAR files to combine
.class
files in the applet, so the applet should be designed to create as few
.class
files as possible to minimize download time.
you’ll see, there are a number of issues that make this a more
complicated problem than it seems. It would be ideal to write the applet using
Java 1.1
but that’s hardly practical. At this writing, the number of users running
Java 1.1-enabled browsers is small, and although such browsers are now commonly
available, you’ll probably need to take into account that a significant
number of users will be slow to upgrade. So to be on the safe side, the applet
will be programmed using only Java 1.0
code. With this in mind, there will be no JAR files to combine
.class
files in the applet, so the applet should be designed to create as few
.class
files as possible to minimize download time.
Well,
it turns out the Web server (the one available to me when I wrote the example)
does
have Java in it, but only Java 1.0!
So the server application must also be written using Java 1.0.
it turns out the Web server (the one available to me when I wrote the example)
does
have Java in it, but only Java 1.0!
So the server application must also be written using Java 1.0.
The
server application
Now
consider the server application, which will be called
NameCollector.
What happens if more than one user at a time tries to submit their email
addresses? If
NameCollector
uses TCP/IP sockets, then it must use the multithreading approach shown earlier
to handle more than one client at a time. But all of these threads will try to
write to a single file where all the email addresses will be kept. This would
require a locking mechanism to make sure that more than one thread
doesn’t access the file at once. A semaphore will do the trick, but
perhaps there’s a simpler way.
consider the server application, which will be called
NameCollector.
What happens if more than one user at a time tries to submit their email
addresses? If
NameCollector
uses TCP/IP sockets, then it must use the multithreading approach shown earlier
to handle more than one client at a time. But all of these threads will try to
write to a single file where all the email addresses will be kept. This would
require a locking mechanism to make sure that more than one thread
doesn’t access the file at once. A semaphore will do the trick, but
perhaps there’s a simpler way.
If
we use datagrams instead, multithreading is unnecessary. A single datagram
socket will listen for incoming datagrams, and when one appears the program
will process the message and send the reply as a datagram back to whomever sent
the request. If the datagram gets lost, then the user will notice that no reply
comes and can then re-submit the request.
we use datagrams instead, multithreading is unnecessary. A single datagram
socket will listen for incoming datagrams, and when one appears the program
will process the message and send the reply as a datagram back to whomever sent
the request. If the datagram gets lost, then the user will notice that no reply
comes and can then re-submit the request.
When
the server application receives a datagram and unpacks it, it must extract the
email address and check the file to see if that address is there already (and
if it isn’t, add it). And now we run into another problem. It turns out
that Java 1.0 doesn’t quite have the horsepower to easily manipulate the
file containing the email addresses (Java 1.1
does). However, the problem can be solved in C quite readily, and this will
provide an excuse to show you the easiest way to connect
a non-Java program to a Java program. A Runtime
object for a program has a method called exec( )
that will start up a separate program on the machine and return a Process
object. You can get an OutputStream
that connects to standard input for this separate program and an InputStream
that connects to standard output. All you need to do is write a program using
any language that takes its input from standard input and writes the output to
standard output. This is a convenient trick when you run into a problem that
can’t be solved easily or quickly enough in Java (or when you have legacy
code you don’t want to rewrite). You can also use Java’s
native
methods
(see Appendix A) but those are much more involved.
the server application receives a datagram and unpacks it, it must extract the
email address and check the file to see if that address is there already (and
if it isn’t, add it). And now we run into another problem. It turns out
that Java 1.0 doesn’t quite have the horsepower to easily manipulate the
file containing the email addresses (Java 1.1
does). However, the problem can be solved in C quite readily, and this will
provide an excuse to show you the easiest way to connect
a non-Java program to a Java program. A Runtime
object for a program has a method called exec( )
that will start up a separate program on the machine and return a Process
object. You can get an OutputStream
that connects to standard input for this separate program and an InputStream
that connects to standard output. All you need to do is write a program using
any language that takes its input from standard input and writes the output to
standard output. This is a convenient trick when you run into a problem that
can’t be solved easily or quickly enough in Java (or when you have legacy
code you don’t want to rewrite). You can also use Java’s
native
methods
(see Appendix A) but those are much more involved.
The
job of this non-Java application (written in C because Java wasn’t
appropriate for CGI programming; if nothing else, the startup time is
prohibitive) is to manage the list of email addresses. Standard input will
accept an email address and the program will look up the name in the list to
see if it’s already there. If not, it will add it and report success, but
if the name is already there then it will report that. Don’t worry if you
don’t completely understand what the following code means; it’s
just one example of how you can write a program in another language and use it
from Java. The particular programming language doesn’t really matter as
long as it can read from standard input and write to standard output.
job of this non-Java application (written in C because Java wasn’t
appropriate for CGI programming; if nothing else, the startup time is
prohibitive) is to manage the list of email addresses. Standard input will
accept an email address and the program will look up the name in the list to
see if it’s already there. If not, it will add it and report success, but
if the name is already there then it will report that. Don’t worry if you
don’t completely understand what the following code means; it’s
just one example of how you can write a program in another language and use it
from Java. The particular programming language doesn’t really matter as
long as it can read from standard input and write to standard output.
//: Listmgr.c // Used by NameCollector.java to manage // the email list file on the server #include <stdio.h> #include <stdlib.h> #include <string.h> #define BSIZE 250 int alreadyInList(FILE* list, char* name) { char lbuf[BSIZE]; // Go to the beginning of the list: fseek(list, 0, SEEK_SET); // Read each line in the list: while(fgets(lbuf, BSIZE, list)) { // Strip off the newline: char * newline = strchr(lbuf, 'n'); if(newline != 0) *newline = '