ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

JSP 2.0: The New Deal, Part 1
Pages: 1, 2

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.