ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


PC Hardware in  Nutshell, 2nd Edition

JSP 2.0: The New Deal, Part 1

by Hans Bergsten, author of JavaServer Pages, 3rd Edition
11/05/2003

The wait is almost over: the latest version of the JavaServer Pages (JSP) specification, JSP 2.0, is about to be released, along with all of the other J2EE 1.4 specifications. The jump to a new major revision for this JSP version signifies that all of the pieces are now in place for using JSP in a new way: there's no need for Java in the pages, thanks to the new Expression Language (EL) and the JSP Standard Tag Library (JSTL), and reusing code is much easier, thanks to two new ways to develop custom actions. More specifically, JSP 2.0 brings you all of these goodies:

Related Reading

JavaServer Pages
By Hans Bergsten

This article is the first in a series of articles describing all of these new JSP 2.0 features. In this part, we'll look at the EL-related news, saving the other features for future installments. I have assumed that you're familiar with JSP 1.2 and have at least heard about the JSP Standard Tag Library (JSTL).

You may also be interested in the third edition of my JavaServer Pages book, where I describe all of this in much more detail and don't assume that you know anything about JSP or JSTL. The book is scheduled for release in December 2003, but you can pre-order it now at Amazon.com, Barnes & Noble, and other online and brick-and-mortar bookstores.

The Expression Language

If you've used JSTL, you're already familiar with the JSP Expression Language. The EL was introduced in the JSTL 1.0 specification to provide an alternative to Java expressions for assigning values to action element attributes at runtime. While the JSTL EL has quickly become very popular, there's a problem: JSTL EL expressions only works with JSTL actions and with custom actions specifically crafted to know how to evaluate EL expressions using non-standard APIs.

Starting with JSP 2.0, the JSP container itself understands EL expressions, making it possible to use them in all places where you previously could only use Java expressions: as the value of attributes for standard and custom actions, and directly in template text.

Before we look at concrete examples, let's take a closer look at what the EL is. The EL is a language inspired by JavaScript, and to some extent, XPath (a language used to access pieces of an XML document), but the EL is much more forgiving about variables without a value (null) and performs more data-type conversions automatically. These features are important for a web application, where the input is mostly in the form of request parameters. The parameters may be present in some requests but not in others, and the browser always sends request parameters as text values, while the application often needs to use them as numbers or Boolean values (true or false). The way the EL is designed, you rarely need to worry about absent values or type conversion at all.

An EL expression contains variables and operators. Any bean stored in one of the JSP scopes (page, request, session, or application) can be used as an EL variable. In addition, the EL supports the following implicit (predefined) variables:

Variable name Description
pageScope A collection (a java.util.Map) of all page scope variables.
requestScope A collection (a java.util.Map) of all request scope variables.
sessionScope A collection (a java.util.Map) of all session scope variables.
applicationScope A collection (a java.util.Map) of all application scope variables.
param A collection (a java.util.Map) of all request parameter values as a single String value per parameter.
paramValues A collection (a java.util.Map) of all request parameter values as a String array per parameter.
header A collection (a java.util.Map) of all request header values as a single String value per header.
headerValues A collection (a java.util.Map) of all request header values as a String array per header.
cookie A collection (a java.util.Map) of all request cookie values as a single javax.servlet.http.Cookie value per cookie.
initParam A collection (a java.util.Map) of all application initialization parameter values as a single String value per parameter.
pageContext An instance of the javax.servlet.jsp.PageContext class, providing access to various request data.

Operators describe what you want to do with the variables. The operators you can use in an EL expression probably look familiar to you if you've used any programming language before, because they are the same as those supported by most languages:

Operator Description
. Access a bean property or Map entry.
[] Access an array or List element.
() Group a subexpression to change the evaluation order.
? : Conditional test: condition ? ifTrue : ifFalse.
+ Addition.
- Subtraction or negation of a value.
* Multiplication.
/ or div Division.
% or mod Modulo (remainder).
== or eq Test for equality.
!= or ne Test for inequality.
< or lt Test for less than.
> or gt Test for greater than.
<= or le Test for less than or equal.
>= or ge Test for greater than or equal.
&& or and Test for logical AND.
|| or or Test for logical OR.
! or not Unary Boolean complement.
empty Test for an empty variable value: null, an empty String, or an array, Map, or Collection without entries).
func(args) A function call, where func is the function name and args is zero, one or more comma-separated function arguments.

An EL expression can also include literals: numbers, text (within single or double quotes), Boolean values and null.

Because an EL expression can appear in many places where static text can also appear, you must tell the JSP container that it should treat an EL expression as such. You do this using delimiters. An EL expression always starts with the ${ delimiter (a dollar sign and a left curly brace) and ends with } (a right curly brace). Here's an EL expression that adds 5 to a variable named amount:

${amount + 5}

If you want to add 5 to the value of a bean property, you use the property access operator:

${order.amount + 5}

The property accessor operator (the dot) tells the EL to look for the named property (amount, in this case) in the specified bean or collection (order, in this case, which can be either a bean or a java.util.Map).

As an alternative, you can use the array element access operator:

${order['amount'] + 5}

The value within the brackets must be either a string literal for the name of the property (as in this example) or a variable (or even a complete EL subexpression) that holds the name of the property.

EL expressions can be used to assign values to any standard or custom JSP action attributes marked as accepting a dynamic value (or request-time attribute value, as it's formally called):

<c:out value="${order.amount + 5}"/>

Prior to JSP 2.0, you had to use a Java expression to assign a dynamic value to an attribute, which has been a common source of confusing syntax errors over the years.

Finally, EL expressions can be mixed with template text directly in the page. This comes in very handy when you're generating HTML elements and need to set an attribute to a dynamic value:

<input name="firstName" value="${customer.firstName}">

With JSP 1.2, you had to use JSTL's <c:out> action to accomplish the same thing, ending up with a mix of elements of different types that was hard to understand:

<input name="firstName" 
    value="<c:out value="${customer.firstName}"/>" >

New JSTL 1.1 Tag Library Identifiers

JSTL 1.1 is a minor specification release, primarily intended to align JSTL with JSP 2.0. The most visible change is that the JSTL 1.0 "twin libraries" (one set of libraries that accepts EL expressions and one set that accepts Java expressions) have been replaced with a single set of libraries that can be used with either EL expressions or Java expressions.

You use the following identifiers for the new JSTL 1.1 libraries:

Library URI Prefix
Core http://java.sun.com/jsp/jstl/core c
XML processing http://java.sun.com/jsp/jstl/xml x
I18N formatting http://java.sun.com/jsp/jstl/fmt fmt
Database access http://java.sun.com/jsp/jstl/sql sql
Functions http://java.sun.com/jsp/jstl/functions fn

If you've used JSTL 1.0, you may notice that the new identifiers are the same as the old EL library identifiers, except that a new /jsp path element has been added for all of them. You may also notice that there's a brand library in JSTL 1.1, containing EL functions. We'll look at these shortly.

A New Expression Language Operator

A very common need in a JSP page is to include a piece of template text only if a certain condition is true. With JSP 1.2 and JSTL 1.1, this is typically done using a <c:if> block, but that's a very verbose solution. JSP 2.0 adds a new conditional operator to the EL to deal with this case in a more elegant way.

The conditional operator exists in many programming languages (for instance, in Java, C, and JavaScript), so you may have seen it before. It takes a Boolean condition and one result to use if the condition is true and another if it's false. An example makes it clear how it works:

<select name="artist">
<option value="1" ${param.artist == 1 ? 'selected' : ''}>
Vesica Pisces
<option value="2" ${param.artist == 2 ? 'selected' : ''}>
Cortical Control
<option value="3" ${param.artist == 3 ? 'selected' : ''}>
Vida Vierra
</select>

Here, I use EL expressions with the conditional operator to set the selected attribute only for the option in a select list that matches the submitted value. If the condition (param.artist == 1) is true, the first result ('selected') is added to the page; otherwise, the second result (the empty string) is added.

Expression Language Functions

When the EL moved from the JSTL specification to the JSP specification, it picked up a new trick: namely, how to invoke functions. The EL function syntax is simple: the function name, followed by a list of arguments within parenthesis:

<%@ taglib prefix="fn"
uri="http://java.sun.com/jsp/jstl/functions" %>
${fn:length(myCollection)}

A function belongs to a tag library and the function name includes the prefix assigned to the library with the taglib directive in the page. In this example, I use the prefix fn, which is the default prefix for the JSTL function library.

The Tag Library Descriptor (TLD) maps the function name to a static method in a Java class that implements the functionality:

<function>
<description>
Returns the number of items in a collection or the number of
characters in a string.
</description>
<name>length</name>
<function-class>
org.apache.taglibs.standard.functions.Functions
</function-class>
<function-signature>
int length(java.lang.Object)
</function-signature>
</function>

The most interesting element here is the <function-signature> element. It contains a declaration of the type of value the function returns, the name of the static implementation method, and type declarations for all arguments (zero or more, comma-separated) within parenthesis. The return type and the argument types must be either Java primitive types or fully qualified type names.

The static method for the length() function is implemented like this in the Jakarta Taglibs Standard library:

public static int length(Object obj)
throws JspTagException {
if (obj == null)
    return 0;
if (obj instanceof String)
    return ((String)obj).length();
if (obj instanceof Collection)
    return ((Collection)obj).size();
if (obj instanceof Map)
    return ((Map)obj).size();

int count = 0;
if (obj instanceof Iterator) {
    Iterator iter = (Iterator) obj;
    count = 0;
    while (iter.hasNext()) {
        count++;
        iter.next();
    }
    return count;
}
if (obj instanceof Enumeration) {
    Enumeration enum = (Enumeration) obj;
    count = 0;
    while (enum.hasMoreElements()) {
        count++;
        enum.nextElement();
    }
    return count;
}
try {
    count = Array.getLength(obj);
    return count;
} catch (IllegalArgumentException ex) {}
throw new JspTagException("Unsupported type"));
}

As you see, there's nothing strange going on here. It's a regular static method that finds out the length its argument using an approach suitable to the specific runtime type of the argument.

Besides the length() method used as an example here, the JSTL 1.1 function tag library contains lots of other commonly needed functions:

Function Description
fn:contains(string, substring) Returns true if the string contains the substring.
fn:containsIgnoreCase(string, substring) Returns true if the string contains the substring, ignoring case.
fn:endsWith(string, suffix) Returns true if the string ends with the suffix.
fn:escapeXml(string) Returns the string with all characters that have special meaning in XML (and HTML) converted to their equivalent XML character entity code.
fn:indexOf(string, substring) Returns the index for the first occurrence of the substring in the string.
fn:join(array, separator) Returns a string composed from the array elements, separated by the separator.
fn:length(item) Returns the number of elements in the item (if it's an array or collection), or the number of characters (if it's a string).
fn:replace(string, before, after) Returns a string where all occurrences of the before string have been replaced with the after string.
fn:split(string, separator) Returns an array where the elements are the parts of the string that are separated by the separator.
fn:startsWith(string, prefix) Returns true if the string starts with the prefix.
fn:substring(string, begin, end) Returns a part of the string, starting from the begin index up to and including the end index.
fn:substringAfter(string, substring) Returns the part of the string that follows the substring.
fn:substringBefore(string, substring) Returns the part of the string that precedes the substring.
fn:toLowerCase(string) Returns a string with all characters from the input string converted to lower case.
fn:toUpperCase(string) Returns a string with all characters from the input string converted to upper case.
fn:trim(string) Returns a string with all leading and trailing whitespace characters in the input string removed.

Conclusion

In this article, I've covered the EL migration to the JSP specification, the new EL features, and the JSTL 1.1 function library. In upcoming installments, I'll tell you about JSP error-page improvements, the benefits of the jsp:id attribute, the new deployment descriptor format, how JSP 2.0 makes it easier to use JSP for XML, and the new features related to custom tag libraries.

If you want to try out the new JSP 2.0 features, I recommend that you use Apache Tomcat 5, one of the first JSP containers to implement the new specification. A version labeled as "stable" can't be released until the final version of the specification is published, but the latest beta versions have proved to be very stable, regardless of the beta label. Tomcat 5 is available at the Jakarta Project site.

Hans Bergsten is the founder of Gefion Software and author of O'Reilly's JavaServer Pages, 3rd Edition.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.