Home > Articles > Programming > Java

  • Print
  • + Share This
This chapter is from the book

2.10 Common Mistakes

All languages have their idiosyncrasies and pitfalls to avoid, and the JSTL expression language is no different. This section discusses some common mistakes that you are apt to make repeatedly. Once you are aware of them, it's easier to avoid them. Here are five of the most common JSTL expression language mistakes:

  1. Forgetting curly braces

  2. Forgetting taglib declarations

  3. Neglecting to store variables in a scope

  4. Using illegal characters for attribute names

  5. Inadvertently using implicit objects

Forgetting Curly Braces

When you first start using the expression language, it can take awhile to remember to use the dollar sign and the curly braces for your expressions. Just as important, it can take awhile for expressions to look odd when the curly braces have been omitted. Here's a classic example:

<c:if test='counter.count == 1'>
   <%-- Do something the first time... --%>
</c:if>

The expression specified for the <c:if> test attribute will always evaluate to false because the value is a string that does not equal "true".19 Instead, you need to do this for the comparison to work:

<c:if test='${counter.count == 1}'>
   <%-- Do something the first time... --%>
</c:if>

Forgetting taglib Declarations

Even if you haven't yet read the Iteration Actions chapter in this book, you probably have a good idea what the following code fragment does:

<c:forEach var='item' begin='1' end='10'>
   <c:out value='${item}'/>
</c:forEach>

At first glance, it looks as though the preceding code fragment will print values from 1 to 10, inclusive; however, that's not necessarily the case. If you forget the taglib directive for the JSTL core actions, the preceding code fragment will do nothing.

To make sure that the preceding code works as you expect, you need to remember the taglib directive, like this:

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

<c:forEach var='item' begin='1' end='10'>
   <c:out value='${item}'/>
</c:forEach>

Neglecting to Store Variables in a Scope

Although it's not recommended for production code, it is not uncommon for developers to create some temporary objects in a scriptlet that act as placeholders for data that will eventually come from another source; for example, you can create a hash map in a scriptlet that you can subsequently access with an EL expression, like this:

<%
   java.util.HashMap map = new java.util.HashMap();
   map.put("key One", "value One");
   map.put("key Two", "value Two");
   map.put("key Three", "value Three");
   map.put("key Four", "value Four");
   map.put("key Five", "value Five");
%>

<c:out value='${map["key One"]}'/>

You may think that the preceding code fragment will display the value of the first entry added to the map, but in actuality, it will display nothing at all because the map created in the scriptlet was never stored in one of the JSP scopes.

Once the map is placed in one of the JSP scopes, it can be accessed with an EL expression. Here is the corrected code fragment:

<%
   java.util.HashMap map = new java.util.HashMap();
   map.put("key One", "value One");
   map.put("key Two", "value Two");
   map.put("key Three", "value Three");
   map.put("key Four", "value Four");
   map.put("key Five", "value Five");

   pageContext.setAttribute("map", map);
%>

<c:out value='${map["key One"]}'/>

You can iterate over the items stored in the map created above like this:

<c:forEach var='item' items='${map}'>
   <c:out value='Key=${item.key}, Value=${item.value}'/>
</c:forEach>

Using Illegal Characters for Attribute Values

The preceding code fragment will print the key and value for each entry in a map. The following code, however, will not do the same:

<%-- The name an-item is not legal, so this produces no output --%>
<c:forEach var='an-item' items='${map}'>
   <c:out value='Key=${an-item.key}, Value=${an-item.value}'/>
</c:forEach>

The preceding code fragment will not produce any output because the name chosen for the scoped variable created by <c:forEach> is not a valid Java identifier—because it contains a dash—and therefore the preceding code will fail silently.

Inadvertently Using Implicit Objects

One final word of caution. Be careful that you don't inadvertently use the names of the JSTL implicit objects; for example, the following code fragment displays all of the request parameters, similar to the example discussed in "Accessing Request Parameters" on page 65:

<html>
   <head>
      ...
   </head>

   <body>
      <%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %>
      ...
      <%-- For every String[] item of paramValues... --%>
      <c:forEach var='parameter' items='${paramValues}'> 
         <ul>
            <%-- Show the key, which is the request parameter
                 name --%>
            <li><b><c:out value='${parameter.key}'/></b>:</li>
            <%-- Iterate over the values -- a String[] -- 
                 associated with this request parameter --%>
            <c:forEach var='value' items='${parameter.value}'>
               <%-- Show the String value --%>
               <c:out value='${value}'/>   
            </c:forEach>
         </ul>
      </c:forEach>
      ...
   </body>
</html>

The preceding code fragment works as advertised, but if you make this seemingly innocuous change—

...
<c:forEach var='param' items='${paramValues}'> 
   <ul>
      ...
      <li><b><c:out value='${param.key}'/></b>:</li>
      ...
      <c:forEach var='value' items='${param.value}'>
         ... 
      </c:forEach>
   </ul>
</c:forEach>
...

—the preceding code fragment will not work like the previous code fragment because param is an implicit object, not the current object of the iteration.

  • + Share This
  • 🔖 Save To Your Account