Chapter 16. Servlets and JSP

Servlets and JSP

When Java was originally released in 1995, much of the “buzz” was about applets. People were captivated by browsers that could run executable code on a client browsing a page. Even today, no other technology can do this in a secure way. But applets soon became a civilian casualty of the “Browser Wars” as Microsoft battled Netscape. Over time, developers shifted their focus from applets to running Java on the server-side. Java on web servers is now one of the “sweet spots” of Java technology.

This chapter describes the two key Java technologies that are used in server-side Java: servlets and JSP. The first of these, servlets, is a way for a browser to cause a program to run on the server. The server calculates something, probably accesses a database, and sends HTML output back to the browser on the client. In a nutshell, that is the architecture of all web-based e-commerce systems, from Amazon.com to E-Trade.com to the Zdnet.com online store. These are applications where the end-user interface is provided by a web browser, and the backend logic runs on a server.

Servlets look set to become the new way for a browser to get a web page from a program (not a file) on the server. The old way used an interface called CGI, and your scripts would be written in Perl or Visual Basic or some other language. With servlets, your code is written in Java. There is a size/complexity tradeoff here: small scripts (less than a couple of pages) can be written at the drop of a hat and are well suited to Perl or PHP. There are a great many web tools used today, as shown in Table 16-1.

Table 16-1. Microsoft Web Tools and Corresponding Competitive Products

Microsoft Product

Multi-platform Alternative

Windows 2000

Linux, Solaris

Visual Basic, VC++, C#

Java, C, C++, Perl

IIS (Internet Information Server)

Apache Web server

ASP

JSP, PHP

SQLServer

many - PostgreSQL, mySQL, Oracle, DB2, etc.

ODBC

JDBC

ActiveX

Java Beans

MTS (Microsoft Transaction Server)

EJB (Enterprise Java Beans)

Office

StarOffice (freely downloadable from Sun)

The larger and more complicated your code, the more you will benefit from using a Java servlet. If you need to access a database, you can use Java’s JDBC library. If you need threading or network libraries, Java has them. If your code needs to run with permissions-based access control, Java supports this. Instead of a mixture of different tools and libraries, you can write the whole thing in one consistent language. Perhaps the biggest advantage is that servlets free you from being tied to one kind of hardware or one software vendor. Because of Java’s portability, you can easily move to more capable hardware as your processing needs increase. Your servlet code can be run by any servlet server. It’s easy to add new capacity and leave the software unchanged.

The second technology we will visit in this chapter is called “Java Server Pages,” modelled after the ColdFusion technology invented by the Allaire company of Boston, Massachusetts. Allaire now makes a Java servlet and JSP execution environment known as JRun that can be plugged into any web server. Allaire’s ColdFusion product was copied by Microsoft and given the name ASP— “Active Server Pages.” ColdFusion, ASP, and JSP are all ways of mixing (“embedding”) programming statements, scripts, and components in web pages on the server side. When the server gets a request for the page, it executes the programming statements, and sends to the browser the fixed HTML plus the HTML dynamically generated by executing the embedded code. If you are familiar with ASP, you can pick up JSP in a few minutes. To put it another way, JSP looks a lot like fragments of Java code, but embedded in an HTML page.

An ordinary page of HTML is static. Each time the server sends it out, it sends the exact same bytes. The only way it changes is if someone updates the HTML file with an editor. But many kinds of information change dynamically: stock prices, the weather, seats available on a flight, amount of inventory on hand, account balance, contents of an online shopping cart, and so on. Servlets and JSP are a great way to get this dynamic information into a web page. The pages that the user sees are calculated by general purpose programs that can reference and update databases as part of serving the request.

For small programs, JSP is simpler than a servlet. Servlets require the programmer to write Java code to output all the HTML (the fixed part and the dynamically varying part) along with all the headers that a web server adds automatically. JSP allows a programmer to write down the fixed HTML as HTML. You write Java code fragments that create the dynamically varying HTML, and you don’t need to bother with generating the HTML headers. Because you write the fixed HTML directly and literally, JSP is (in theory) a good way to keep separate the dynamic and static parts of your web page.

In practice, it takes some discipline to prevent your JSP programs from becoming hard to maintain. JSP doesn’t have any extra capabilities compared with servlets, and indeed JSP is usually implemented in terms of servlets.

Both servlets and JSP are big topics, covered at book length elsewhere. In this chapter we map out the territory and get the first examples of each working. The goals are to show you how to write basic servlets, and to cover the key points of server-side Java. This chapter can be worked through in an afternoon, and gives you enough information to interview for an entry-level job on an e-commerce project. After you master the basics here, you can go on to get deeper knowledge from Robert Burdick, et al., Professional JSP, 2d ed., 2001, Wrox Press Ltd., Birmingham, UK.

Why Use Servlets?

Server-side web programming is well established on the web. It lets you build systems with a client part that can run in a browser on any computer, with any operating system, at any time, from anywhere in the world. The HTTP protocol provides a framework for communicating with a server where all the real work is done. The server-side code may do load-balancing to move incoming requests to the system best equipped to handle them. The server code can access/update your database and process any data using the most up-to-date information. It does this in a safe way. The client cannot call server routines directly. It can only send over HTTP requests saying what it wants, so opportunities to subvert the server are more restricted than when everything runs on one physical system. You still need to code defensively as people may try to access your page in a way which could make the server spend all its time trying to service their request.

Client/server programming was popular even before the web went mainstream, and bringing the two together was a natural marriage. CGI—the “Common Gateway Interface”—was the first attempt to get dynamic content into web pages. CGI got the job done, but it had security and performance problems. CGI implementations often start up an entire new process to run a script. It doesn’t have to be done that way, but in practice it usually is. Servlets are loaded into memory once, and stay around ready to handle all future requests. So there can be a big performance advantage to using servlets. It also means that servlets can choose to hold system resources (such as a database connection) between requests. Since opening and closing a database connection is a lengthy operation, this is another win for servlets.

Servlets make it easier to separate the business logic used to generate results from the HTML that displays those results. JSP takes that one step further. Separation of logic from presentation has benefits. It’s an enabler for the use of component software (Java Beans, described in a later chapter). Component software lets a system designer deploy the same code to handle a transaction whatever the origin is: web-based, online transaction, or batch processing. We’re getting into Enterprise-level software issues here, but it delivers consistency and code reuse.

Servlet technology replaces the family of server plugins such as the Netscape API, CGI, or the Microsoft ISAPI, none of which are standardized or multiplatform like the JavaServer API is. Servlets today are the most popular choice for building portable interactive web applications. Add-on software to run servlets are available for Apache Web Server, iPlanet Web Server, Microsoft IIS, and others. Servlet containers can also be integrated with web-enabled application servers such as BEA WebLogic Application Server, IBM WebSphere, iPlanet Application Server, and others.

People are currently driving the technology even further with a technique called “ASP” or Application Service Provision. Don’t confuse Application Service Providers with “Active Server Pages.” ASP is all about extending the benefits of client/server systems to all kinds of application software. The idea is that instead of buying software and installing it locally on your PC, you rent access to the software at the ASP site. Instead of running a spreadsheet locally, the program executes on a server at the ASP site and sends you the equivalent data for display on your screen. Ideally, you won’t see much difference between using an ASP and running your programs locally, but the total cost of ownership is lower. The ASP takes care of all the system administration tasks, data backup, etc., and your PC is just used as a communications device to reach the ASP. You don’t even need an expensive heavyweight PC. You can use any number of cheap or portable or wireless devices to connect to the ASP. Servlets are ideal for use in an ASP, providing a simple way to connect clients to server processing.

The ASP model has some compelling advantages, but it is still a work-in-progress. If you think this sounds like a rerun of X-Windows or Citrix technology, you are right, but the web aspect adds a significant new dimension (the ability to run from any computer, any OS, anywhere). Nobody yet knows when or even whether Application Service Providers can deliver on the early promise, but there are a number of smart people working hard to make it happen.

Releases and Versions

By agreement with Sun Microsystems, the reference implementation for servlets and JSP is maintained by the Apache Software Foundation. The Apache web server is an open source project, and by far the most widely-used web server in the world. You can look up more information about the Apache Software Foundation at www.apache.org. Apache uses the project name “Jakarta” for their Java-specific work.

The servlet library is part of the Enterprise Edition of Java, but must be downloaded separately if you are using the Standard Edition. The servlet design underwent some rapid evolution at first with a number of versions and releases, but it has settled down now. Tables 16-2 and 16-3 spell out the details, so you can relate everything to other versions you may have heard about. At the time of this writing (2001), the most up-to-date version of the servlet API is version 2.3, and that is used in this chapter. Check the Apache website listed below for any later version and download and use that in preference. This technology is mature enough that there won’t be any drastic changes in future revisions.

The main product of Apache’s Java-based Jakarta project is a servlet-and-JSP container known as Tomcat. Tomcat can run standalone as a servlet server, or it can be added on to most other web servers to process any Java requests. Tomcat was based on an earlier program known as “JServ” (in case you hear that term used somewhere). A “servlet container” is the new name for what older books refer to as a “servlet engine.” It simply means the software framework within which servlets execute. We will use Tomcat as the container throughout this chapter. Tomcat is used because it is the reference implementation for servlets, and because it is available for free download and use. It is written in Java, so you can get it running on any computer with an up-to-date JVM.

Table 16-2. Server/Servlet Versions

Servlet Container

Version Number

Compatible with This Version of the Java API

JServ

ver 1.1.3

Servlet 2.0, JSP 1.0

Tomcat

ver 3.2.1

Servlet 2.2, JSP 1.1

Tomcat

ver 4.0

Servlet 2.3, JSP 1.2

The servlet and JSP specifications have changed as people got practical experience with the technology. JSP 1.0 allowed the use of Java beans. JSP 1.1 added support for custom JSP tags. The Servlet specification 2.3 introduced filters that allow you to do preprocessing on an http request before the servlet gets it. There are additional products that combine Java and web servers at the Apache website, and it is worth visiting jakarta.apache.org to review these for yourself.

Table 16-3 lists a glossary covering all the new terms, so you can refresh your memory or refer back to it as needed.

Table 16-3. Glossary

Term

Definition

Apache

The Apache Software Foundation is a volunteer organization which has produced the most popular web server in the world, and made it available for free download. Their website is www.apache.org

Ant

A utility that accompanies Tomcat, used when Tomcat has to compile some servlet code automatically. Ant is a Java-based build utility that works out the correct dependency order in which to compile each file. It works cross-platform, unlike non-Java based tools.

Catalina

The servlet container (engine) part of Tomcat version 4.

CGI

The Common Gateway Interface was the first server-side scripting technology. It specifies how the server should execute a script when a particular web page is referenced. CGI scripts can be written in different languages, and Perl is a popular choice.

cookie

A cookie is a few bytes of information that the server asks the browser to store on the client and return on demand. This token can be used to keep track of what the client has already seen, whether they have already given a password, and other information about the current session with the server.

HTTP

Hyper-Text Transfer Protocol. The vocabulary and standard way in which a browser and a server take turn to exchange information with each other.

Jakarta

The part of the Apache Software Foundation that focuses on Java server technology, and maintains the Java part of the Apache website. It has the Tomcat software as its centerpiece.

Jasper

The JSP server part of Tomcat.

JServ

An early implementation of the Java Servlet API from the Apache Software Foundation. It has been replaced by the Tomcat project.

JSP

Java Server Pages is a technology that allows programmers to mix together programming statements and HTML in web pages. The statements are executed and replaced with their output when the page is referenced. This server-side scripting approach was pioneered by Allaire's ColdFusion product on Windows.

Servlet

A servlet is any Java class that implements the javax.servlet.Servlet interface. It is executable by any compliant servlet container. The most common form of servlet is an HTTP servlet that responds to browser requests.

Tomcat

An open source servlet-and-JSP engine, written in Java, from the Jakarta project of Apache. Tomcat also includes a rudimentary web server making it easy to use for development (you don't need to set up a separate web server).

post

A request made by a browser that will upload user-entered data to the server and get back a new page. The contents of the new page will be calculated on the fly by the server.

get

Similar to post, except the browser or server may return a cached version of the page rather than calculating it anew.

Installing the Tomcat Software

This section describes how to download and install the Tomcat servlet web server software. There is a “servlet runner” utility available from Sun that works like the appletviewer. It provides just enough context to execute your specialized web code. We could use the servlet runner, but it does not support JSP. Further, it is good experience to try installing and configuring a real web server.

To get started on your first servlet, go to the “servlets” directory on the CD that comes with this book. You can get there easily by browsing the index.html file at the top level on the CD, then just click on the servlets link. Create a top level directory on your disk called “tomcat” and copy the file “jakarta-tomcat-4.0-b3.zip” from the CD into that disk directory. If there is a later version at the Apache website jakarta.apache.org, use that instead. Unpack the file. You can use WinZip, or the Java “jar” utility with these commands

cd c:	omcat 
jar -xf jakarta-tomcat-4.0-b3.zip 

The “-b3” in the pathname indicates we are using the beta-3 release of Tomcat version 4.0 here. Definitely switch to the FCS (First Customer Shipment, i.e., the real release) version when it is available at the Apache website. Don’t deploy beta software in production systems. The jar command shown above will create a directory tree under your “server” directory, containing the Tomcat software. Give the top of this newly created tree a simpler name in the “8.3” form that works best with Windows. If you fail to do this renaming, the beta version of the Tomcat software may have problems finding files later. The renaming is:

cd c:	omcat 
move jakarta-tomcat-4.0-b3  4beta3 

Now set or update these shell variables so that Tomcat can find the Java compiler, and the Java compiler can find the servlet jar file. On a Windows system, the autoexec.bat file is one convenient place to do it. Or, you can create a new batch file just for setting up Tomcat. The commands to set them on Windows look like:

set TOMCAT_HOME=c:	omcat4beta3 
set JAVA_HOME=c:jdk1.3 
set CLASSPATH=c:	omcat4beta3commonlibservlet.jar;. 

Installing the Tomcat Software

Note: The commands shown are for Windows. Make adjustments if you are using Unix, Linux, etc. That servlet.jar file has been moving around to different directories in recent beta releases, so check where it actually is located and use that pathname. That allows your programs to compile against the servlet libraries.

Be careful to get this right. You may already have a JAVAHOME variable; Tomcat needs a JAVA_HOME (with the underbar). You may already have a CLASSPATH variable, in which case you want to add to it, not replace it. If you set these variables in a batch file, make sure you execute it.

Running the Example Servlets

The next step is to try running Tomcat on one of the example servlets that accompany it. First shut down any other web servers that you have running on your system, so they don’t interfere with this example. Then go to the main Tomcat directory with this command:

cd c:	omcat4beta3 

Tomcat will run as a stand-alone web server, which is very convenient for development. It can also be configured to run as an adjunct to most other web servers and to handle the servlet/JSP requests. That’s useful for deployment, and we won’t get into it here. Issue the command to start Tomcat as a stand-alone server:

binstartup 

After a second or two, a new window will appear saying that it is “Starting service Tomcat-Standalone.” This means your system is now running a servlet capable web server. Tomcat serves web pages to requests that come through port 8080, so start a browser and give it the URL http://localhost:8080.

You can use the name “localhost” or the special IP address “127.0.0.1” that means “this system.” Or if your computer has a DNS name, you can equally use that in the URL. If you have installed and set up everything correctly, your browser will display a page as shown in Figure 16-1.

Setting up Tomcat

Figure 16-1. Setting up Tomcat

If you don’t get this page served to you, something in your configuration is not set up correctly, so start again from the beginning (and check the website for this book www.afu.com, in case there is an update to the errata sheet).

Click on the “Servlet Examples” link displayed in your browser, and you will bring up a new page that has the top half-a-dozen examples of servlet-related things you want to do, along with a skeleton of the source code that implements them. This demonstrates that you can successfully run the example servlets on your system. After you have read the basic example here, you can return to this URL and find sample code for the following:

  • getting the http headers of this request

  • reading the parameters passed with an HTTP “get” request

  • setting and retrieving a cookie

  • creating and examining session information

We cover the first two of these in this chapter. Cookies and sessions should be studied with the online Tomcat examples. We’ll now cover the material that you need to understand how servlets work. All this information might look somewhat involved, but writing servlets and JSP is easily done. My next door neighbor is a hardware engineer. Hardware engineers normally have terrible trouble with software, but she was able to teach herself how to program servlets. And you can learn it too, just as easily.

Review servlet and JSP Javadoc API web pages.

One of the links displayed in the default Tomcat home page is the “API docs for Servlet 2.3 and JSP 1.2 Packages.

Setting up Tomcat

It’s a good idea to keep a browser window open on that page, and review each class as it is mentioned in the rest of this chapter.

Ports and Protocols

Computers on an Internet network are uniquely identified by something called an “IP address.” IP addresses are stored as a group of either 32 bits (IP classic) or 128 bits (IP version 6), but binary numbers are hard for people to deal with. So the network protocols allow you to give a computer a hostname, and to collect a group of related hosts into hierarchical domains. There might be several subdomains within a domain, which is written in the form with dots separating the subdomains like this: “ engineering.sun.com.” Domain Name Servers (DNS) contain tables that translate between IP addresses and names within a domain. If you know a computer’s IP address or DNS name, you can send anything to it: mail, ftp commands, http requests, and so on.

When you send something to a computer, the IP address specifies which computer it must go to. You also need to specify which application should receive the data. This is done with a “port number.” A port in this context is a software service implemented by the operating system, not a hardware concept like the serial port or parallel port. Hardware or software, they all do the same job: provide a channel for data to enter or leave the computer. A few common port numbers and their associated applications are shown in Table 16-4.

Table 16-4. Example Port Numbers and Their Standard Applications

Port Number

Standard Application

Description

80

HTTP connections

The Hypertext Transport Protocol used between browsers and servers

8080

Servlet requests in Tomcat

The port used by the Java servlet server from the Apache group

20 and 21

FTP connections

The File Transfer Protocol used to move files between systems

23

telnet

Supports remote login from one computer to another

25

smtp

The Simple Mail Transfer Protocol

79

finger

Displays information about all the users logged into a computer

119

NNTP

The Network News Transfer Protocol used to send Usenet articles

The way you read or write data to a port is with a socket. Sockets were a Unix innovation, but are so useful that every OS now has a software library that supports use of sockets. Programmers can create a socket that sends data to a particular port on a particular host, or one that waits for data to come in on a particular port on the localhost computer. In Java, you use input and output streams on sockets just as though you were processing a file. These libraries are found in the java.net package. The class java.net.ServerSocket lets your program accept incoming data by spawning off a thread with a socket that you can read from. The class java.net.Socket lets you send data to another computer, or read data that is coming into the local host. The Java libraries for sockets are much, much better designed and easier to use than the C libraries.

Servlets can be used to service any request that is made via a socket, not just web page requests. Servlets can be written to respond to any protocol, not just HTTP. You can write a servlet that sits on port 21, talks File Transfer Protocol, and takes care of FTP requests. A servlet that talks something other than HTTP is called a “generic servlet” and it will extend the class javax.servlet.GenericServlet. The vast majority of servlets are used to serve web requests. These are known as “http servlets,” and they extend the class javax.servlet.http.HttpServlet. We will go into the details soon.

A web browser is just a program that sends requests to the HTTP port on a server and displays the data that the server sends back. A basic web browser that doesn’t also try to be a newsreader/mail client/HTML editor/instant message service/etc., can be written in a hundred lines of code (assuming you have a GUI component that renders HTML, which Java does). A web server is just a program that waits for incoming requests on the HTTP port, and maps those into sending the contents of local files back to the requestor. One basic web server was written by the very talented programmer Jef Poskanzer in only 200 lines of code! Jef makes it available on his website at www.acme.com. Part of developing into a better programmer is reading code from others, so I encourage you to look at it. It’s on the CD that comes with this book, along with other interesting material. We also write the world’s smallest web server in Chapter 17.

The computer science term “protocol” means “an agreement on how to talk to each other.” Browsers and servers talk to each other using HTTP, HyperText Transfer Protocol. The browser starts the conversation, and then each end takes its turn to say something. It goes back and forth over the net like a game of tennis. An http request from a browser is replied to with a response from the server. A commercial web server is multithreaded and typically dealing with many clients (browsers) at any moment, but is either reading a request or sending the response to each. The key concept of servlets is that when you browse a particular page, it causes the servlet to run. The servlet does whatever processing you coded, and then writes some HTML to represent the answer. The web server sends that newly-generated HTML back to the browser for display. Just as with a regular HTML page, a servlet can be invoked many times. A servlet can cope with several concurrent requests, and it may call another servlet or forward the original request to it for processing.

All this somewhat involved material is just to give you the background information. Writing servlets and JSP is actually relatively simple.

The HTML to Invoke a Servlet

This section describes the HTML that will be displayed on the client and cause a servlet to run on the server. The most common way for a browser to invoke a servlet is via an HTML form in a web page. An HTML form starts with the <FORM> tag and ends with the </FORM> tag. If the web server allows you to see that directory, you can also invoke a servlet by browsing the URL that points to the location of the servlet. There is no rule against it, but it is not common for an applet to invoke a servlet. There’s an exercise at the end of the chapter inviting you to write a servlet that can send over and accept back a high score file for a game. Servlets don’t have to serve HTML. They can send files of any kind, or anything that the client knows how to process. But most servlets are invoked by an HTML form.

People typically place a number of input <INPUT> tags inside their <FORM>. An HTML input tag puts some kind of simple GUI component on the browser screen, and scoops up any data the user enters. An input tag has a TYPE attribute, a NAME attribute, and often other attributes like SIZE too. (Reminder: attributes are the name=value pairs that live inside tags to provide extra information). The TYPE attribute says what kind of a GUI control this is: a checkbox, radio button, textfield, etc. The input tag as a whole defines a GUI component that allows the user to enter data on the web page. One of the input tags will have a TYPE attribute of “submit.” Pressing that causes the entire form, with all the data the user typed in, to be sent over to the server.

Figure 16-2 shows an example of an HTML form, some INPUT tags, and the web page they generate. You should create a web page with the HTML shown here, and confirm that you can browse it, enter data, and press the submit button.

HTML example form.

Figure 16-2. HTML example form.

There are about 10 different GUI input types, but the most often used are text, radio, checkbox, and submit. For a complete list of all the input types and other attributes, do a web search on “HTML, form, guide.” To make it all line up nicely on the screen, everything inside a form is often put in an HTML table.

Now we come to the question of how and where the browser sends the data from the form. The form tag will always have two attributes (omitted in Figure 16-2, for simplicity) that specify how and where the form data goes. These attributes are called “action” and “method.” There are also additional possible attributes, to give the whole form a name, and to say how the data should be encoded before it is sent to the server. The default values are fine for these. An example of a complete form tag would be

<form  action="/servlet/petform"   method="post"> 

The action attribute gives the URL for the script or servlet that will process the data. It doesn’t need to be an URL on the same server that served the form. It doesn’t need to be a full URL. It can be a partial URL that is based on the page already being served. The method attribute specifies the HTTP approach that the browser should use when sending over the data. The two possibilities are “GET” and “POST.” In HTML, attributes may be enclosed in quotation marks. In XML (which we’ll meet in Chapter 27) attributes must be enclosed in quotation marks. So you may as well get into the habit now.

Reams of pages have been written about using POST versus GET in an HTML form. Originally, GET was used to ask for a file from the server, and POST was used to send data to the server. Today, either can be used to transmit form data to a server-side application. The differences boil down to this:

  • POST passes the form data to the server as a series of fields in the body of the HTTP request. GET sends the data appended to the URL as a query string, like this

    http://www.yahoo.com/stocks.htm?somename=somevalue 

    Since the GET data is actually added onto the end of the URL string, the user can bookmark it, and submit the same data later by going to the bookmark. This is why search engines often use GET. As it is part of the URL, the user can also see it and play around with it, which you may not want.

  • GET is limited to a small amount of text data that can be appended to the address (less than 255 characters). POST handles an arbitrary amount of text and binary data and does not show up as part of the address URL. Many web servers log URLs. If you don’t want your logs to contain sensitive user data (like account names and passwords), you must POST it.

  • GET responses can be cached anywhere along the way—by your browser, by your company’s proxy server, or by the web server. With POST, the page request is required to go through all the caching layers to the server and extract the data again. So POST should be used when the servlet is counting accesses, or making a charge to see the page, or controlling who can see the page.

You will typically “post” form data to a servlet. If you are sending data to a web servlet by some other means, you need to send the data according to the HTTP protocol. The HTTP protocol defines the contents of HTTP requests and responses. The user does not see all the text that makes up an HTTP request sent to the browser. All they see is the URL in the location field at the top of the browser. But the browser also assembles several other text strings, specifying extra administrative details that will help the server answer. These are known as “header fields.” All of this together forms the “HTTP request,” as shown in Figure 16-3.

An HTTP request and response.

Figure 16-3. An HTTP request and response.

The browser sends requests, and the server sends back responses.

The header information, together with the HTML body forms the “HTTP response.” The browser deals with what the headers tell it to do, and displays the rest of the response on the screen for the user to read. Some of the HTTP headers defined in RFC2616 are shown in Table 16-5.

Table 16-5. HTTP Headers

Header

Purpose

Content-Encoding

This header tells the browser that the content has been encoded for transmission, so the browser knows it has to change it back before displaying it. The content might be zip compressed, for example.

Content-Language

This header specifies the language in which the content is written. The value is one of the language codes laid down by RFC 1766, e.g., “ en ” (English), “ en-us ” (North American dialect), etc.

Expires

This header specifies the time when the content is considered out of date, and hence should no longer be cached.

Connection

This header can have a value of “ keep-alive ” when persistent connections are being used, or “ close ” when they are not.

We will only use forms to send data in this chapter, avoiding the rarer techniques of applets or browsing the servlet URL directly. When you use a form, your browser automatically provides any necessary headers for the HTTP request. If you want to get more details on headers that can appear in an HTTP request or response, the best resource is RFC 2616 (the Internet standard for HTTP) available at www.rfc-editor.org. You will need this information if you craft an HTTP request or response by hand in a program.

A Servlet and Its Request/response

In this section we will present the skeleton of a servlet, and also look at the objects that it uses to learn about a request and send a response. We will start by restating that a servlet is really just like any other Java program, but one that (like an applet) has a special context in which to run. In the case of an applet, the context is a web browser sandbox. In the case of a servlet, it runs inside a web server engine, termed the “container.”

You create your servlet by extending one of the javax.servlet classes, and overriding one or more of the methods in it with your own code. There is some configuration or conventions that tell the servlet container where your servlet is and what URL should invoke it. The servlet container will call your overriding methods when a certain URL is requested, and pass in parameters that encapsulate (have all the information about) those events. Again, this is very similar to the way applets work.

The skeleton of an http servlet looks like this:

public class MyServlet extends javax.servlet.http.HttpServlet {

    public void init() { ... } 
    public void doGet() { ... } 
    public void doPost() { ... } 
    public void destroy() { ... } 
} 

This code is simplified slightly by leaving off the method parameters and the exceptions they can throw. They are shown a couple of paragraphs later. The init() method is called only once when the class is first loaded. You would use this for one-time initialization, such as opening a connection to a database. The destroy() method is also called only once when the servlet is unloaded. This method is used to free any remaining resources or do final housekeeping on shutting down. If you don’t have any special startup or shutdown code, you don’t need to override these methods.

The doGet() or doPost() methods are the ones that do the work of the servlet. Obviously, doGet() is called when the HTML form used a “get” method, while doPost() is invoked by a form with a “post” method. There are other less important doSomething() methods, too, corresponding to the other things that an HTML form may do. For example, there are other methods that can be overridden for less common HTTP requests like DELETE. You can review these in the source file HttpServlet.java that is part of the servlet kit.

The doGet() and doPost() methods take the same parameters: an HttpServletRequest and an HttpServletResponse. Both of these are interfaces, and all these doSomething() methods will get passed objects that implement the interfaces. You call methods on the HttpServletRequest to find out what the browser is asking for exactly. There’s a method you call to get a PrintWriter from the HttpServletResponse, and you write your resulting plain text, HTML, image file, audio file, or Javascript using it. What you write gets sent back to the browser. It’s as simple as that.

The actual signature of the doPost routine in javax.servlet.http.HttpServlet is:

protected void doPost(javax.servlet.http.HttpServletRequest req, 
                     javax.servlet.http.HttpServletResponse resp) 
              throws javax.servlet.ServletException, java.io.IOException; 

The method doGet() has the same parameters and can throw the same exceptions. Note that the two routines are labelled as “protected,” meaning that they can only be called by routines in the same package or in a subclass. That makes sense. It is probably not meaningful for your servlet to be called other than to process an http request. If it is meaningful to invoke your doPost() routine otherwise, then your system design probably needs some refiltering, perhaps to split out a chunk of the common code into a Java bean.

Servlet Request

Part of a request and part of a response will be the HTTP headers and the parameters. Headers are the bookkeeping information supplied automatically by the browser or server, stating things like the locale and the version of HTTP in use. Parameters are provided by the user and passed in the query string or in the form data. A parameter name is whatever the html form designer called it. It is legal for parameter or headers to have several values, usually in a comma-separated list. You need to be alert to this possibility in your code.

Let’s take a look at the classes that implement response and request objects to see what information comes and goes. We’ll start with the java class that represents an HTTP request. Tomcat will create an object that implements this interface to hold all the data in the incoming request. Tomcat will then invoke your servlet, and pass the request object to it as an argument.

These methods are just the highlights of an HTTP servlet request object. There are about 20 getSomething() methods in HttpServletRequest, and another 20 in its parent, ServletRequest, allowing all information in the request to be retrieved.You will invoke these methods (shown in Table 16-6) on the javax.servlet.http.HttpServletRequest parameter, as shown in the example coming up.

Notice that some of these methods return Enumeration objects, rather than the newer Iterator object that was intended to replace Enumeration and was part of JDK 1.2. This is for backwards compatibility with existing servlet code.

Table 16-6. Key Methods of javax.servlet.http.HttpServletRequest

Method

Purpose

getHeader(String s)

Returns the first value of the header whose name you provide, or null if there isn't one of that name.

getHeaderNames()

Returns an Enumeration of all the header names in this request.

getHeaders (String s)

Returns an Enumeration of all the values of the header whose name you provide, or an empty Enumeration if there isn't one of that name. Some headers, such as Accept-Language, can be sent by clients as several headers each with a different value rather than sending the header as a comma-separated list.

getIntHeader (String s)

Used when you want to pull an integer out of the headers. String s is the name of the header. It will return the int value of the header, or throw a NumberFormatException, or return -1 if there is no header with this name.

getParameter (String s)

Returns the value of the parameter whose name you provide, or null if there isn't one.

getParameterValues (String s)

Works like getParameter(), but is used when the parameter can have several values, e.g., it may be a set of checkboxes or a multiselection list. It returns an array of String containing all the values.

getParameterNames()

Returns a java.util.Enumeration object containing all the parameter names in this request.

getServerName()

Returns the hostname of the server that received the request.

getCookies()

Returns an array of the cookies that came with this request. A cookie is a few bytes of data that the server sends to the browser and gets back in later requests, allowing the server to keep track of the client.

Response to a Servlet Request

Tomcat will also pass your servlet one of these response objects as an argument. The object has lots of methods that let you give values to its fields. You send back the actual data by writing to a print writer that you get from the response object. Table 16-7 shows the most frequently called methods of your response object, the HTTP servlet response.

Table 16-7. Key Methods of javax.servlet.http.HttpServletResponse

Method

Purpose

getWriter()

Returns a PrintWriter that will get written with the data part of the servlet response.

setHeader(String n, String v)

Adds a response header with the given name and value.

setDateHeader(String s, long d)

Adds a response header with the given name and time value.

setIntHeader(String s, int v)

Adds a response header with the given name and int value.

addCookie(Cookie c)

Adds the specified cookie to the response.

setStatus(int sc)

Set the status code for this response.

setContentType (String s)

Sets the response's MIME content type.

setContentLength (int size)

Sets the Content-Length header of the response.

You will invoke these methods on the javax.servlet.http.HttpServletResponse parameter, as shown in the example coming up. There are about 20 methods in HttpServletResponse and its parent class, ServletResponse, allowing just about any field to be set and returned to the browser. There are about 20 static final variables giving names to each of the status codes. You should review the Javadoc descriptions of these classes.

There are about a dozen HTTP headers, but you can ignore them unless you need the special effects that they cause. The content type is the only one you need to set. You can also look a few pages further on in this chapter where we write a JSP program to echo the headers received from the browser. That shows you some typical headers.

Writing Your Own Servlet

Here is the code for a servlet that can process the HTML form that we created in the previous section. We’re going to send a reply that suggests a suitable pet based on the weight and leg count the user submitted. Make sure that your CLASSPATH has the servlet.jar file in it, as shown in the section “Installing Tomcat.”

import javax.servlet.*; 
import javax.servlet.http.*; 
import java.io.*; 
import java.text.*; 
import java.util.*; 

public class PetServlet extends HttpServlet {

    private String recommendedPet(int weight, int legs) {
        if (legs ==0) return "a goldfish"; 
        if (legs ==4) {
           if (weight<20) return "a cat"; 
           if (weight<100) return "a dog"; 
        } 
        return "a house plant"; 
    } 

    public void doPost(HttpServletRequest req, 
                       HttpServletResponse resp ) 
        throws ServletException, IOException {

        // get the input field values 
        int petWeight = 0, petLegs = 0; 
        try {
          petWeight = Integer.parseInt(req.getParameter("weight")); 
          petLegs = Integer.parseInt(req.getParameter("legs")); 
        } catch (NumberFormatException nfe) {
          petWeight=petLegs=-1; // indicates that we got an invalid number 
        } 

        resp.setContentType("text/html"); 

        PrintWriter out = resp.getWriter(); 

        out.println(" <html> <body> <h1>Recommended Pet</h1> <p>"); 
        out.println("You want a " + petLegs + "-legged pet weighing " 
                   + petWeight + "lbs."); 

        String pet = recommendedPet(petWeight, petLegs); 
        out.println("<P> We recommend getting <b>" + pet ); 
        out.println("</b> <hr> </body> </html> "); 

        out.close(); 
    } 
} 

Note the line that says “ resp.setContentType("text/html").” It is putting some standard information in the HTML headers that are sent back to the browser. We have to provide the minimal set of headers for the HTTP response. If you are going to set any headers, make sure you do it before you start writing the content of the response. A common content type is “text/plain” for ordinary character files, and “text/html” for HTML files. It refers to the MIME encoding of the strings that follow. MIME encoding is a way of turning arbitrary binary files into ASCII and labelling what the data represents. MIME was developed so that binary files like JPEG images could be mailed around more easily, and it is equally useful for HTTP transactions. MIME is an abbreviation for “Multipurpose Internet Mail Exchange,” and is laid down in RFCs 1521 and 1522 if you want to look it up. In this example you don’t need to set any other headers.

There are two versions of HTTP: 1.0 and 1.1. If you use any contemporary browser you get support for 1.1, which is good, but a lot of people out there are not using modern browsers. Among other improvements, HTTP 1.1 allows clients to send more requests to the server on the same socket that it just used. That saves time if you’re getting some more content on the same web page, e.g., if you are displaying some HTML with image files. Normally, the client knows when it has got all the content because the server ends by breaking the socket connection. But if the server tells the client how many bytes are in the current response body, the client can count them as they arrive and will know when the server has sent everything and is ready for another request on this socket.

So it’s good practice to set a header giving the length of the content part of each response when you know it. You can do that by assembling all the content in a ByteArrayOutputStream before sending it. ByteArrayOutputStream grows automatically as needed. Write everything to a ByteArrayOutputStream. After you have written all the data, call the size() methodof the ByteArrayOutputStream to find out how much you wrote, and do a setContentLength(). Finish up by doing a response.getOutputStream() and passing that as an argument to the ByteArrayOutputStream’s writeTo() method. You don’t have to copy anything anywhere. The code fragment that follows illustrates this approach. Needless to say, you must have completely finished writing any headers before you start writing the content of the response.

Keeping Track of Content Length

ByteArrayOutputStream ba = null; 
    private void writeBytes(String s) throws IOException {
        byte buf[] = s.getBytes(); 
        ba.write(buf); 
    } 
    public void service(HttpServletRequest req, 
                       HttpServletResponse resp ) 
        throws ServletException, IOException {
        resp.setContentType("text/html"); 
        // How to calculate content length 
        ba = new ByteArrayOutputStream(); 
        writeBytes("<P> some text <HR> "); 
        resp.setContentLength(ba.size()); 
        OutputStream out = resp.getOutputStream(); 
        ba.writeTo(out); 
        out.close(); 
    } 
} 

Three further tips. First, always close the output stream when you are not going to write any more to it. Second, examine your exception handling, and try to express any problem in terms of an appropriate HTML status code if there is one. The HTML status codes are static int constants that can be found in interface javax.servlet.http.HttpServletResponse. Third, each servlet container has some way to log unexpected situations. Find out what that way is for your web server, and write log records as part of running each servlet.

Now compile and run this servlet. You can put this first example source file anywhere, but for simplicity and convenience I recommend that you put the source file and its class file in the same directory along with the examples that come with Tomcat. If you do this, no other configuration of Tomcat is needed. And Tomcat configuration is more difficult than it needs to be because of its confusing directory names and scarce tutorials. The pathnames you need to use and other information are shown in the Table 16-8. It’s very finicky! So double check that you have used the exact names shown here.

Apache and Tomcat are great web-serving engines: free, open source, widely-used. Their weakness is that the information needed to configure them is not very accessible. Every web server is going to have its own configuration rules, and some are easier than others. Make sure you have set the environment variables listed at the beginning of this chapter, then complete the example by compiling the source file in the directory specified below, setting up the HTML, starting the Tomcat server, and finally browsing the URL for this servlet. Set all the pathnames up according to the table below. This re-uses the existing Tomcat “examples” directory, and you don’t need to create or configure anything additional.

Table 16-8. Pathnames to Execute Your Servlet

Purpose

Value

Servlet source file

$TOMCAT_HOMEwebappsexamplesWEB-INFclassespetservlet.java

When compiling, your $CLASSPATH must include (the path may differ on non-Windows platforms).

$TOMCAT_HOMEinservlet.jar

Command to compile the servlet

javac petservlet.java

Form html file

$TOMCAT_HOMEwebappsexamplesservletspetform.html

HTML tag that invokes the servlet

<form action=/examples/servlet/petservletmethod=post>

browse this URL to run

http://127.0.0.1:8080/examples/servlets/petform.html

Note the last two entries in this table. The HTML tag has the singular “servlet,” and the URL has the plural “servlets.” This inconsistency is a bit of a “newbie hurdle” but it won’t exist for real servlets that you deploy. They will be placed in a different directory and will have a descriptor (entry in a file) that tells the container about them. We’ve avoided that here so there is less to do to get the example running.

On some Windows systems, using the name “localhost” in a URL will cause the computer to try to connect to the network to find a DNS server. It’s fine to let that proceed.

The petservlet produces a result in the browser as shown in Figure 16-4.

Result of the petservlet.

Figure 16-4. Result of the petservlet.

Servlet Operating Cycle and Threading

Servlets typically have the operating cycle, as shown in Figure 16-5.

Operating cycle of a servlet.

Figure 16-5. Operating cycle of a servlet.

The sequence of events in a servlet’s lifetime is:

  1. The servlet container starts up, and at some point constructs an instance of the servlet and calls its init() method. The init() method is only called once. Not once per request, not once per session, but once at the beginning of the servlet’s lifetime. The init() method is a good place to put code to open a database connection.

  2. Unlike, say, a GUI, there is no background thread always running code in the servlet. The servlet instance object just stays ready in memory, waiting for a request. This makes servlets very efficient. Eventually, a request comes to the web server, and the web server passes the request to the servlet container.

  3. The servlet container instantiates a new thread to process the request. Note that the container does not instantiate a new servlet object. The newly created thread representing the request calls the doPost() method (or whatever is appropriate for this request) of the existing instance of your servlet. The servlet can access a database, the filesystem, other servlets, etc. It creates the HTTP response which the container returns to the client. Thread-per-request makes servlets scalable and high performance.

  4. Repeat steps 2 and 3 for each request. Eventually the web server will be requested to shut down. At that point, the servlet’s destroy() method is called. Then it is a candidate for garbage collection and finalization. A servlet instance will also be destroyed if you have set things up so that newer versions of a servlet are loaded automatically.

Servlets typically run on multithreaded servers and instantiate a new thread for each incoming request. This is the usual way that servers process incoming requests on a socket—create a new thread for each request for service. The use of threads means that two requests might be executing in your servlet code at the same time. Your code will need to synchronize access to any resources that are shared. This will include resources like instance variables, database connections, and static data. If you don’t properly synchronize access to instance data, you will run into trouble with data race bugs.

Consider a servlet that accesses a database and puts data in an instance variable of the servlet. If two requests come in together and you are unlucky with scheduling, it could happen that request A gets its data out of the database, but it is overwritten in the instance variable with B’s data from the database before A can use it. Then the servlet returns B’s data to both A and B, confusing everyone. Chapter 11 on advanced thread topics explains synchronization in more detail.

There is an alternative to making your servlet thread-safe. You can declare that it implements javax.servlet.SingleThreadModel, like this:

public class petservlet extends HttpServlet 
                      implements javax.servlet.SingleThreadModel {

When you implement this interface, the servlet container queues up HTTP requests so that only one thread at a time is executing in your servlet. However, the container may create multiple instances of your single thread model servlet, so you still have to worry about synchronizing class (static) data. Normal servlets only have one instance per context per container (according to the 2.2 specification) but can have many threads in that one instance. Generally speaking, SingleThreadModel should be avoided as an unnecessary drag on performance, unless there are special reasons to use it. One reason would be when you know you will never have many concurrent requests. In this case, the simplest code will use the single thread model, making the database connection an unsynchronized instance variable.

There is not much more to servlets than this. The topics outside the scope of this chapter are cookies, setting a session, security, filtering, and redirecting the request to another servlet. All of these are covered at length in the Servlet version 2.3 Specification which can be downloaded from the Sun website. Although they call it a specification, and it’s more than 200 pages long, it’s easy to read and worth taking a look at. You can find it at java.sun.com/products/servlet/index.html.

A cookie is a morsel of tasty data that a server sends back to the clien and can retrieve on demand. It allows the server to retain some state information for each of its clients. The information is typically something like, “what pages has the user seen?” or “has this user given the password yet?” A session is a way for the server to identify a user across more than one page request. You would use a session to conduct an entire e-commerce transaction, with all the different pages for choosing goods, submitting credit card numbers, and so on. Cookies are often used to maintain session information. Readers who want to know more about these two matters can look at the examples in the sample code that comes with Tomcat. Start Tomcat running and then browse the URL //127.0.0.1:8080 to see these pages.

Java Server Pages

We will conclude this tour of server-side Java with a description of Java Server Pages (JSP), and an example JSP program. One way of understanding JSP is to say that JSP is ASP, without the restriction to Windows only. Another way of understanding it is to say that JSP programs are a variant on ordinary servlets, where some of the simple tasks are automated for you. In fact, the container implements JSPs by automatically translating them into the equivalent servlet which is then run in the usual way.

An ordinary unchanging web page contains HTML (plus Javascript perhaps). A servlet is a compiled Java program. A JSP program is a hybrid of these two. It lets you mix individual Java statements in with your HTML code. The Java code will be executed on the server when the page is browsed, and it will provide some dynamic content to the page. You might do some calculations, or put something in a loop. Your JSP Java code fragments are padded out to make a complete servlet. This servlet is automatically compiled for you by the JSP container when the page is browsed. As with servlets, JSP code is compiled once and loaded into memory on first use. A developer will typically browse all the JSP pages when deploying a system, so that there is no “first time through” time penalty of compilation for the users.

A large part of a servlet is “boilerplate,” meaning text that is the same in all servlets. The class declaration, the method signatures, and so on are needed to make sure your code compiles, but they are the same in every servlet. JSP eliminates all that standard context. It is provided for you automatically. This can dramatically shorten the amount of code you need to write, and also makes it simple enough for non-programmers to produce JSP.

JSP uses special tags to separate the Java from the HTML. The JSP opening tag is “<%” and the closing tag is “%>”. The opening tag “<%” might be followed by another character such as “!” or “@” or “=”to further specialize its meaning. A very brief example here will show you best. These lines in a JSP file:

<b> current time is: 
    <%=  new java.util.Date() %> 
</b> 

will produce a line of output like this when you browse the jsp page:

current time is: Mon Feb 19 18:37:23 PST 2001

Note that it may take 30 seconds or so to appear because the container has to compile your JSP file the first time you browse it. When you browse the same file a minute later without changing anything, the resulting page will show a different time, demonstrating that the JSP provides dynamic page content. Second and later references give results much more quickly as the container keeps the compiled class file for future use. If the automatic JSP compilation results in compiler error messages, these will be sent back to the client for display in the browser.

The piece that is new is the second line in the JSP file. It starts with the tag “<%=” which means “evaluate the Java expression that follows, convert it to String, and write it to the HTML output.” Other JSP tags have their own meaning, as shown in Table 16-9:

Table 16-9. JSP Tags and Meanings

Start of JSP Tag

Meaning of JSP Tag

<%

Everything up to the closing tag “%>” is java code (blocks, statements, declarations, etc.).

<%=

Evaluates the Java expression that follows, converts it to String, and writes it to the HTML output. Ends with “%>”.

<%!

This is a Java declaration which is inserted into the body of the servlet where it is available to all methods in the servlet.

<%@

This tag can be followed by one of several different strings, such as “method,” “import,” “implements,” “extends.” These are followed by a string that specifies the name for a Java method, package, interface, etc. This tag affects the generated Java, rather than the HTML it will output.

<jsp: useBean ...>

Has a list of attributes that specify a Java bean to invoke, and parameters to pass to it. Note that it ends with “>”. This tag uses the XML conventions.

As a further example, the following JSP code echoes back all the headers that the page received. Note that there are some variables predefined within JSP for the coder’s convenience. The response PrintWriter is “out,” the HttpServletRequest is “req,” and the HttpServletResponse is “resp.”

You should type this in and try running it using the pathnames shown in Table 16-10. Make sure Tomcat is running when you try this program, otherwise there is nothing to handle the request!

Table 16-10. Executing Your JSP

Purpose

Value

JSP source file

$TOMCAT_HOMEwebappsexamplesjspecho.jsp

JSP class file

generated automatically for you.

Your $CLASSPATH

You do not need to set this for JSP, but it doesn't hurt if you leave it set pointing to the servlet.jar file.

Browse this URL to run

http://127.0.0.1:8080/examples/jsp/echo.jsp

Since we aren’t sending across any parameters, we don’t need to invoke the JSP with a form, and we can just directly browse the JSP file itself. If you have connected up everything correctly, there will be a small pause while Tomcat automatically generates a servlet for the JSP and compiles it. Then you should see something like Figure 16-6 appear in your browser.

Results of browsing your JSP file.

Figure 16-6. Results of browsing your JSP file.

A browser doesn’t know if there’s a servlet, JSP, or static web page at the other end of the URL. These are the kind of headers that the client sends with any request. The headers will vary slightly on different systems and browsers. It is possible to shorten this JSP example by using the JSP tag that automatically does the output, as shown in this next JSP example.

Second Example of JSP

<html> 
<body bgcolor="white"> 
<h1>The Echo 2 JSP</h1> 
<%      java.util.Enumeration eh = request.getHeaderNames(); 
            while (eh.hasMoreElements()) {
                   String h = (String) eh.nextElement(); 
%> 
                    <br> header: <%=  h  %> 
                              value: <%=  request.getHeader(h) %> 
<% 
     } 
%> 
</body> 
</html> 

JSP code can become messy if you are not careful, as this example shows. Tangled messes seem much more common than nicely separated code. People have put effort into additional servlet-based technologies such as WebMacro (www.webmacro.org), Enhydra (xmlc.enhydra.org), and Velocity (jakarta.apache.org/velocity) to try to enforce the separation more cleanly. If you are working with JSP, you should look into these packages.

To help deploy all the files to your application server, you may create a Web Archive (WAR) of your JSPs. A war file is just like a jar file with the addition of a “/WEB-INF” directory and a “web.xml” file that describes the application to Tomcat. You can use the “jar” tool that comes with the JDK to create it. The file format is the same, but a different extension name was chosen to highlight the different uses of a .jar and a .war file. A .jar file contains a set of classfiles that can be placed in a classpath. It might also be double-clickable, containing everything including a GUI needed to run an application. A .war file contains servlet and JSP classfiles that can only be run in the context of a web server.

The Tomcat server has a configuration directory at TOMCAT_HOMEconf. In there you will find a web.xml file that can configure Tomcat for web-related issues (like the MIME types it understands), and an example server.xml file that configures it with information about your servlets.

The configuration file uses XML, which is a human-readable form that looks a bit like lots of new HTML markup tags. Chapter 28 has more information on XML. You will find that you need to stop and start Tomcat again so that it can pick up changes in your servlets. You can change the configuration file so that it always looks for a newer version classfile before running a servlet. This is called making the servlet reloadable, but there is a large performance cost to this feature, so you want to turn it off after your development is complete. You can add other details to the configuration file, like the servlet names and the URLs that correspond to them. If you stick to the pathnames shown in this chapter you can get it all running without the additional distraction of mastering a Tomcat configuration though. The most important thing is to put your compiled code under the directory c: omcatwebappsROOTWEB-INFclasses. The directory structure under that must match the package hierarchy of your code (see Table 16-11). If you are getting a few examples working without using a named package, the classes can go right into that directory.

Table 16-11. Where to Put Files with Tomcat

Purpose

Value

Directory for .jsp and .html files

omcatwebappsROOT

Directory for .class files

omcatwebappsROOTWEB-INFclasses

Then access pages as:

JSP page

http://localhost:8080/my.jsp

HTML page

http://localhost:8080/myservlet.html

Servlet URL

http://localhost:8080/servlet/myservlet

Java Beans in Servlets and JSP

This chapter wouldn’t be complete without pointing out the role of Java beans on the server side. Java beans are software components, namely well-specified “modules” which do a specific job and can easily be reused in many applications. Microsoft makes extensive use of software components under the product name ActiveX, often for some visual or GUI feature. For example, a programmer might write a piece of code that can display a set of numbers as a pie chart. That routine is very suitable for turning into a software component, making it available to any program on the system.

The point of JSP is to use lots of Java beans that cover your business processes. You might have one bean that encompasses everything you can do with a customer record, another for an order, a third for a payment transaction. JSP lets you easily glue these beans together in a web-based display framework. JSP has a special tag that lets web pages on the server easily interact with beans with hardly any “glue” code needed. People call this a “tag library.” Here’s an example of the tags that connect a JSP page to a Java bean that manages database access.

<%@ page language="java" import="java.sql.*" %> 

<jsp:useBean id="db" scope="request" 
  class="com.afu.database.DbBean" /> 

<jsp:setProperty name="db" property="*" /> 

You use the same beans (the same logic) for your non-web-based processing so you have the advantages of consistency, familiarity, and software reuse. The combination of Java beans and JSP is dealt with at length elsewhere, so we will note that it is a major use of JSP and leave it at that.

The main reason for using JSP is that it allows web developers to quickly build web pages that interface to enterprise systems. The JSP tags let HTML designers tie web information into corporate business logic contained in Java objects without having to learn all about Java object-oriented programming. A separate, smaller programming team can create libraries of software components. Then web designers can use those libraries by writing markup tags that they are familiar with. Use of “tag-libraries” are one of the cornerstones of JSP. JSP thus provides a rapid prototyping framework for building two tiers (the client and the front-end server) of an N-tier distributed system.

Servlets can act as a middleware gateway to existing legacy systems, providing an easy way to “webify” your current systems. Furthermore, since all the code is on the server (not the client), when you want to update your application you just roll the code out to a few servers and your entire user base gets the newest code at once.

Further Reading

When you start to write servlets on a regular basis, you might want to check the website www.revusky.com. At that site, skilled Java programmer Jonathan Revusky has made available some free tools for improving and simplifying your Java code. One of the tools is “Niggle”—an easy-to-use framework for building robust web applications.

If you are interested in a more detailed study of servlets, download and read the Java Servlet 2.3 Specification from the java.sun.com website. Although its title is “Specification,” it actually contains some good explanations of the details of servlets. Marty Hall’s book, Core Servlets and JavaServer Pages (Prentice Hall, 2000), is also recommended.

If you want to know what kind of web server a site is running, or you want to see the market share of different webservers, look at www.netcraft.com. Finally, the website www.servlets.com is a great resource for programmers writing servlets and JSP code.

Exercises

  1. Modify the petform servlet so that it includes the content length in its response.

  2. Write a servlet that sends back to the client (for display) all the parameters and HTTP request headers that it received. Have the servlet get enumerations of all the headers and all the parameters, and echo them back to the client.

  3. Write a Java Server Page that handles our “pet selection” form.

  4. Earlier in this chapter, we showed an HTML form that invoked a servlet. It’s actually possible to write a servlet or JSP that delivers that form as well as responding to it. When the servlet is invoked by a URL, it should respond with the HTML representing the form for pet selection. When the servlet is invoked by submitting the form, it should make the pet selection. That keeps everything relating to pet selection in one file, possibly easing maintenance. You can tell if a form was submitted by doing a requestParameter() on any of the argument names, like this: String formSent =request.getParameter("legs"). If the string comes back null, there wasn’t a form submitted (or at least that argument was not filled in), so the servlet must have been invoked with a URL reference; the service routine should then generate the form. Otherwise, the servlet should send back the HTML with the pet selection. Write a JSP file so that it delivers the pet selection form in this way, and responds to it too.

  5. Write an applet/servlet combination that writes/displays a high score file for a game. You might want to integrate this with one of existing games on the CD.

  6. (Extra credit) Read RFC 2616 (the Internet standard for HTTP) available at www.rfc-editor.org. Use that information to write a very simple web server in Java that can list directories and serve plain text and HTML files. It should use a ServerSocket to accept requests, read the requests, and then send back the appropriate information. Use a property file to configure the web server (e.g., the root directory that it will serve, etc.). Ignore sessions, cookies, headers, etc. This can be done in 200-300 lines of Java.

Some Light Relief—The Java-Powered Toaster

First prize for the “most entertaining Java application of 2001” goes to Robin Southgate. For his final year project as an Industrial Design student at Brunel University, England, Robin designed and built a bread toaster. Not just any toaster though. Robin’s toaster is powered by a Java program that dials a weather service, retrieves the forecast, and singes the outlook onto the toast. Examples of the toast are shown in Figure 16-7.

Java-powered Toaster

Figure 16-7. Java-powered Toaster

Robin’s design integrates a standard domestic toaster with the TINI microcontroller from Dallas Semiconductor. The TINI (Tiny InterNet Interface) is a $20 microcontroller chip set that supports an incredible software development platform. TINI contains a Java virtual machine, a web server, and a TCP/IP network stack running on top of a real time operating system, all in less than half a Mbyte of flash RAM. You program the chip and control I/O to its peripherals completely in Java. The peripherals can include ethernet, a parallel port, a wireless network interface, as well as the usual RS232 serial port and I2C bus.

Robin modified the toaster so that it works automatically. When a piece of toast is put in, the microcontroller wakes up and dials out through a modem on the serial port to remotely access the weather information. The Java code then condenses the forecast into a choice between “sunny,” “overcast,” “rain,” or “snow,” and chooses the appropriate baffle to move in front of the toast heater element. The baffle is made of polytetrafluorethylene (more commonly known as “teflon” or PTFE) which is both food-safe and heat resistant at toaster temperatures. The baffle has a hole in the shape of the weather icon, exposing that area of the toast to more radiant heat than adjacent masked areas. The toast pops up in about 30 seconds with the weather icon burned onto it.

When he started on the project, Robin appealed to the TINI engineering mailing list for advice. About half the engineers made a lot of fat-headed suggestions, like using cocoa powder for toner to print on the bread. Another proposed using a CO2 laser to reduce cooking time into the 1-2 second range. They just didn’t seem to be taking the project seriously. Other engineers could see the value of Java-powered toast, and gave Robin guidance on how he could refine his design.

The project involved sensing toaster operation, communicating with a remote site, decoding the data returned, moving the baffles, and controlling the toaster element. The protoype shown in Figure 16-8 needed special attention to switch the high current for the heating element safely. TINI is an excellent choice for this kind of embedded design. It has a built-in serial port that can trivially drive an external modem. There are readily available modules to monitor current, temperature, baffle position, and to switch loads. A key element with all projects is to build and debug the new design in stages rather than trying the whole thing at once. And of course, all the programming was done in Java.

Java-powered toaster.

Figure 16-8. Java-powered toaster.

See www.dalsemi.com for more information on the amazingly capable Java products from Dallas Semiconductor. As one engineer on the mailing list concluded, “when it comes to domestic appliances for toast-related processing, Java has the biggest appetite.”

If, like me, you have often wondered what a Java program to control a weather-forecasting toaster looks like, here is the answer. It is just the regular “put bit patterns into ports” that comprises most embedded programming, but expressed in Java quite neatly.

//  The toaster main control program 

import java.util.*; 
import java.io.*; 
import com.dalsemi.onewire.*; 
import com.dalsemi.onewire.adapter.*; 
import com.dalsemi.onewire.container.*; 
import com.dalsemi.onewire.container.OneWireContainer.*; 
import com.dalsemi.onewire.utils.*; 
import com.dalsemi.onewire.utils.Address; 

public class WeatherSwitch {

    public static void main(String args[]) {
         // details omitted... 
         // contact server, get forecast 
         // translate it into a command for the Switch. 
    } 

    public static void Switch2405(byte[] ID) {
       // "ID" is a byte array of size 8 with the address 
       // of a part we have already found. 
       // "access" is a DSPortAdapter 
       DSPortAdapter access = new TINIExternalAdapter(); 
       int i=0; 
       OneWireContainer05 ds2405 = 
                    (OneWireContainer05) access.getDeviceContainer(ID); 
       ds2405.setupContainer(access,ID); 
       byte state[] = {}; // declare variable first, we'll assign it below 

       try // catch exception {
         state = ds2405.readDevice(); 
       } catch (Exception e) {}; 

       // I know that the 2405 only has one channel (one switch) 
       // and it doesn't support 'Smart On' 
       boolean latch_state = ds2405.getLatchState(0,state); 
       System.out.println("Current state of switch: "+latch_state); 
       System.out.println("Current output level:" + 
                                              ds2405.getLevel(0,state)); 
       if (!latch_state) {
           System.out.println("Toggling switch"); 
           ds2405.setLatchState(0,!latch_state,false,state); 
           try {
               ds2405.writeDevice(state); 
               state = ds2405.readDevice(); 
               latch_state = ds2405.getLatchState(0,state); 
           } catch (Exception e) {}; 
           System.out.println("Current state of switch: "+latch_state); 
           System.out.println("Current output level:" 
                                             +ds2405.getLevel(0,state)); 
       } 
   } 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.26.90