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.

Replay

Category: java Time: 2005-05-22 Views: 2
Tags:

Related post

  • The Grand Tour: Kickin' It MVC Style 2005-01-14

    January is turning out to be a pretty light month for Java news. Oh well, more time to continue my grand tour of Java Web development! Still following along? Last time, I showed you how to convert a "to-do list" servlet into a JSP. Unfortunately

  • The Grand Tour: Old School JSP 2005-01-01

    Thought I was gone, didn't you? December was a crazy month for me, so I had to put this blog on hold, but with the new year comes new priorities, and I'm back to serve you, the Java-hungry hordes. First up this year, another step along the path to un

  • The Grand Tour: Servlets 2004-11-05

    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

  • What is the "crash course" for taking picture of pregnant woman? 2011-08-07

    My friends are expecting their first baby. They asked me if I could do the shots of their "expectancy". I'm a hobbyist photographer. I mostly enjoy taking shots of landscape and architecture and I'm not much into people. What would be the crash

  • A Crash Course in Django 2009-12-22

    Are you after a web framework that drastically cuts the time it takes to build data-driven web apps? If so, the Python-based Django might be worth investigating. With a unique architecture enabling extensive code reuse and an automatic admin system,

  • FreeBSD crash course for a Debian administrator? 2010-09-20

    Can someone please post a quick FreeBSD administration crash course, targeted at a Debian administrator? The environment is a production web server. Some things I'd like to know: package management (ports or pkg_*) ? pros/cons vs. aptitude ? upgradin

  • How to restore the window of tabs crashed 1 day ago in Google Chrome 2011-02-11

    How do you restore the window of tabs crashed 1 day ago in Google Chrome? if I have used another window of many tabs in Chrome for 1 day. --------------Solutions------------- I created a pure web-app that deals with the problem of session restore. (m

  • Is the synchronized keyword,still used/needed in java? 2011-04-14

    Is the synchronised keyword still required (ignore backwards compatibility, I'm thinking in terms of writing new code, today) or should we all be using the features available in the Concurrent and Collection packages? --------------Solutions---------

  • 24 hour crash course in ZFS- some final questions 2012-02-01

    Due to various circumstances I've given myself a crash course on the ZFS file sytem. I need some help getting comfortable with the unknowns. Whatever those are. Data: Running www.zfsonlinux.org on CentOS 6.2 I have an array with 12x2TB sata disks. I

  • Which topics are essential for a crash course in QGIS? 2012-09-14

    What topics do you think are essential in a 25-hour "crash course" introduction for Quantum GIS? What topics do you think are nice extras to be included in such a course? Target audience: Zero or rudimentary knowledge in mapping and geospatial s

  • Load Testing Crash Course 2013-03-08

    Can someone point me at a good resource to get a crash course in load testing. I have a sql server machine that I need to load test but I havent been thruogh the process before. Also we do not have any third party software for this or money to purcha

  • What is the benefit of switching on Strings in Java 7? 2013-11-16

    When I was starting to programme in Java, the fact that switch statements didn't take strings frustrated me. Then on using Enums, I realised the benefits that you get with them rather than passing around raw values - type safety (which brings easier

  • Emergency crash course on LaTeX 2013-11-28

    So, I wrote a document in LaTeX. Someone who doesn't know LaTeX and is a very busy person now has to edit it. Is there a crash course in LaTeX document? Aside from saying 'Ignore everything that starts with \'? Like a one page \textit means italic, %

  • Crash course in using linux 2014-09-18

    Crash course assuming you've just installed a distro and logged in as root. Basic knowledge required to navigate around a linux system, and learn more. I've spent only a few hours in total playing with linux, so an expert may formulate a better crash

  • Does it make sense to use the term "Space Leak" with regard to Java? 2015-12-30

    EDIT: To clarify, I am not suggesting that leaks don't happen in a managed application. I'm simply pondering about how we talk about them. There are some highly upvoted discussions about memory leaks and Java that contain flame wars with 'fanboy' slu

  • Android App Crash and no java error log 2016-01-28

    My Application is a music play and bluetooth control App, Today, A crash happened.I'm sure I know how to use logcat. I searched the logcat and cant find anything about java code error. I post the log what I find. 01-28 15:57:59.772 9218-9229/com.exam

  • Website Promotion Crash Course 2002-03-06

    If, after my last article, you've gone out and paid good money for a company Website, be it to a professional design firm or not, the next stage is to make sure that people know where it is, and why they should visit. Many small-medium sized companie

  • How to change the text of a 'Label' field in java fx at runtime? 2008-10-20

    What are Null Pointer Exceptions (java.lang.NullPointerException) and what causes them? What methods/tools can be used to determine the cause so that you stop the exception from causing the program to terminate prematurely? --------------Solutions---

  • What is the difference between Serializable and Externalizable in Java? 2009-05-03

    What is the difference between Serializable and Externalizable in Java? --------------Solutions------------- To add to the other answers, by implementating java.io.Serializable, you get "automatic" serialization capability for objects of your cl

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development

search

Front-end development

Database

development tools

Open Platform

Javascript development

.NET development

cloud computing

server

Copyright (C) avrocks.com, All Rights Reserved.

processed in 5.157 (s). 13 q(s)