Java - - By Kevin Yank

The Grand Tour: A crash course in Java-less JSP

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

In the last instalment of my “Grand Tour” of Java Web application technology, we 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 separation 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.

This time around, I’ll show you how to get rid of the Java code in 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, display logic is needed 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 latter:

<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, 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 written by various groups floating around the Web. From simple JSP tag libraries (collections of custom tags that you can mix in 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, however, 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).

While EL is built into JSP 2.0, and is therefore available automatically in your JSP files, JSTL is a separate library that must be specifically 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 in the audience 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.

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 then checks if it actually 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 only output the contents of the tag 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 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 set it to the number of items in toDoItems (which we again get with the fn:length EL function). We then use a <c:if> to test if the value is less than 2, in which case we use another <c:set> to set the variable to that minimum.

We can 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 is pretty messy, though. Wouldn’t it be nicer 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 dead simple:

package com.sitepoint.jsp;

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

Next you 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 pretty 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 drastically simplifying 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.

Now the point of all this is that EL is JavaBeans-savvy. It makes it really easy to get values of JavaBean properties. So to output the value of a ToDoItem’s id property, we can just 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, was also using 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)}

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

Instead of writing all of your application logic as a twisty set of servlets, you can use a Web application framework like Struts 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! In the coming months, I’ll look at many of these options with a critical eye and try to advise you on which to use for what sort of project.

Sponsors