Skip to main content

Section 15.11 Java Server Pages (JSP) and Servlets

In this chapter we have been discussing the client/server model of computing. Thus far we have learned how to implement client/server applications using socket connections between programs running on different computers. Because it requires the programmer to directly create and manage the socket protocol, this socket-level approach is a low-level approach. It is important to know about sockets and how they are used, but most client/server applications are programmed at a much higher level by using Java library classes.

Our focus in this section will be to give you a brief sense of how Java programs can be integrated into the Web pages. We will discuss two approaches: Java Server Pages (JSP) and Java servlets. As Web-based approaches, both of these require the use of HTML (HyperText Markup Language) code, the language that is used for coding Web pages. This means that in order to write your own servlets and JSPs you would really have to learn a little about HTML code. Fortunately, learning HTML code is not difficult and although it doesn't fit within the scope of this book, you can easily find books or Web sites that cover basic HTML coding.

In order for servlets and JSPs to work, they must be run in a Web server that is specially configured to understand Java code. Apache Tomcat is a simple web server that you can download and install for this purpose. Note that the current software industry does not use JSP and servlets as much these days. Spring is a popular Java web application framework that is used instead.

Subsection 15.11.1 Java Server Pages

A Java Server Page (JSP) is a Web page that contains small snippets of Java code. The Java code on a JSP embedded within <% ... %> brackets and interspersed among a page's HTML tags. The Java code can extend over one or more lines. Listing 15.11.1 shows the complete sourcecode for a simple JSP.

<html><head><title>Very Simple JSP Example</title></head>
<body bgcolor="white">
<h1>Very Basic JSP</h1>
Current time: <%= new java.util.Date() %>
<br><br>
Reload this page to watch the greeting change.
<br><br><b>
<!-- including lines of Java code in an HTML page -->
<%
   int um = (int)( Math.random() * 5 );
   switch ( um )
   {
      case 0: out.println("Welcome"); break;
      case 1: out.println("Bienvenidos"); break;
      case 2: out.println("Bienvenue"); break;
      case 3: out.println("Bienvenuti"); break;
      case 4: out.println("Willkommen"); break;
      default: out.println("Huh? " + um);
   }
   out.println("<br>");
%>
</b>
</body>
</html>
Listing 15.11.1. A simple JavaServer Page (JSP).

In this example we see two uses of Java code. In the first case, a JSP expression tag is used to display the current date on the Web page:

Current time: <%= new java.util.Date() %>

A JSP expression element begins with <%= and ends with %>. The expression contained within the tag is evaluated, converted into a Java String and inserted into the Web page. In this case the Date object is evaluated and its string value is displayed on the Web page (Fig. Figure 15.11.2).

Figure 15.11.2. A screen shot of a JSP.

In the second case, a scriptlet of Java code uses the Math.random() method to display a random greeting on the Web page. A scriptlet extends over several lines and is contained within the <%...%> tag (Listing 15.11.1). Note the use of the output statement, out.println(). The out object is a built-in output stream. Anything written to out will be transmitted as part of the HTML code that is sent to the Web page. In this case, one of the greetings is displayed each time the page is reloaded.

Obviously, this simple example only scratches the surface of what you can do with JSP. If you want to learn more about JSP, there are many helpful online tutorials available, such as https://www.tutorialspoint.com/jsp/index.htm. However, remember that in order to experiment with JSP, it will be necessary to have access to a JSP-aware Web server either on your own computer or on one provided by your service provider.

Subsection 15.11.2 Java Servlets

A Java servlet is another high-level approach to developing client/server applications. A servlet is a Java program that runs on a Web server and processes Web pages using the HyperText Transfer Protocol (HTTP). In a Web application, the browser serves as the client.

Many URLs that we access on the web are pure HTML files that are simply transmitted back to the browser by the Web server. For example, the following web page:

<HTML>
<HEAD>
   <TITLE>Very Simple HTML Document</TITLE>
</HEAD>
<BODY>
    <CENTER><H1>Hello</H1></CENTER>
</BODY>
</HTML>

If we want the server to do some processing and submit the results of that processing to the browser, we could use a Java servlet. A servlet can perform some processing task and return the results of that task to the browser in the form of an HTML document.

The difference between a Java servlet and a Java applet is that \marginpar{Servlets vs. Applets} an applet performs all of its processing on the client side of the client/server connection. A servlet performs its processing on the server side. When you load a Java applet into a browser, the Web server downloads the applet's bytecode into the browser. The browser then runs the byte code, assuming, of course, it is equipped with a plugin for the Java Virtual Machine (JVM). When you access a Java servlet from a browser, the Web server performs some computation and transmits just the results to the browser.

There are several advantages of servlets over applets. First, servlets cut down significantly on the amount of data that has to be transmitted to the browser. Second, because the servlet returns an HTML-encoded page, there are many fewer platform-related problems. All browsers can interpret HTML code, but not all browsers have the right plugins for interpreting Java applets. Third, servlets are not subject to the same security and privacy restrictions as Java applets, which, as we saw earlier in the chapter, must be run as untrusted code. Finally, Java servlets can directly access large databases and other resources that are stored on the server. Access to such resources via an applet would be very difficult and inefficient.

So, servlets have many advantages over applets. Because of these advantages they have quickly become an industry standard for developing client/server applications on the Web.

Subsection 15.11.3 A Simple Servlet Example

To illustrate the difference between a Java servlet and a simple HTML page, Figure 15.11.3 shows a servlet that creates a Web page that says “Hello.” As you can see, a servlet is a Java program. In addition to libraries that you are already familiar with, such as java.io, it also imports names from two new libraries: javax.servlet and javax.servlet.http. The program defines a single class, the HelloServlet class, which is a subclass of HttpServlet, the standard superclass for all Java servlets.

import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloServlet extends HttpServlet {
    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<HTML>");
        out.println("<HEAD>");
        out.println("<TITLE>Simple Servlet</TITLE>");
        out.println("</HEAD>");
        out.println("<BODY>");
        out.println("<H1> Hi, from a Java Servlet.</H1>");
        out.println("</BODY>");
        out.println("</HTML>");
    }
  }
Listing 15.11.3. A simple Java servlet.

The servlet defines the doGet() method. This is a method that is defined in the HttpServlet superclass. Our HelloServlet is overriding that method. In general, Web browsers make two types of requests when they request a Web page, a get or a post. We won't go into the differences between these requests. The result in either case is that the Web server will respond to the request by transmitting some text data to the browser. When a browser makes a get request, the server will automatically call the servlet's doGet() method. That's why we have to override it. The HttpServlet class also has a default doPost() method, which is called automatically to handle post requests.

Note the two parameters in the doGet() method: the HttpServletRequest and the HttpServletResponse. The doPost() method has the same two parameters. These are the objects that are used to hold the data that are communicated between the client and the server. When the client (browser) makes a get request, the HttpServletRequest objects hold the data contained in the request. These data might include data that a user has typed into an HTML form. We will see an example of how to extract these data in the next section.

The HttpServletResponse object is where the servlet will write its response. As you can see from examining the code, the HttpServletResponse object has an associated output stream, a PrintWriter, and it is a simple matter to write text to that output stream. Note that the text we write is HTML code that is practically identical to the code contained in the previous HTML example.

Subsection 15.11.4 The Nim Servlet

The simple servlet in the preceding section illustrates how the servlet communicates with the client—by writing HTML code to the HttpServletResponse object. Let's now look at an example that uses two-way communication between the client and server. To keep the example simple, we will revisit once again on our One Row Nim game. In this application the servlet will manage the One Row Nim game and will play against a human player, who will access the game through a Web browser.

Figure 15.11.4. The interface for the Nim servlet.

The browser interface for this version of the game is shown in Figure 15.11.4. As you can see, it is a simple Web page. The sticks in this instance are replaced by pennies. In addition to reporting the total number of pennies left, the page displays images of pennies. This Web page itself is organized as a simple HTML form, which contains one text field for the user's input. Each time the user hits the RETURN key in the text field, the user's input is transmitted to the servlet where it is processed. The servlet then transmits a new page to the user's browser, which shows the updated state of the game.

Let's now look at the servlet program itself, whose code is shown in Listing 15.11.5. This servlet program is quite a bit longer than the simple hello server, but it is not really any more complex or difficult. The NimServlet extends the HttpServlet superclass and overrides the doGet() method. Note that it also overrides the doPost() method, by simply having that method call the doPost() method. So this servlet will work for both get and post requests.

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class NimServlet extends HttpServlet {
    private OneRowNim nim = null;
    private NimPlayer nimPlayer = null;
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response)
      throws IOException, ServletException
    {
        doGet(request, response);
    }
   
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException
    {
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      HttpSession session = request.getSession(true);
      out.println("<html>");
      out.println("<body>");
      out.println("<head>");
      out.println("<title>Simple Nim Game</title>");
      out.println("</head>");
      out.println("<body>");
      out.println("<center><h1>One Row Nim</h1></center>");
      out.println("<center><h3>The Rules</h3>");
      out.println("A random number of pennies is thrown on the table.<BR>");
      out.println("Two players alternate making moves,<BR>");
      out.println("picking up between 1 and 3 pennies on each move.<BR>");
      out.println("The player who picks up the last penny loses.<BR><BR>");
      if (nim == null) {
        nim = new OneRowNim(7 + (int)(Math.random() * 11));
        nimPlayer = new NimPlayer(nim);
        out.println("<h4>You go first!</h4></center>");
      } else {
        int userTakes = Integer.parseInt(request.getParameter("pickup"));
        if (!nim.takeSticks(userTakes)) {
          out.println("<h4><font color='red'>Woops. That's an illegal move!. Try again. </font><h4>");
        } else if (!nim.gameOver()) {
          nim.changePlayer();
          out.println("<h4>So, you took <font color='blue'>" + userTakes + "</font><BR>");
          out.println("That leaves me with <font color='blue'>" + nim.getSticks() + "</font><BR>");
          int iTake = nimPlayer.move();
          out.println("OK. I take <font color='red'>" + iTake + " </font>pennies.<BR></h4>");
          nim.takeSticks(iTake);
          nim.changePlayer();
        } // if not gameover
      } // else nim != null
      if (!nim.gameOver()) {
        if (nim.getPlayer() == 1)
          out.println("<center><h3>Who's Turn: <font color='magenta'> Your turn </font><h3></center>");
        else
          out.println("<center><h3>Who's Turn: <font color='magenta'> My turn </font><h3></center>");
        out.println("<center><h3>Pennies Left: <font color='red'>" + nim.getSticks() + "</font><h3></center>");
        out.println("<center>");
        for (int k=0; k < nim.getSticks(); k++)
          out.println("<img src='http://xroads.virginia.edu/~CAP/LINCOLN/cent.jpg' width='25' height='25'>");
        out.println("</center><br>");
        out.println("<center>");
        out.println("<form action='/jjj3e/NimServlet' method='POST'>");
        out.println("<table border='0'>");
        out.println("<tr><td>How many do you pickup?: </td>" +
            "<td><input type='text' name='pickup' value='0'></td></tr>");
        out.println("</table>");
        out.println("</center>");
        out.println("</form>");
      } else {
        out.println("<h3><font color='red'>Game over!</font><h3>");
        if (nim.getPlayer() == 1)
          out.println("<center><h4>And the winner is : <font color='magenta'> Me.</font><h4></center>");
        else
          out.println("<center><h4>And the winner is: <font color='magenta'> You.</font><h4></center>");
        out.println("<center><h4><font color='magenta'> Nice game!</font><h4></center>");
        out.println("<center><h4>To play again, just reload the page.<h4></center>");
        nim = null;
      } // else game over
      out.println("</body>");
      out.println("</html>");
    }// doGet
Listing 15.11.5. Java code for the NimServlet

NimServlet uses two other objects: a OneRowNim object and a NimPlayer object. You should be familiar with these from Chapter 8, so we won't go over their internal details here. The OneRowNim object manages the playing of the game and the NimPlayer object acts as a computer-based player of the game. Note that variable references for these two objects are declared in the beginning of the class definition, but the objects themselves are declared within the doGet() method.

One of the tricky parts of NimServlet is how we declare the OneRowNim object. As you might already know, the HTTP protocol is said to be a stateless protocol, which means that each time a browser submits a request to a Web server, the Web server sees the request as a completely independent communication. The server does not, in and of itself, maintain an internal state that keeps track of a series of transactions with a particular browser session. For example, when you are shopping for books on Amazon, each time you go to a new page, the Amazon web server treats that request as a completely independent action. Web applications use various techniques to get around the stateless nature of the HTTP protocol. One technique is to use cookies to record the progress of a session. A cookie is a small text file containing data that the server uses to keep track of a user's session. Data that identifies the user and the state of the transaction—for example, buying a book—are passed back and forth between the browser and the server each time the user visits the Amazon Web site.

Java's servlet library contains methods and objects that support the use of cookies. But rather than use cookies, we will use the OneRowNim object itself to keep track of the state of the Nim game. The first time the user submits a request to Nim servlet—that is, when the user first visits the servlet's URL—the servlet will create an instance of the OneRowNim object. Creating a OneRowNim object will have the effect of initializing the game, including the creation of a NimPlayer to play the server's moves. The OneRowNim object will persist throughout the playing of the game and will handle all subsequent user's move. When the game is over, the NimServlet will, in effect, dispose of the OneRowNim object by setting its reference to null. Thus, in outline form, the code for creating and disposing of the OneRowNim object goes as follows:

// First request: Start a new Nim game
if (nim == null) {
   nim = new OneRowNim(7 + (int)(Math.random() * 11));
   nimPlayer = new NimPlayer(nim);
// Code deleted here.
else {
   // Code for playing the game goes here.}
if (!nim.gameOver()) {
  // Code for playing the game goes here.} else {
   // Code deleted here.
  nim = null;
}

Those places where code has been deleted in this segment would contain Java code for responding to the user's input and deciding how many pennies to take.

Unlike the HelloServlet, the NimServlet accepts input from the client. The code for handling user input is as follows:

int userTakes =
        Integer.parseInt(request.getParameter("pickup"));

This statements reads the user's input from the text field on the Web page by using the request.getParameter() method. This is one of the public methods of the HttpServletRequest object. The name of the text field is 'pickup', which is provided as an argument in this method call. As we noted above, the text field itself is on element of the HTML form contained in the servlet's Web page. The HTML code for creating the form element is also generated by the servlet:

out.println("<form action='/jjj3e/NimServlet' method='POST'>");
out.println("<table border='0'>");
out.println("<tr><td>How many do you pick up?: </td>" +
  "<td><input type='text' name='pickup' value='0'></td></tr>");

Unless you already know something about HTML, you won't completely understand this code. We will give a minimal explanation. In HTML, a text field is known as a input element of type 'text'. Note that this code segment names the element 'pickup', which allows our program to refer to it by that name.

The remaining details in the servlet have to do with managing the game and repeat concepts that were covered in Chapter 8. We won't repeat them here, other than to note that any output sent to the client must be in the form of HTML statements, hence the appearance throughout the code of HTML tags, which are the elements in the angle brackets.

You have attempted of activities on this page.