All Java, No Froth: 6 Easy Steps to MVC Web Apps

It’s an exciting time to be a Java web developer. Gaining popularity amongst hosting providers, Java 5 (Java 2 Standard Edition 5.0) contains a pile of new language features to bamboozle complacent developers who had grown used to knowing the language inside and out. Hosts have also largely deployed the latest releases of major Java web application servers, which support the current standards in Java web development (J2EE 1.4). And the major development tools have been updated to support the powerful features of these standards, such as JavaServer Faces. It’s all right there, waiting for you to use it.

At the same time, Java is getting a bad reputation among everyday web developers. There’s a growing sense that Java isn’t easy anymore, that you have to work for a company with the budget equal to the GDP of a small country for web development on this platform to make sense. Competing platforms like Microsoft’s .NET are winning loads of cool points for doing things that Java has done for years; nimble scripting languages like Ruby are making amazing things possible with very little code, while Java is perceived as a stagnant monolith by many.

A lot of this sentiment comes from the fact that Java web development was invented in layers. First there was this great, easy-to-learn programming language: Java. Someone wanted to generate web pages with it on the fly, so servlets were invented, and they ran on Java. Someone else wanted to build dynamic web pages without losing the HTML code among all the Java code, so JavaServer Pages (JSP) were invented, and they ran on servlets, which ran on Java.

Years later, the cutting edge of Java web development sits on top of at least a half dozen layers of technology, and as a newcomer you can quickly feel lost in the forest of buzzwords! So now we get hobbyists asking how to build a web-based photo gallery with Enterprise JavaBeans (EJB) – the equivalent of buying a tractor trailer to carry your bread and milk home from the corner store.

In this article, I’ll chart a map through that forest of buzzwords, so that as you take your first steps in Java web development you can work out what you really need to know, what you can really use, and what you can safely leave to the multinationals. Most importantly, I’m here to express the joy I find in working with Java. I hope I can help you find it, too.

Let’s Start at the Bottom…

As I have mentioned, Java web technology has been built up in layers over many years. Today, there are at least a dozen practical and proven approaches to building web sites with Java. By and large, however, they are all built on the same foundation: Java Enterprise Edition (JavaEE) — previously Java 2 Enterprise Edition (J2EE) — a constellation of related specifications that describe the aforementioned layers of server-side Java technology.

Picking our way through J2EE, we’ll start by looking at Servlets, then we’ll move on to JSP, combine the two as we examine Model 2, extend this to a discussion of MVC frameworks like Struts and Spring, and evenutally explore the various View technologies like Velocity, JavaServer Faces, and XMLC. This is by no means an exhaustive list — there’s lots to explore!

GA_googleFillSlot(“Articles_6_300x250″);

As we do this, I predict you’ll notice an interesting trend. Most web development platforms start out being reasonably easy to learn and use, but they tend to get more and more complicated as you try to shoehorn larger, more practical and complex projects into them. PHP comes to mind: much as I love that language’s ease of use, you can spend months reading people’s thoughts on how best to structure sizeable projects and still not come up with a clean solution.

The trend with Java is different: there is a lot to learn up front, and at first simple tasks can seem stupidly labour-intensive. But as you become comfortable with the layers of complexity, they begin to work for you, and projects that you used to find intimidating will start to seem easy.

To begin our tour, we’ll start with a dead simple web application: a database driven to-do list. We’ll be building this same application with each of the technologies we explore, and I’ll provide downloadable code for each version. Because this is a simple project, it’ll allow you to focus on the differences between the techniques, their strenghts and weaknesses, which features are easy to implement, and which are hard.

Each incarnation of this application will rely on the same MySQL database, so let’s start with that. If you plan to follow along, now’s a good time to make sure you have a healthy MySQL installation on your development machine. If you’re really new to databases or server-side web development in general, you can find a solid introduction to MySQL with full installation instructions in the first two chapters of my book, Build Your Own Database Driven Website Using PHP & MySQL. These chapters are available as free articles on sitepoint.com: chapter one and chapter two.

With MySQL in place, create a new database (I’ll call it todo) with the following single table in it:

CREATE TABLE todo ( 
 todoid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
 todo VARCHAR(255) NOT NULL
)

That’s it! We’re all set to look at the Java classes that will interface with this simple database.

Talking to MySQL: Your First Look at JDBC

To build the to-do list application we will use to explore the myriad Java web development technologies that are available, we’ll begin with the backbone of the application: a set of classes that connect to a MySQL database to retrieve, model, and update a to-do list.

Before we go any further, you’ll need a working knowledge of Java as a programming language. At the very least, you should understand the basic concepts of object oriented programming: classes, objects, methods, properties, and constructors. For an overview of these concepts and the necessary basics of Java programming, see my articles: Getting Started with Java, Java Language Basics, and Object Oriented Concepts in Java (part one and two).

In the following discussion, I’ll also make use of many of the built-in utility classes that Java offers in its core APIs. If you’re curious about these (and you should be!), you can browse the reference in the Java 5 API documentation, or grab a copy for yourself from the same page where you downloaded JDK.

Since we’re connecting to a database, we will be using the Java Database Connectivity (JDBC) classes, which are part of the Java Enterprise Edition (JavaEE) platform, supported by all Java-enabled web servers. JDBC provides a common set of classes for connecting to any database server (you can browse the API reference for these classes if you like).

In order to connect to MySQL with JDBC, we need to grab a copy of MySQL Connector/J, the JDBC driver for MySQL. After telling Java to load the driver, we can ask it to connect to a MySQL database, and all of the standard JDBC classes will know how to work with that connection.

Download and extract the MySQL Connector/J archive. Inside you’ll find a mysql-connector-java-version-bin.jar file (version 3.1.12 as of this writing), which is the driver library. Ignore the rest of the fluff and copy the JAR file to the working directory in which you plan to build your to-do list Java application.

We’re ready to start coding! In this article, I’ll present all the code line-by-line, so that you can type it straight into your favourite text editor. If you’re used to some of the more terse scripting languages out there, Java code may seem a bit verbose to you. Indeed, that’s one of the main things people who don’t like Java tend to complain about. For real world development, I would highly suggest you get yourself a solid Integrated Development Environment (IDE), such as NetBeans or Eclipse (both are free). A good IDE will write much of the code for you, so that Java’s verbosity becomes an aid to code readability, not a hindrance to productivity. In these initial learning stages, however, typing all the code by hand will definitely help you absorb exactly what’s going on, so I’ll leave further exploration of IDEs for a later article.

First of all, let’s build a class called ToDoList, which will represent the to-do list stored in the database and will allow us to access and modify its entries. We’ll put this class in a Java package (or namespace) called com.sitepoint so, in your working directory, create a directory called com with a subdirectory called sitepoint, and in it create a file named ToDoList.java. Start the file out with the required package declaration:

package com.sitepoint;

In this class, we’ll use the JDBC classes from the java.sql and the collection classes from java.util, so let’s import those:

import java.util.*; 
import java.sql.*;

Finally, we’ll declare our class:

public class ToDoList {

To keep the class as database-independent as possible, we’ll design its constructor to accept the name of a JDBC driver and a JDBC connection string, which together give it everything it needs to connect to a database through JDBC. The constructor will load the driver class immediately, then store the JDBC connection string in a private property, so that the object can use it to connect to the database when it needs to.

  private String jdbcConnectionString; 

 public ToDoList(String jdbcDriver, String jdbcConnectionString) {
   this.jdbcConnectionString = jdbcConnectionString;

   // Load the driver
   try {
     Class.forName(jdbcDriver).newInstance();
   }
   catch (Exception ex) {
     System.err.println("Error loading database driver " + jdbcDriver +
                        ":n" + ex.getMessage());
   }
 }

Class.forName() obtains a reference to the JDBC driver class, and calling its newInstance() method makes sure it is loaded. We catch any exceptions that may be thrown in case the driver class is not available (if you forget to do this, the compiler will remind you about it).

Now, our first version of this class will allow Java programs (and web pages) to:

  • Get a list of the items on the to-do list.
  • Get the number of items on the list.
  • Add new items to the list.
  • Delete items from the list.

Because fetching the list from the database can be a time consuming operation, we’ll make our class keep a copy of the list once it has been fetched, and only update it from the database when necessary.

  private List list = new ArrayList(); 
 private boolean staleList = true;

The list variable will store the list retrieved from the database, and the second will keep track of when that list needs updating (i.e. when it is "stale"). We start off with an empty ArrayList (Java’s stock-standard list class, from the java.util package), which is assumed to be in need of updating.

Now, whether the program wants the actual list of to-do items or it simply wants to know how many items there are, we will need to fetch the list from the database. So let’s write a single private method that checks if the stored list (in the list property) is stale, and loads the list from the database if necessary:

  private void refreshList() { 
   if (staleList) {
     // Load list from the database...

     staleList = false;
   }
 }

Loading the list from the database is where JDBC comes in. First, we use the JDBC connection string (stored by the constructor in jdbcConnectionString) to connect to the database. Since this is a time consuming operation, we’ll store the connection in another private property called conn, and only create a new connection when it is empty:

        if (conn == null) { 
         conn = DriverManager.getConnection(jdbcConnectionString);
       }

Next, we create a Statement object from the connection and use it to execute a SELECT query and obtain the resulting ResultSet object:

        Statement stmt = conn.createStatement(); 
       ResultSet rs = stmt.executeQuery("SELECT todoid, todo FROM todo");

With the results in hand, we store a new, empty ArrayList in the list property, and fill it with ToDoItem objects created from the contents of the result set:

        list = new ArrayList(); 
       while (rs.next()) {
         list.add(new ToDoItem(rs.getInt(1), rs.getString(2)));
       }

This may be a confusing bit of code for several reasons. First, we’re using a while loop to step through the result set. Calling the next() method of the result set advances it to the next record, or returns false if there are no records remaining, thus ending the while loop.

Within the loop, we’re using the add() method of the ArrayList class to add items to the list. But what exactly are we adding? New instances of the ToDoItem class.

ToDoItem is a simple little class that keeps track of an ID (the database ID of a to-do list item) and a string (the text for that item). These two values are "read only", in that there are no methods provided for altering them. Objects like this that represent records in the database are called data objects. Create this class by pasting the following code into a file called ToDoItem.java alongside the ToDoList.java file you're already working on:

package com.sitepoint; 

public class ToDoItem {
 private int id;
 private String item;

 ToDoItem(int id, String item) {
   this.id = id;
   this.item = item;
 }

 public int getId() {
   return id;
 }

 public String getItem() {
   return item;
 }

 public String toString() {
   return getItem();
 }
}

The only detail worthy of note in this simple class is that the constructor is not declared public, but is instead left package private, so that only classes within the com.sitepoint package can create ToDoItem objects.

Returning to ToDoList, the constructor of ToDoItem expects to be given the ID and text values for the item. We can fetch these values from the current row of the result set, using getInt(1) to fetch an integer value from the first column (todoid) and getString(2) to get a string value from the second column (todo).

That’s it for filling up the list, except that to handle database errors from all this we much catch any SQLExceptions that might be thrown (again, the compiler will remind you if you forget). Here’s the completed refreshList() method, and the delcaration for the conn property:

  private Connection conn; 

 private void refreshList() {
   if (staleList) {
     try {
       if (conn == null) {
         conn = DriverManager.getConnection(jdbcConnectionString);
       }
       Statement stmt = conn.createStatement();
       ResultSet rs = stmt.executeQuery("SELECT todoid, todo FROM todo");

       list = new ArrayList();
       while (rs.next()) {
         list.add(new ToDoItem(rs.getInt(1), rs.getString(2)));
       }
     }
     catch (SQLException ex) {
       System.err.println(
           "Error retrieving to-do list items from the database:n" +
           ex.getMessage());
     }
     staleList = false;
   }
 }

With the hard work done in refreshList(), implementing getToDoItems() and getItemCount(), to obtain the to-do list items and the number of such items respectively, is a cinch:

  public Iterator getToDoItems() { 
   refreshList();
   return list.iterator();
 }

 public int getItemCount() {
   refreshList();
   return list.size();
 }

The iterator() method of Java’s list classes returns an Iterator, an object much like the database result set we just worked with, that lets the requesting object step through the list. size(), meanwhile, is self-explanatory.

The addItem() and deleteItem() methods work much the same way as refreshList(), except they use a PreparedStatement instead of a simple Statement. Consider this code from addItem:

      PreparedStatement stmt = conn.prepareStatement( 
         "INSERT INTO todo (todo) VALUES (?)");
     stmt.setString(1, item);
     stmt.executeUpdate();

Notice the question mark in the INSERT query. This indicates a spot where some unknown value will be added to the query (the text for the new to-do list item, in this case). The setString(1, item) method call that follows assigns a string value (provided by the item variable in this case) to the first spot in the query. Other methods like setInt() let you enter values of other types. Sticking values into your database queries in this way neatly sidesteps the character escaping issues that often come into play with other languages, and that are often the cause of security vulnerabilities.

Here’s the complete code for addItem() and deleteItem(), thus completing our ToDoList class:

  public void addItem(String item) { 
   try {
     if (conn == null) {
       conn = DriverManager.getConnection(jdbcConnectionString);
     }
     PreparedStatement stmt = conn.prepareStatement(
         "INSERT INTO todo (todo) VALUES (?)");
     stmt.setString(1, item);
     stmt.executeUpdate();
   }
   catch (SQLException ex) {
     System.err.println(
         "Error adding a to-do list item to the database:n" +
         ex.getMessage());
   }
   staleList = true;
 }

 public void deleteItem(int id) {
   try {
     if (conn == null) {
       conn = DriverManager.getConnection(jdbcConnectionString);
     }
     PreparedStatement stmt = conn.prepareStatement(
         "DELETE FROM todo WHERE todoid=?");
     stmt.setInt(1, id);
     stmt.executeUpdate();
   }
   catch (SQLException ex) {
     System.err.println(
         "Error deleting a to-do list item from the database:n" +
         ex.getMessage());
   }
   staleList = true;
 }

Notice that each of these methods sets staleList to true once it’s done its job, so that the next attept to read the to-do list will cause refreshList to fetch it from the database again.

All we need now is a class to test the work we’ve done so far. Here’s a class called ToDoTest that’ll do the trick. Put ToDoTest.java in with your other files:

package com.sitepoint; 

import java.util.*;

public class ToDoTest {
 public static void main(String[] args) {
   ToDoList list = new ToDoList("com.mysql.jdbc.Driver",
       "jdbc:mysql://localhost/todo?user=root&password=password");

   System.out.println("The to-do list contains " + list.getItemCount() +
                      "items:");
   Iterator it = list.getToDoItems();
   while (it.hasNext()) {
     System.out.println(" - " + it.next());
   }

   list.addItem("Another todo item.");
   list.addItem("And yet another.");

   System.out.println("The to-do list contains " + list.getItemCount() +
                      " items:");
   it = list.getToDoItems();
   while (it.hasNext()) {
     System.out.println(" - " + it.next());
   }
 }
}

You’ll need to substitute your MySQL database name, user name, and password into the JDBC connection string near the top of this file.

Compile your three classes from the top-level working directory:

javac com/sitepoint/ToDoList.java com/sitepoint/ToDoItem.java 
   com/sitepoint/ToDoTest.java

Then run ToDoTest, with the MySQL JDBC driver added to the classpath:

java -classpath .;mysql-connector-java-3.0.15-ga-bin.jar 
   com.sitepoint.ToDoTest

You should see a list of the to-do list items before and after the two new items are added to the list, something like this:

The to-do list contains 2 items: 
- Another todo item.
- And yet another.
The to-do list contains 4 items:
- Another todo item.
- And yet another.
- Another todo item.
- And yet another.

Download the source code. (5KB)

That’s it! We’re ready to build a web application around these classes.

Servlets

If you’ve followed along, you’ve now got a to-do list database and a couple of classes that view and update it. The next step is to take that functionality to the web by wrapping it in a web application. On the Java platform, there are dozens of ways to do this. The simplest approach is to write a servlet. A servlet is simply a class that has methods that handle requests from web browsers.

Basic page requests are handled by a doGet() method. Form submissions that use the POST method are handled by a doPost() method. Objects passed to these methods provide access to information about the browser request and allow control over the servlet’s response.

GA_googleFillSlot(“Articles_6_300x250″);

An XML configuration file controls the URLs the servlet is responsible for, and provides any configuration information that the servlet may require.

The Java web application standard (J2EE) even specifies a directory structure, so that the servlet always knows where to find any class files, configuration files, and additional web resources (like images and style sheets) that it needs.

Let’s start by putting the stuff we have already into the correct directory structure. Create a new empty directory to work in, then create a subdirectory called WEB-INF. All of the "normal" web resources (HTML pages, images, style sheets and JavaScript files) will go in the main directory, while all the Java stuff (classes, libraries and configuration files) will go in WEB-INF.

Within WEB-INF, create two more subdirectories: classes and lib. WEB-INF/classes will contain all the Java classes for our web application, and WEB-INF/lib will contain any libraries that those classes may require.

Speaking of required libraries, remember from the previous section that our ToDoList class requires the JDBC driver for MySQL (MySQL Connector/J) to access the database. For a standalone application, we needed to add the JAR file (mysql-connector-java-version-bin.jar) to the classpath. For a Java web application, simply drop the file into the WEB-INF/lib directory.

Since we’ll be using the classes we’ve already developed (ToDoList and ToDoItem) in our web application, we need to put them in the WEB-INF/classes directory. You might as well drop the source files in there along with the compiled classes, just in case you need to make any changes — recompiling will then be a breeze.

Here’s our file and directory structure so far:

/WEB-INF/classes/com/sitepoint/ToDoItem.class  
/WEB-INF/classes/com/sitepoint/ToDoItem.java  
/WEB-INF/classes/com/sitepoint/ToDoList.class  
/WEB-INF/classes/com/sitepoint/ToDoList.java  
/WEB-INF/lib/mysql-connector-java-version-bin.jar

Let’s now turn our attention to building the servlet for our application. Remember, servlets are just Java classes, and this one will be com.sitepoint.ToDoServlet:

package com.sitepoint;  
 
import java.io.*;  
import java.util.*;  
import javax.servlet.*;  
import javax.servlet.http.*;  
 
public class ToDoServlet extends HttpServlet {

As you can see, servlet classes must extend the javax.servlet.HttpServlet class. You can view documentation on this and related classes in the J2EE API Specification.

Our servlet will use an instance of our ToDoList class, which we want to create when the servlet is first loaded. We can perform initialization tasks like this in the init() method, which the server will call when it loads the servlet:

  private ToDoList toDoList;  
 
 // Initialize global variables  
 public void init() throws ServletException {  
   toDoList = new ToDoList(getInitParameter("jdbcDriver"),  
                           getInitParameter("jdbcConnectionString"));  
 }

You may recall that the ToDoList constructor takes the name of the JDBC driver you want to use, and a JDBC connection string so that it can connect to your database. Rather than hard-coding these strings into our servlet, we use this code, which uses initialization parameters for these values, so that they can be configured without recompiling the servlet. We’ll look more at this later.

You’ll notice that the init() method, like all standard servlet methods, can throw a ServletException. This exception is used to let the server know that something went wrong in the servlet. We’ll see how this works a bit later.

Next up is the doGet() method, which handles normal browser requests. It takes two parameters: an HttpServletRequest that contains detailed information about the browser request, and a HttpServletResponse that the servlet can use to control its response to the browser:

  public void doGet(HttpServletRequest request, HttpServletResponse response)  
     throws ServletException, IOException {

Once again, the method is able to throw a ServletException to signal an error in the servlet. The servlet specification also allows this function to throw an IOException, in case there is a problem reading the request, or writing the response.

In response to normal browser requests, we want to display the current to-do list and give the user the ability to add items to the list, and also to delete existing items on the list. First, we must let the HttpServletResponse object know what content type we will be sending back to the browser:

    response.setContentType("text/html");

Now we can ask it for a PrintWriter object that we can use to send HTML code to the browser:

    PrintWriter out = response.getWriter();

The PrintWriter object lets us send HTML code to the browser using its println() method:

    out.println("<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"n" +  
               "  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">");  
   out.println("<html xmlns="http://www.w3.org/1999/xhtml">");  
   out.println("<head>");  
   out.println("<title>To-Do List</title>");  
   out.println("<meta http-equiv="content-type" " +  
               "content="text/html; charset=iso-8859-1" />");

If this doesn’t look very pretty to you, then you’ve spotted the biggest weakness of servlets: the HTML markup is mixed in with the Java logic of your application, which makes it difficult to read and maintain.

Pressing on, we want to link a CSS style sheet to our page:

    out.println("<link rel="stylesheet" type="text/css" href="" +  
               request.getContextPath() + "/styles.css" />");  
   out.println("</head>");  
   out.println("<body>");

Since we don’t yet know which directory of the web server our application will be installed in, we don’t know the path at which resources like style sheets and images will be available. The above code uses the request object’s getContextPath() method to obtain the path to the root of our application, and from there we can point to the styles.css file, which we’ll create a little later.

Next up, we’ll display our to-do list in an HTML form menu. We can start by grabbing an Iterator from our ToDoList with its getToDoItems() method. Then, we’ll check to see if it contains any items with its hasNext() method:

    Iterator toDoItems = toDoList.getToDoItems();  
   if (toDoItems.hasNext()) {

We want the form to submit back to the same URL, so that this servlet can handle that request as well, so we use the getRequestURI() method to get it:

      out.println("<form action="" + request.getRequestURI() +  
                 "" method="post">");

Since HTML form menus turn into drop-down lists with a size of 1, we want the <select> tag to have a size of at least 2, but we also want it to stretch to accomodate the number of items in our to-do list. We use the Math.max() method choose between 2 and the total number of items in the list, as given by the getItemCount() method of our ToDoList:

      out.println("<select name="deleteid" size="" +  
                 Math.max(2, toDoList.getItemCount()) + "">");

We can then loop through the toDoItems with a while loop. Each time we move through the loop, we pull a ToDoItem out of the Iterator with next(). Since it doesn’t know it contains ToDoItems, we need to cast them to the right class before we can use them:

      while (toDoItems.hasNext()) {  
       ToDoItem toDoItem = (ToDoItem) toDoItems.next();

For each item, we want to create a <option> tag with the item’s ID as its value. Outputting the ID is no problem, since it’s just an integer, but the to-do item itself gets tricky. What if the to-do item contains HTML code — possibly even malicious script code? We don’t want to output that stuff and have it interpreted by the browser as part of our site! The solution is to escape any special characters in the value before printing it out.

This is another area where servlets are weak: there is no built-in HTML escaping functionality in the servlet API or in Java in general (at least none that is accessible to us). Thankfully, this is a longstanding issue, and 3rd party classes have been created to do the job. The one I’ve chosen is developed and distributed by AnyWare. The class is called uk.co.anyware.html.HTMLEscaper, and its source code and license are included in the code archive I’ve provided below.

To use HTMLEscaper, drop the class (and source code if you want to hold onto it) into the WEB-INF/classes directory and add the required import to the top of the ToDoServlet class:

import uk.co.anyware.html.*;

With the class in hand, we can now safely output the to-do item. We’ll also polish off the rest of the form with a submit button for deleting selected items:

      out.println("</select>");  
     out.println("<input type="submit" value="Delete Selected Item" />");  
     out.println("</form>");  
   }

We’ll finish off the page with a second form, this time for submitting new to-do items:

    out.println("<form action="" + request.getRequestURI() +  
               "" method="post">");  
   out.println("<input type="text" name="newtodo" />");  
   out.println("<input type="submit" value="Add New Item" />");  
   out.println("</form>");  
 
   out.println("</body>");  
   out.println("</html>");  
   out.close();  
 }

That takes care of displaying the initial page to the user, but we’ve now got two forms submitting back to this same servlet!

Both of these forms submit using the POST method (method="post"), so we could handle them in the servlet’s doPost() method. But to make the servlet as flexible as possible we’ll also support submissions for adding new to-do items, and deleting existing ones, via GET requests. To do this, we’ll simply feed POST requests back into our doGet() method:

  public void doPost(HttpServletRequest request, HttpServletResponse response)  
     throws ServletException, IOException {  
   doGet(request, response);  
 }

At the top of doGet(), we now need to check for and process our form submissions. Here’s the code for handling new to-do items:

    String newToDo = request.getParameter("newtodo");  
   if (newToDo != null) {  
     toDoList.addItem(newToDo);  
 
     // Redirect to self  
     response.sendRedirect(request.getRequestURI());  
     return;  
   }

The getParameter() method lets us retrieve a submitted value with a given name as a string. If the value isn’t null, we know we have a submission on our hands. We add it to the to-do list using its addItem method, then redirect the browser to the current page with the response’s sendRedirect() method.

If we didn’t redirect the browser, the rest of the doGet() method would indeed display the updated to-do list for the user, but refreshing the page would cause the form submission to be sent again, resulting in a duplicate entry on the to-do list. Redirecting the browser back to the same page forces the browser to think of it as a separate request, and therefore it will not resubmit the form when refreshing the page.

The code for processing deleted items is very similar, except that it must convert the submitted string into an integer for the to-do list’s deleteItem() method:

    String deleteid = request.getParameter("deleteid");   
   if (deleteid != null) {  
     try {  
       toDoList.deleteItem(Integer.parseInt(deleteid));  
 
       // Redirect to self  
       response.sendRedirect(request.getRequestURI());  
       return;  
     }  
     catch (NumberFormatException e) {  
       throw new ServletException("Bad deleteid value submitted.", e);  
     }  
   }

The conversion is achieved by the Integer.parseInt() method but, if the value submitted cannot be converted into a number, it will throw a NumberFormatException. If this happens, our code catches the exception and throws a ServletException (to which we pass the NumberFormatException as a root cause).

GA_googleFillSlot(“Articles_6_300x250″);

Remember, all standard servlet methods are allowed to throw ServletExceptions to let the server know something has gone wrong. That’s exactly what we’re doing here. When the code throws the ServletException, the server running the servlet catches it and displays an appropriate error message in the user’s browser. You can configure most Java servers to control how much technical detail is included in such error pages.

Believe it or not, that’s it for the servlet! You still have to compile it, though, and that’s a little tricky. You see, the HttpServlet class that our servlet extends is included in the libraries distributed with every Java server, and you need that class to be able to compile your subclass.

In Tomcat 5.x, the servlet library is called servlet-api.jar and it can be found in the commonlib directory of your Tomcat installation. So you can compile your servlet by including that JAR file in the classpath:

javac -classpath   
".;c:Program FilesApache GroupTomcat 5.5commonlibservlet-api.jar"  
com/sitepoint/*.java uk/co/anyware/html/*.java

Here’s what your file and directory structure should look like now:

/WEB-INF/classes/com/sitepoint/ToDoItem.class   
/WEB-INF/classes/com/sitepoint/ToDoItem.java  
/WEB-INF/classes/com/sitepoint/ToDoList.class  
/WEB-INF/classes/com/sitepoint/ToDoList.java  
/WEB-INF/classes/com/sitepoint/ToDoServlet.class  
/WEB-INF/classes/com/sitepoint/ToDoServlet.java  
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.class  
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.java  
/WEB-INF/lib/mysql-connector-java-version-bin.jar

We have two things left to add to complete our Java web application. The first is the styles.css style sheet referenced by our servlet:

body, p, td, th {   
 background: #fff;  
 color: #000;  
 font: medium Verdana, Arial, Helvetica, sans-serif;  
}  
 
select {  
 width: 100%;  
}

Drop this in the main application directory, which also contains the WEB-INF directory.

The other thing we need is the XML configuration file for the application, web.xml. This file is called the deployment descriptor. It must start with a <web-app> tag like this one (again, any decent IDE will write this boilerplate code for you):

<?xml version="1.0" encoding="UTF-8"?>   
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"  
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"  
   version="2.4">

Next up, we provide a name for our web application:

  <display-name>ToDoServlet</display-name>

Now we’ll configure our servlet. We give it a name and specify its class:

  <servlet>   
   <servlet-name>toDo</servlet-name>  
   <servlet-class>com.sitepoint.ToDoServlet</servlet-class>

Now, remember the init() method of our servlet used two initialization parameters: one for the JDBC driver class name, and one for the JDBC connection string. We provide values for those parameters here:

    <init-param>   
     <description>The JDBC driver class.</description>  
     <param-name>jdbcDriver</param-name>  
     <param-value>com.mysql.jdbc.Driver</param-value>  
   </init-param>  
   <init-param>  
     <description>The JDBC connection string.</description>  
     <param-name>jdbcConnectionString</param-name>  
     <param-value>jdbc:mysql://localhost/todo?user=root&amp;password=password</param-value>  
   </init-param>  
 </servlet>

Finally, we supply a servlet mapping, which sends requests to a given URL to the servlet. For our example, we’ll direct requests for index.html in the root of our application to our servlet:

  <servlet-mapping>   
   <servlet-name>toDo</servlet-name>  
   <url-pattern>/index.html</url-pattern>  
 </servlet-mapping>  
</web-app>

That’s it for our application! Here’s the complete list of files:

/styles.css   
/WEB-INF/web.xml  
/WEB-INF/classes/com/sitepoint/ToDoItem.class  
/WEB-INF/classes/com/sitepoint/ToDoItem.java  
/WEB-INF/classes/com/sitepoint/ToDoList.class  
/WEB-INF/classes/com/sitepoint/ToDoList.java  
/WEB-INF/classes/com/sitepoint/ToDoServlet.class  
/WEB-INF/classes/com/sitepoint/ToDoServlet.java  
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.class  
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.java  
/WEB-INF/lib/mysql-connector-java-version-bin.jar

You’re now ready to bundle this application up so that it’s ready to be deployed on a Java-capable server. To do this, you need to use the jar utility included with the JDK. If you’ve added the bin directory of your JDK to your system path, you should be able to run it from the command prompt just by typing jar.

Move to your working directory for the application (the one that contains styles.css and WEB-INF), and type this command:

jar cvf ToDoServlet.war .

This will produce a file called ToDoServlet.war containing your application. It’s actually a ZIP file in disguise.

You now need to deploy this application on your server. Different servers provide different ways of doing this. If you’re using Tomcat, simply copy the ToDoServlet.war file into the webapps directory of your installation. After a few moments, Tomcat will automatically extract the file into a new directory. You can then go and edit the web.xml file to make sure the JDBC connection string contains the correct details for your database server.

Once that’s done, you should be ready to run your application. Load up http://localhost:8080/ToDoServlet/index.html in your browser (assuming Tomcat is running on port 8080 on your local machine). Here’s what you should see:

1507_todoservlet

Have a play with the page. It should work just as you’d expect. Here’s the WAR file (complete with source code if you unzip it):

Download the code. (250KB)

Old School JSP

You’re ready for your next step along the path to understanding the state of the art in Java web application development. So far, we’ve looked at servlets: Java classes that are designed to respond to web browser requests. Using a servlet, we have assembled a simple web interface to our database driven to-do list. And while it works, it would be a pain in the butt to write practical web applications this way, with the application logic all mixed in with the HTML code for the page.

JavaServer Pages (JSP) were created to overcome this weakness of servlets. Instead of writing a Java class with HTML code in it, you write an HTML page with Java code in it. The server then converts this page into a Java servlet on the fly in order to process page requests. As we’ll see, reversing our approach in this way solves some problems, but creates some new ones.

Starting with the to-do list web application we built a moment ago, let’s do away with our pesky servlet and replace it with a JavaServer page that does the same thing: todo.jsp. Here’s the updated file and directory structure for our application:

/todo.jsp    
/styles.css    
/WEB-INF/web.xml    
/WEB-INF/classes/com/sitepoint/ToDoItem.class    
/WEB-INF/classes/com/sitepoint/ToDoItem.java    
/WEB-INF/classes/com/sitepoint/ToDoList.class    
/WEB-INF/classes/com/sitepoint/ToDoList.java    
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.class    
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.java    
/WEB-INF/lib/mysql-connector-java-version-bin.jar
GA_googleFillSlot(“Articles_6_300x250″);

Let’s get started writing our todo.jsp file. Open up your favourite text editor and we’ll get cooking!

JSP files look a lot like HTML files, except that scattered throughout them will be special JSP tags. As a general rule, all JSP tags start with <% and end with %>. As we look at more modern and advanced ways of working with JSP in future, this is a rule that will be broken but, for now, it’s okay if you take this as gospel.

The first thing we need to do is provide some information about the page. This is done with a page directive. Directives are a type of JSP tag that contain various settings and other types of configuration information. Directives have an @ sign following their opening <%. Here’s our page directive:

<%@ page import="java.util.*,com.sitepoint.*,uk.co.anyware.html.*" %>

The most common use for a page directive is to import Java packages that will be used by the Java code in the JSP file. In this case, we’ve indicated that we need classes from java.util, com.sitepoint, and uk.co.anyware.html. These same packages were imported by our to-do list servlet (the code for which you might like to have nearby for comparison).

We can then proceed to write our page much as we would any (X)HTML file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"    
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">    
<html xmlns="http://www.w3.org/1999/xhtml">    
<head>    
 <title>To-Do List</title>    
 <meta http-equiv="content-type"    
     content="text/html; charset=iso-8859-1" />    
 <link rel="stylesheet" type="text/css"    
     href="<%= request.getContextPath() %>/styles.css" />    
</head>

Look closely, and you’ll see another JSP tag in there: <%= request.getContextPath() %>. This is what we call an expression, as indicated by the = sign following the opening <% in the tag. Expressions are used to output the values of Java code; in this case, we’re outputting the value returned by the getContextPath() method of the request object — the root directory of our web application, which the browser needs to locate the styles.css file.

Yes, JSP code, just like servlet code, has access to the browser’s request through a variable called request. There is also a response variable for the browser’s response. Both of these variables are called implicit objects — they’re created implicitly for you.

Other implicit objects include out, an object that works just like the PrintWriter that is used in a servlet to send output to the browser, session, an object for storing values over the course of a particular user’s visit to your site, and application, an object for storing values for use throughout your application.

Now, just as our servlet relied on a ToDoList object to do a lot of the work of the application, so will our JSP file. We need to declare this object, and for this we need another JSP tag: a declaration.

<%!    
private ToDoList toDoList;    
   
public void jspInit() {    
 toDoList = new ToDoList(getInitParameter("jdbcDriver"),    
     getInitParameter("jdbcConnectionString"));    
}    
%>

As you can see, declarations are indicated by an exclamation mark (!) following the opening <%, and contain Java property and method declarations just like those you’d find in a Java class.

In this case, we’ve declared a ToDoList object called toDoList, and we’ve written a method named jspInit() that creates this object from initialization parameters, just as we did in our servlet’s init() method. While init() is a special method for servlets that is called by the server before a servlet is used for the first time, jspInit() is a special method that is called automatically to initialize JSP files.

Next up is the code that will process form submissions in this page. You’ll remember from our servlet that the page will contain two forms: one for adding items to the to-do list, and one for deleting them. The code for processing these submissions will be identical in our JSP, except that it goes inside yet another type of JSP tag: a scriptlet.

<%    
String newToDo = request.getParameter("newtodo");    
if (newToDo != null) {    
 toDoList.addItem(newToDo);    
 response.sendRedirect(request.getRequestURI());    
 return;    
}    
   
String deleteid = request.getParameter("deleteid");    
if (deleteid != null) {    
 try {    
   toDoList.deleteItem(Integer.parseInt(deleteid));    
   
   response.sendRedirect(request.getRequestURI());    
   return;    
 }    
 catch (NumberFormatException e) {    
   throw new ServletException("Bad deleteid value submitted.", e);    
 }    
}    
%>

When JSP was first conceived, scriptlets were expected to be the most common JSP tag type, so they are indicated with simple <% and %> delimiters — no special character inside the start of the tag. The Java code inside a scriptlet is executed every time the page is requested.

With the form processing taken care of, all that’s left is to produce the forms themselves. First up, we have our to-do list, which displays the current to-do items and allows the user to delete them:

<body>    
 <%    
 Iterator toDoItems = toDoList.getToDoItems();    
 if (toDoItems.hasNext()) {    
   %>    
   <form action="<%= request.getRequestURI() %>" method="post">    
     <select name="deleteid" size="<%= Math.max(2, toDoList.getItemCount()) %>">    
       <%    
       while (toDoItems.hasNext()) {    
         ToDoItem toDoItem = (ToDoItem) toDoItems.next();    
         %>    
         <option value="<%= toDoItem.getId() %>"><%= HTMLEscaper.escape(toDoItem.toString()) %></option>    
         <%    
       }    
       %>    
     </select>    
     <input type="submit" value="Delete Selected Item" />    
   </form>    
   <%    
 }    
 %>

Looks like a bit of a mess, doesn’t it? What we have here is a mixture of HTML code, JSP scriptlets, and JSP expressions. Let’s break it down.

  <%    
 Iterator toDoItems = toDoList.getToDoItems();    
 if (toDoItems.hasNext()) {    
   %>    
   ...    
   <%    
 }    
 %>

The first scriptlet gets an Iterator object containing the items in the to-do list. Our servlet did the exact same thing. Since we don’t need to display the to-do list if it doesn’t contain any items, we use an if statement to check if it does using the Iterator‘s hasNext() method.

All of the code for the form then goes inside this if statement. The closing brace of the if statement is in the last scriptlet of the page. As you can see, the Java code inside a scriptlet doesn’t need to be self-contained; you can think of the HTML code between your JSP tags as instructions to output that HTML code, with the scriptlets providing the logic for when and how that HTML should appear.

In the form, we use JSP expressions to output required values in our <form> and <select> tags:

    <form action="<%= request.getRequestURI() %>" method="post">    
     <select name="deleteid" size="<%= Math.max(2, toDoList.getItemCount()) %>">    
       ...    
     </select>    
     <input type="submit" value="Delete Selected Item" />    
   </form>

Finally, we need to output an <option> tag for each item in our to-do list. The code is once again remarkably similar to our servlet, as we use a while loop to do the job:

        <%    
       while (toDoItems.hasNext()) {    
         ToDoItem toDoItem = (ToDoItem) toDoItems.next();    
         %>    
         <option value="<%= toDoItem.getId() %>">    
           <%= HTMLEscaper.escape(toDoItem.toString()) %></option>    
         <%    
       }    
       %>

It’s a mess at first glance, but if you look carefully (or better yet, if you have an editor that highlights JSP tags in a different colour), you can see how the logic is in JSP scriptlets, and the rest of the code is just HTML with JSP expressions to output dynamic values.

The form for adding new to-do list items is a piece of cake compared to the first one:

  <form action="<%= request.getRequestURI() %>" method="post">    
   <input type="text" name="newtodo" />    
   <input type="submit" value="Add New Item" />    
 </form>    
</body> &   
</html>

That takes care of our JSP file! The only thing left is to update the web.xml configuration file for our application to make the initialization parameters (jdbcDriver and jdbcConnectionString) available to our JSP file:

<?xml version="1.0" encoding="UTF-8"?>    
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"    
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"    
   version="2.4">    
 <display-name>ToDoJSP</display-name>    
 <servlet>    
   <servlet-name>toDo</servlet-name>    
   <jsp-file>/todo.jsp</jsp-file>    
   <init-param>    
     <description>The JDBC driver class.</description>    
     <param-name>jdbcDriver</param-name>    
     <param-value>com.mysql.jdbc.Driver</param-value>    
   </init-param>    
   <init-param>    
     <description>The JDBC connection string.</description>    
     <param-name>jdbcConnectionString</param-name>    
     <param-value>jdbc:mysql://localhost/todo?user=root&amp;password=password</param-value>    
   </init-param>    
 </servlet>    
 <servlet-mapping>    
   <servlet-name>toDo</servlet-name>    
   <url-pattern>/todo.jsp</url-pattern>    
 </servlet-mapping>    
</web-app>

There are two significant changes from the web.xml file we used with our servlet:

  • Instead of using a <servlet-class> tag to indicate the servlet for which we are providing parameters, we have a <jsp-file> tag to indicate the JSP file.
  • The <url-pattern> tag in the <servlet-mapping> points to the JSP file as well.

With those changes made, you’re ready to bundle up the application and deploy it on your server. Unlike servlets, you don’t need to compile JSP files in advance — the server will convert them to servlets and compile them for you on the fly. You do, however, still need to compile the classes that your JSP uses (ToDoList, ToDoItem, HTMLEscaper).

As with the servlet, use the jar command-prompt utility to create a WAR file containing your application:

jar cvf ToDoJSP.war .

Drop this file in Tomcat’s webapps directory to deploy it (or deploy it using whatever Java-compatible server you prefer), and edit the deployed web.xml file to match your database configuration.

Then load http://localhost:8080/ToDoJSP/todo.jsp to try out your application. You should see your familiar to-do list interface, this time generated by a JSP.

Here’s the finished WAR file, including source code, for you to experiment with:

Download the code. (250KB)

Now, you’ll recall that the whole point of JSP was to overcome the messiness of mixing HTML code into the Java code of a servlet. If you’ve looked at the code for our new JSP file, I’d forgive you for being skeptical about whether we’ve achieved our aim.

Our to-do list JSP file is written with what I call "old school JSP". It’s pure JSP, as it was originally conceived years ago, with none of the modern amenities. In the rest of this article, I’ll show you how to modify it using current and advanced features of JSP. First of all, we’ll bring servlets back into the picture (but in a much simpler form!), then we’ll look at standards like JavaBeans, the Java Standard Tag Library, and JSP Expression Language.

Generally speaking, our goal will be to get rid of all the Java code in the JSP file, either by replacing it with more designer-friendly tag constructs, or by moving it into external, independent Java classes. By the time we’re done, you’ll know how to write a JSP file so that it is barely distinguishable from a standard HTML file.

Kickin’ It MVC-Style

Still following along? I’ve already shown you how to convert a to-do list servlet into a JSP. Unfortunately, what we got wasn’t much better in terms of readable code — Java code embedded in an HTML document isn’t a whole lot more readable than HTML code embedded in a Java class.

What to do? Well, so far we have two tools at our disposal: servlets and JSPs. Servlets are great for containing Java code, JSPs are great for containing HTML code. The answer is to split our application apart so that the Java code goes into servlets, and the HTML code goes into JSPs.

A standard approach for this called Model 2 Architecture has been around for a long time, but lately it has become known by the more descriptive name: Model-View-Controller (MVC).

GA_googleFillSlot(“Articles_6_300x250″);

The idea is to break the application into three parts:

  • The model: a collection of Java classes that perform the actual work of the application (often called the business logic), independant of the web interface.
  • The view, a collection of JSPs, or some other technology, that produces the actual web pages that the users see.
  • The controller, one or more servlets that process browser requests by telling the model what to do and then handing over to the view to respond.

Now I could go on and on about this all day, but it’s easier to see through an example, so let’s get to work on modifying our to-do list application.

The model is usually the best place to start, as you can usually write it without worrying much about the web interface. In the case of our to-do list application, we already have our model: it’s made up of the classes ToDoList and ToDoItem. These two classes do all the work of managing the to-do list.

While we’re looking at these classes, let’s make one minor tweak to the getToDoItems method: we’ll make it return a List rather than an Iterator. This allows for a bit more flexibility in how the to-do list items may be used when they are retrieved through this method.

  public List getToDoItems() {     
   refreshList();    
   return (List)list.clone();    
 }

Next, let’s work on our controller. We know we’ll have three different kinds of requests coming from the browser: simple requests to view the to-do list, form posts for adding new items to the list, and form posts for deleting existing items from the list.

We now have a choice: do we write one servlet that knows how to handle all these different request types, or do we write three simple, specialized servlets each of which knows how to handle one type of request? There’s no right answer, as there are advantages to each approach, but let’s try to keep our classes simple and go for multiple servlets.

We’ll start with ToDoServlet, which will handle requests to view the to-do list. The first thing this servlet needs to do is set up the model — an instance of ToDoList. Back when we first looked at servlets, we did this with the init() method of the servlet, which stored the ToDoList in an instance variable of the servlet.

This time, that won’t quite do the trick, because we want all three of our servlets to be able to access the model. We can’t create the ToDoList in one servlet’s initialization procedure because one of the other servlets might need it first, and we can’t store it in an instance variable because the other servlets wouldn’t be able to see it at all. What we need is a way to create the model when the web application first starts up, and a place to store it where any servlet can get at it.

To perform initialization tasks for the entire application, we must use a ServletContextListener. Rather than a class to extend, this is an interface, which any class can implement. Since our "main" servlet is a good place to do this stuff, we’ll make it implement that interface:

public class ToDoServlet extends HttpServlet     
   implements ServletContextListener {

When a class implements ServletContextListener, it must contain two methods: contextInitialized, which performs application initialization tasks, and contextDestroyed, which performs application cleanup:

  public void contextInitialized(ServletContextEvent sce) {     
   ServletContext sc = sce.getServletContext();    
   sc.setAttribute("toDoList",    
       new ToDoList(sc.getInitParameter("jdbcDriver"),    
                    sc.getInitParameter("jdbcConnectionString")));    
 }    
   
 public void contextDestroyed(ServletContextEvent sce) {    
 }

All the action here is in contextInitialized, since we don’t need to do anything special when the application shuts down. As you can see, when they’re called, both of these methods receive a ServletContextEvent from which we can get a reference to the ServletContext. The ServletContext is an object that represents the web application as a whole — it’s the context in which the servlet is running. All servlets and JSPs have access to the ServletContext; therefore, it provides the perfect place to store our model!

The ServletContext lets you set and get attributes, which are simply application-wide values associated with string labels. We’ll store our model, a new ToDoList object, in an attribute labelled "toDoList".

Before we move on, have a close look at the code that creates the ToDoList:

        new ToDoList(sc.getInitParameter("jdbcDriver"),     
                    sc.getInitParameter("jdbcConnectionString")));

As we’ve done previously, we’re getting the JDBC driver and connection string values required by this class from initialization parameters, but because we’re performing initialization for our entire application, the initialization parameters for the ToDoServlet are not yet available! That’s why we’re calling the getInitParameter method of the ServletContext object, not the servlet itself, as we’re used to doing. These are known as context initialization parameters, as opposed to servlet initialization parameters.

Now we’ve got a ServletContextListener that’s ready to initialize our application, as long as it gets the context initialization parameters it needs. As you may have guessed, we need to add some things into our web.xml file to make this work:

<?xml version="1.0" encoding="UTF-8"?>     
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"    
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">    
 <display-name>ToDoMVC</display-name>    
 <listener>    
   <listener-class>com.sitepoint.ToDoServlet</listener-class>    
 </listener>    
 <context-param>    
   <description>The JDBC driver class.</description>    
   <param-name>jdbcDriver</param-name>    
   <param-value>com.mysql.jdbc.Driver</param-value>    
 </context-param>    
 <context-param>    
   <description>The JDBC connection string.</description>    
   <param-name>jdbcConnectionString</param-name>    
   <param-value>jdbc:mysql://localhost/todo?user=root&amp;password=password</param-value>    
 </context-param>    
</web-app>

The <listener> tag lets the application know about the context listener we’ve provided, while the <context-param> tags set up our application-wide context initialization parameters.

Now, before we got caught up in all this application initialization stuff, I seem to remember that we were writing a servlet. So let’s take a look at the doGet and doPost methods:

  public void doGet(HttpServletRequest request, HttpServletResponse response)     
     throws ServletException, IOException {    
   ToDoList toDoList = (ToDoList)getServletContext().getAttribute("toDoList");    
   List toDoItems = toDoList.getToDoItems();    
   request.setAttribute("toDoItems", toDoItems);    
   
   RequestDispatcher view = request.getRequestDispatcher("/todo.jsp");    
   view.forward(request, response);    
 }    
   
 public void doPost(HttpServletRequest request, HttpServletResponse response)    
     throws ServletException, IOException {    
   doGet(request, response);    
 }

Look at that! A servlet with no embedded HTML code! How is such a thing possible? Well remember, this servlet is merely the controller in our MVC design: after getting things done with the model, it hands the request to the view to display the actual web page. Looking closely at the doGet method, you’ll see that this is exactly what it does:

    ToDoList toDoList = (ToDoList)getServletContext().getAttribute("toDoList");     
   List toDoItems = toDoList.getToDoItems();    
   request.setAttribute("toDoItems", toDoItems);

Here, it fetches the model (the ToDoList stored in a servlet context attribute), uses it to get a List of the to-do list items, and then stores that List someplace where the view will be able to find it — namely, in the request object. It turns out that the request object supports attributes too, and this is the perfect way to pass values to the view that it will need to build the page.

With the heavy lifting done, we’re ready to pass the request to the view (in this case, a JSP called todo.jsp in the root of our application):

    RequestDispatcher view = request.getRequestDispatcher("/todo.jsp");     
   view.forward(request, response);

At a glance, this may seem a bit confusing, but this is the formula we will always use to forward requests from a servlet to a JSP. We get a RequestDispatcher object for the location we want to forward to (in this case, "/todo.jsp" specifies the todo.jsp file in the root of the application), then we call its forward method, passing it the request and response objects it will need to do the job.

Okay, so I’ve had to yammer on a bit to explain all the new stuff that’s going on in this servlet, but if you step back and look at the code, you’ll find it’s actually pretty neat and tidy. And since they aren’t burdened with all the application setup stuff, our other two servlets are even neater and tidier!

package com.sitepoint;     
   
import javax.servlet.*;    
import javax.servlet.http.*;    
import java.io.*;    
   
public class AddToDoServlet extends HttpServlet {    
 public void doPost(HttpServletRequest request, HttpServletResponse response)    
     throws ServletException, IOException {    
   
   String newToDo = request.getParameter("newtodo");    
   if (newToDo != null) {    
     ToDoList toDoList = (ToDoList)getServletContext().getAttribute("toDoList");    
     toDoList.addItem(newToDo);    
   }    
   response.sendRedirect("index.html");    
 }    
}
package com.sitepoint;     
   
import javax.servlet.*;    
import javax.servlet.http.*;    
import java.io.*;    
   
public class DeleteToDoServlet extends HttpServlet {    
 public void doPost(HttpServletRequest request, HttpServletResponse response)    
     throws ServletException, IOException {    
   String deleteid = request.getParameter("deleteid");    
   if (deleteid != null) {    
     try {    
       ToDoList toDoList = (ToDoList)getServletContext().getAttribute("toDoList");    
       toDoList.deleteItem(Integer.parseInt(deleteid));    
     }    
     catch (NumberFormatException e) {    
       throw new ServletException("Bad deleteid value submitted.", e);    
     }    
   }    
   response.sendRedirect("index.html");    
 }    
}

You might be surprised to note that these servlets don’t actually forward to a JSP after they’ve done their work. Instead, they redirect the browser to "index.html", which we’ll shortly configure to point to our main ToDoServlet.

Because we want to show the user the updated to-do list after adding or deleting an item, we could forward the request to /todo.jsp, but, as I explained previously, this would lead to problems if the user were to refresh the browser afterward. The browser would re-submit the item addition/deletion request, causing errors or duplicate list entries. Redirecting instead of forwarding gets around this by having the browser make a new request, which is safe to repeat, after it has submitted the form.

To polish off our servlets, we need to assign URLs to each of them in our web.xml file. We’ll use /index.html for the ToDoServlet, since we want it to come up by default when a user loads our application directory. AddToDoServlet and DeleteToDoServlet will get /AddItem.do and /DeleteItem.do respectively, following the convention of giving "action" URLs .do extensions in Java web apps.

  <servlet>     
   <servlet-name>todoservlet</servlet-name>    
   <servlet-class>com.sitepoint.ToDoServlet</servlet-class>    
 </servlet>    
 <servlet-mapping>    
   <servlet-name>todoservlet</servlet-name>    
   <url-pattern>/index.html</url-pattern>    
 </servlet-mapping>    
 <servlet>    
   <servlet-name>addtodoservlet</servlet-name>    
   <servlet-class>com.sitepoint.AddToDoServlet</servlet-class>    
 </servlet>    
 <servlet-mapping>    
   <servlet-name>addtodoservlet</servlet-name>    
   <url-pattern>/AddItem.do</url-pattern>    
 </servlet-mapping>    
 <servlet>    
   <servlet-name>deletetodoservlet</servlet-name>    
   <servlet-class>com.sitepoint.DeleteToDoServlet</servlet-class>    
 </servlet>    
 <servlet-mapping>    
   <servlet-name>deletetodoservlet</servlet-name>    
   <url-pattern>/DeleteItem.do</url-pattern>    
 </servlet-mapping>

With our servlets done, all that’s left is to build the view for our application. For this example, all we need is a single JSP file: todo.jsp.

Now that we’ve pulled all our initialization and request processing code out into servlets, our JSP file looks a lot more reasonable:

<%@ page import="java.util.*,com.sitepoint.*,uk.co.anyware.html.*" %>     
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">    
<html xmlns="http://www.w3.org/1999/xhtml">    
<head>    
 <title>To-Do List</title>    
 <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />    
 <link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/styles.css" />    
</head>    
<body>    
 <%    
 List toDoItems = (List)request.getAttribute("toDoItems");    
 Iterator it = toDoItems.iterator();    
 if (it.hasNext()) {    
   %>    
   <form action="DeleteItem.do" method="post">    
     <select name="deleteid" size="<%= Math.max(2, toDoItems.size()) %>">    
       <%    
       while (it.hasNext()) {    
         ToDoItem toDoItem = (ToDoItem) it.next();    
         %>    
         <option value="<%= toDoItem.getId() %>"><%= HTMLEscaper.escape(toDoItem.toString()) %></option>    
         <%    
       }    
       %>    
     </select>    
     <input type="submit" value="Delete Selected Item" />    
   </form>    
   <%    
 }    
 %>    
 <form action="AddItem.do" method="post">    
   <input type="text" name="newtodo" />    
   <input type="submit" value="Add New Item" />    
 </form>    
</body>    
</html>

If you understood the original JSP we built, this one should be a piece of cake! The scriptlet code simply pulls the List out of the request‘s "toDoItems" attribute to produce the list of to-do items, and our two forms now submit to the .do URLs we assigned to the corresponding servlets. Beyond those changes, it’s the same old JSP with a lot less Java code.

And there we have it: an MVC Java web application! Here’s the directory structure:

/todo.jsp     
/styles.css    
/WEB-INF/web.xml    
/WEB-INF/classes/com/sitepoint/AddToDoServlet.class    
/WEB-INF/classes/com/sitepoint/AddToDoServlet.java    
/WEB-INF/classes/com/sitepoint/DeleteToDoServlet.class    
/WEB-INF/classes/com/sitepoint/DeleteToDoServlet.java    
/WEB-INF/classes/com/sitepoint/ToDoItem.class    
/WEB-INF/classes/com/sitepoint/ToDoItem.java    
/WEB-INF/classes/com/sitepoint/ToDoList.class    
/WEB-INF/classes/com/sitepoint/ToDoList.java    
/WEB-INF/classes/com/sitepoint/ToDoServlet.class    
/WEB-INF/classes/com/sitepoint/ToDoServlet.java    
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.class    
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.java    
/WEB-INF/lib/mysql-connector-java-version-bin.jar

Download the code. (250KB)

This application is starting to look pretty darned good, even if I do say so myself. Its major weakness continues to be the Java scriptlet code in the JSP. We’ve gotten rid of most of the Java code from this file, but what’s in there would still be pretty confusing for a web designer. The next step in the grand tour will be to look at some of the features of modern JSP that allow us to dispense with these scriptlets in favour of tags and expressions.

A Crash Course in Java-less JSP

It’s time to take the Java out of JavaServer Pages.

We’ve split our to-do list web application into three parts: the model, classes that manage the data at the heart of our application; the controller, servlets that process incoming requests and then send display values to the view; and the view, JSP files that generate web pages from those display values.

While this approach generally did a good job of separating the Java application logic from the HTML user interface code, it still left us with some Java code in our JSP file(s). This code was needed to grab the values supplied by the controller and massage them into our HTML interface. We’ll call this display logic.

Now, I’ll show you how to get rid of the Java code ftrom your JSP files, and implement that display logic with a simpler and more powerful alternative.

Let’s start by reviewing just what the Java display logic in our example’s JSP file does. First, it gets the list of items supplied by the controller:

  List toDoItems = (List)request.getAttribute("toDoItems");      
 Iterator it = toDoItems.iterator();

Then, it checks if there are any items in the list:

  if (it.hasNext()) {

To keep the HTML <select> displaying as a standard list of the correct size and not a drop-down list, we use display logic to set the size attribute:

<select name="deleteid" size="<%= Math.max(2, toDoItems.size()) %>">

Display logic is then used to process each of the to-do list items in turn:

        while (it.hasNext()) {      
         ToDoItem toDoItem = (ToDoItem) it.next();

Finally, display logic is used to extract the ID and text content of each to-do list item, and to escape any special characters that may appear in the text:

<option value="<%= toDoItem.getId() %>"><%= HTMLEscaper.escape(toDoItem.toString()) %></option>

Given that this is a relatively simple application, that’s quite a bit of Java code still lingering in a file which will ostensibly be created and edited by web designers — people who typically aren’t well versed in the finer points of the Java language and APIs.

So, what to do? Obviously this display logic is required, but we need a better way of implementing it than including Java code in our page.

There are actually quite a few alternatives that have been written by various groups floating around the Web. From simple JSP tag libraries (collections of custom tags that you can mix with your HTML to implement your display logic) to complete JSP replacements, the galaxy of options can be humbling. The solution proposed by the JSP 2.0 standard is a combination of a tag library called the JSP Standard Tag Library (JSTL) and a syntax for accessing Java values without Java code called JSP Expression Language (EL).

GA_googleFillSlot(“Articles_6_300x250″);

While EL is built into JSP 2.0, and therefore is available automatically in your JSP files, JSTL is a separate library that must specifically be included in your web application before you can use it. In Tomcat 5.x, you can grab the JSTL 1.1 library files from the jsp-examples web application included with the server. Simply go into the webapps/jsp-examples/WEB-INF/lib subdirectory of the server installation, grab jstl.jar and standard.jar, and copy them into the WEB-INF/lib subdirectory of the to-do list web app.

You can now use JSTL tags in your JSP files. Let’s modify the todo.jsp file to produce the same to-do list user interface without any Java scripting.

First, we need to declare our intention to use JSTL tags in the file. JSTL is actually divided into a number of sub-libraries, so you don’t have to load the entire library if you just want to use a couple of its tags. The most commonly-used tags are found in the Core sub-library, which we can load using this @taglib directive immediately following the @page directive at the top of the file:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

Here’s the first piece of Java code in our todo.jsp file. We use it to get the context path (the root) of our web application, so that we can locate the CSS file to be used by the page:

  <link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/styles.css" />

For example, if our web application is installed in http://www.example.com/todo, then the context path for the application is /todo and therefore our style sheet will be correctly located at /todo/styles.css.

The <c:url> tag of the JSTL Core library lets us produce URLs relative to the context path automatically. Here’s how the adjusted code looks:

  <link rel="stylesheet" type="text/css" href="<c:url value="/styles.css"/>" />

Yes, you read right. That’s a JSTL tag within the attribute value of an HTML tag. XML sticklers may grit their teeth at this, but JSP was never meant to be valid XML. For XHTML standards compliance, you just need to make sure that the code generates valid XML, which this will.

The next chunk of Java code in our todo.jsp file is a little more challenging. It grabs the List object that the controller stored in a request object attribute called toDoItems, and checks if it contains any to-do items:

  <%      
 List toDoItems = (List)request.getAttribute("toDoItems");      
 Iterator it = toDoItems.iterator();      
 if (it.hasNext()) {      
   %>

The <c:if> tag lets us test a condition and output the contents of the tag only when that condition is true. The tag looks like this:

  <c:if test="<i>condition</i>">...</c:if>

But how do we specify a condition? That’s where JSP Expression Language (EL) comes in. The test attribue of the <c:if> tag takes an EL expression as the condition to be tested.

EL was designed specifically to be really, really good at fetching values out of request, session, and application attributes. As a matter of fact, the EL expression that will fetch the toDoItems request attribute is simply this:

${toDoItems}

For our purposes, we actually want to go a step further and check how many items are in the toDoItems list. To do this, we need to use an EL function, which requires another JSTL sub-library to be added with a @taglib directive at the top of the page:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

With that done, we can get the number of items in the list with this EL expression:

${fn:length(toDoItems)}

And we can determine if the list contains items with this expression:

${fn:length(toDoItems) > 0}

We can now write the <c:if> tag to test this condition:

  <c:if test="${fn:length(toDoItems) > 0}">...</c:if>

Next, we’ll use JSTL not to replace some Java design logic, but to improve some pure HTML in our todo.jsp file. The form that displays the to-do list items and allows the user to delete them begins with this <form> tag:

    <form action="DeleteItem.do" method="post"></form>

This is just fine as long as our JSP is in the root directory of our web application, but if we were to move it into a subdirectory, the action attribute of this tag would no longer point to DeleteItem.do in the root of the application. To ensure this attribute always points to the correct URL, we can use a <c:url> tag just like we used for the style sheet URL above:

    <form action="<c:url value="/DeleteItem.do"/>" method="post">

Incidentally, we can make the same change to the second <form> tag on the page, which points to AddItem.do.

The next piece of Java display logic in todo.jsp is a bit trickier to reproduce with JSTL/EL:

      <select name="deleteid" size="<%= Math.max(2, toDoItems.size()) %>">

There is no JSTL or EL equivalent to Java’s Math.max method, so to get a <select> list with a size equal to the number of items in toDoItems, but no less than 2, using only standard JSTL/EL features, we would need to implement this logic more verbosely:

      <c:set var="selectSize" value="${fn:length(toDoItems)}"/>      
     <c:if test="${selectSize < 2}">      
       <c:set var="selectSize" value="2"/>      
     </c:if>

The JSTL <c:set> tag lets us set a variable for use in EL expressions in the rest of the page. In this case, we’d set it to the number of items in toDoItems (which we’d again get with the fn:length EL function). We’d then use a <c:if> to test if the value was less than 2, in which case we’d use another <c:set> to set the variable to that minimum.

We could then go ahead and output the value with an expression in our <select> tag’s size attribute:

      <select name="deleteid" size="${selectSize}">

Yes — you can use EL expressions in HTML tag attributes too.

This solution would be pretty messy, though. Wouldn’t it be nice if we had an EL function that did the same thing as Math.max? As it turns out, extending EL with your own functions is pretty easy.

First, you need to create a Java class with a public, static method that does what you want your EL function to do. For this project, let’s create a class called com.sitepoint.jsp.Functions (in com/sitepoint/jsp/Functions.java). The code for this class will be very simple:

package com.sitepoint.jsp;      
     
public class Functions {      
 public static int max(int i1, int i2) {      
   return Math.max(i1, i2);      
 }      
}

Next, we need to define a custom tag library to set this class’s max method as a custom EL function. To do this, create an XML file called functions.tld and put it in the WEB-INF directory of the project. Aside from the first tag (which is always the same), most of the code is fairly self-explanatory:

<?xml version="1.0" encoding="iso-8859-1"?>      
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"      
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"      
   version="2.0">      
 <tlib-version>1.0</tlib-version>      
 <short-name>Functions</short-name>      
 <uri>http://www.sitepoint.com/jsp/taglibs/functions</uri>      
 <function>      
   <name>max</name>      
   <function-class>com.sitepoint.jsp.Functions</function-class>      
   <function-signature>int max(int, int)</function-signature>      
 </function>      
</taglib>

What this file does is associate a unique identifier, in the form of a URL (http://www.sitepoint.com/jsp/taglibs/functions), with a library of EL functions. The one function in this library will be called max and will call the max method of the com.sitepoint.jsp.Functions class.

To use this library in our JSP, we need to add a @taglib directive for it to the top of the page:

<%@ taglib prefix="spfn" uri="http://www.sitepoint.com/jsp/taglibs/functions" %>

We can now calculate the size attribute of our <select> tag using a single EL expression:

      <select name="deleteid" size="${spfn:max(2,fn:length(toDoItems))}">

Next up in our Java display logic, we have a while loop that iterates through the to-do list items, pulling each out in turn to be processed:

        <%      
       while (it.hasNext()) {      
         ToDoItem toDoItem = (ToDoItem) it.next();      
         %>

This is almost shamefully simple to do with JSTL’s <c:forEach> tag:

        <c:forEach var="toDoItem" items="${toDoItems}">

Again, we’re using the simple EL expression ${toDoItems} to access the request attribute supplied by the controller. This tag will output its contents once for each item in the list, assigning that item to the EL variable name specified by the var attribute (toDoItem, in this case).

Our final tidbits of Java display logic are used to output the ID and text of the ToDoItem objects contained in the list:

          <option value="<%= toDoItem.getId() %>"><%= HTMLEscaper.escape(toDoItem.toString()) %></option>

Here’s where EL really comes into its own. In addition to simplifying drastically the process of pulling values out of request attributes, it’s also really good at pulling values out of those values! Let me show you what I mean…

Although I didn’t mention it at the time, the ToDoItem class was designed according to the JavaBeans standard. Though it has some more complicated sections, the JavaBeans specification (not to be confused with Enterprise JavaBeans — a completely different spec) is mainly just a naming convention for classes and methods.

Under the JavaBeans spec, if an object has a property (a value that can be read and written), then it should have getPropertyName and setPropertyName methods to access it. If it’s a read-only property, then it should only have a getPropertyName method. If the property contains a boolean value, then the ‘get’ method should be called isPropertyName instead.

There’s a lot more to the spec than that, but those are the bare essentials. Since the ToDoItem class has a getId method, it has a read-only property named id.

The point of all this is that EL is JavaBeans-savvy: EL makes it really easy to get values of JavaBean properties. So, to output the value of a ToDoItem‘s id property, we can use this expression:

${toDoItem.id}

As for the text value of the ToDoItem, EL will automatically convert any object to a String using its toString method, so we could just use ${toDoItem}. Our Java code, however, also uses the HTMLEscaper class to escape any characters that might be interpreted as HTML code. But wait: JSTL/EL can do that, too!

Actually, there are two ways to escape HTML special characters with JSTL/EL. The first is to use the JSTL <c:out> tag with the escapeXml attribute:

<c:out value="${toDoItem}" escapeXml="true"/>

Even more convenient is the EL function fn:escapeXml:

${fn:escapeXml(toDoItem)}

Here’s how to output our to-do list items in our new todo.jsp file:

          <option value="${toDoItem.id}">${fn:escapeXml(toDoItem)}</option>

Since we’re no longer using the HTMLEscaper class, we can remove the relevant files from our web application. We can also remove the @page directive that imported this and the other classes that were used by our Java display logic code: no Java code, no imports needed!

With all those changes made, our finished todo.jsp file looks like this:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>      
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>      
<%@ taglib prefix="spfn" uri="http://www.sitepoint.com/jsp/taglibs/functions" %>      
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"      
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">      
<html xmlns="http://www.w3.org/1999/xhtml">      
<head>      
 <title>To-Do List</title>      
 <meta http-equiv="content-type"      
     content="text/html; charset=iso-8859-1" />      
 <link rel="stylesheet" type="text/css"      
     href="<c:url value="/styles.css"/>" />      
</head>      
<body>      
 <c:if test="${fn:length(toDoItems) > 0}">      
   <form action="<c:url value="/DeleteItem.do"/>" method="post">      
     <select name="deleteid" size="${spfn:max(2,fn:length(toDoItems))}">      
       <c:forEach var="toDoItem" items="${toDoItems}">      
         <option value="${toDoItem.id}">${fn:escapeXml(toDoItem)}</option>      
       </c:forEach>      
     </select>      
     <input type="submit" value="Delete Selected Item"/>      
   </form>      
 </c:if>      
 <form action="<c:url value="/AddItem.do"/>" method="post">      
   <input type="text" name="newtodo"/>      
   <input type="submit" value="Add New Item"/>      
 </form>      
</body>      
</html>

Though certainly new, the JSTL/EL syntax in this file will be a lot easier for your average web designer to grasp than the Java code that was there previously!

Here’s the file and directory structure of our updated application:

/todo.jsp      
/styles.css      
/WEB-INF/functions.tld      
/WEB-INF/web.xml      
/WEB-INF/classes/com/sitepoint/AddToDoServlet.class      
/WEB-INF/classes/com/sitepoint/AddToDoServlet.java      
/WEB-INF/classes/com/sitepoint/DeleteToDoServlet.class      
/WEB-INF/classes/com/sitepoint/DeleteToDoServlet.java      
/WEB-INF/classes/com/sitepoint/ToDoItem.class      
/WEB-INF/classes/com/sitepoint/ToDoItem.java      
/WEB-INF/classes/com/sitepoint/ToDoList.class      
/WEB-INF/classes/com/sitepoint/ToDoList.java      
/WEB-INF/classes/com/sitepoint/ToDoServlet.class      
/WEB-INF/classes/com/sitepoint/ToDoServlet.java      
/WEB-INF/classes/com/sitepoint/jsp/Functions.class      
/WEB-INF/classes/com/sitepoint/jsp/Functions.java      
/WEB-INF/lib/jstl.jar      
/WEB-INF/lib/mysql-connector-java-version-bin.jar      
/WEB-INF/lib/standard.jar

Download the code. (759KB)

As far as JSP best practices go, this updated to-do list example is about as good as you’re gonna get by following the official specs. And, admittedly, we’ve got a pretty powerful web application platform happening here. You could certainly build sizeable applications using nothing but Java classes for the model, Java servlets for the controller, and JSPs using JSTL/EL for the view, but there are more powerful options out there.

Instead of hand-coding database access in your model classes, you can use a persistence framework to synchronize your database with a set of auto-generated Java objects automatically. Hibernate is the darling of the day in this area, though EJB 3.0 is on the horizon with all the same benefits in a standardized package.

Instead of writing all of your application logic as a twisty set of servlets, you can use a web application framework like Struts, WebWork, Tapestry or Stripes to manage the complexity.

Instead of relying on JSTL tags and EL expressions enhanced with your own custom functions, you can use other tag libraries like JavaServer Faces or one of the many open source taglibs, or you can step away from JSP and use a templating system like Velocity or XMLC.

You could almost say that there are more ways to build web applications with Java than without it! Be sure to follow The Daily Grind, SitePoint’s Java blog, as I explore these many options, and watch sitepoint.com for more articles to help you discover the joys of Java web development.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Guest

    Where are the other pages (1..6) gone??

    • http://onsman.com/ ronsman

      The rest of the article was hidden by some broken code. Fixed now. Of course, only you and I know that, Guest. I could deny everything. What “other pages?”, I could say. Who’d take the word of an anonymous guest called Guest? Hmm?