Chapter 5. JSP and EL

The previous chapters in this book demonstrated the breadth of JSP technology and introduced some basic techniques of JSP development. The aim thus far has been to provide you with some fast, hands-on experience with the JSP technology. The working examples in these earlier chapters enabled you to try out real JSP code, and see what JSP can be used for in the real world.

Unlike the earlier chapters, this chapter provides a more in-depth exploration of a cornerstone element of the JSP standard: JSP's Expression Language, or EL for short.

In this chapter, you will discover the following:

  • Why EL is an indispensable part of JSP 2.0

  • How to use EL named variables

  • How to perform type conversion and coercion in EL

  • How to handle null values in EL

  • How to work with arithmetic, logical, comparison, and other operators in EL

  • The different ways of accessing members of a collection in EL

  • How to access properties of objects in EL

  • How to access nested object properties in EL

  • How to use implicit objects in EL

  • How to define and access functions in EL

  • How to use a namespace when referencing EL functions

This chapter covers a lot of ground, and includes five separate examples. By the end of the chapter, you should be very familiar with EL, and be comfortable using it in your own applications.

EL and Its Vital Role in JSP

EL was not part of the JSP standard prior to 2.0. One of the main reasons for creating EL was to ensure that presentation-level JSP pages could be created without relying on scripting elements. Chapter 3, "JSP Basics 2: Generalized Templating and Server Scripting," covered the use of scripting elements (typically code written in Java) that are embedded within a JSP page.

The need for scripting elements within JSP is typically driven by the requirements of an application. Major application requirements that demand the use of scripting elements include the following:

  • To provide control-flow for JSP execution

  • To set, and subsequently access, variables that are local to the JSP page

  • To render a value from a complex expression that involves Java objects

  • To access properties of an arbitrary Java object

  • To call methods of JavaBeans or other Java objects

Unfortunately, experience has shown that the use of scripting elements in JSPs makes large projects difficult to maintain over the long term. It also encourages programming practices that may tightly couple the presentation (user interface) of an application to its business logic, reducing its flexibility and scalability. This is a highly undesirable practice in the creation of Web applications and services. Ideally, JSPs should be created free of scripting elements if at all possible.

In order to create a JSP version that can work completely free of scripting elements, it is essential that all five of the application requirements can be satisfied without the use of embedded Java coding. JSP 2.0 satisfies these requirements. The first two items are handled by JSTL (explored in detail in Chapter 6, "JSP Tag Libraries and JSTL"), while the last three requirements are handled by EL.

EL is independent of JSP 2.0. Despite the vital role of EL in JSP 2.0, the use of EL is not exclusive to JSP containers. The EL parser is also not tightly integrated into the JSP parser, but can be detached and reused for other purposes. In fact, EL is incorporated into both Java Server Faces (JSF, a server-side GUI construction kit technology; see Chapter 21, "JavaServer Faces," for more information), and JSTL. Therefore, becoming familiar with EL will save you time when exploring these other technologies.

EL Named Variables

When working with EL (and JSTL), you will frequently work with named variables. Named variables in EL refer to attributes attached to JSP scoping objects. For example, the following EL expression will render the value of the named variable called bearCount:

<b>There are ${bearCount} bears in the cave.</b>

The EL parser will search for the attribute through the various JSP scoping objects in the following order:

  1. Page

  2. Request

  3. Session (if currently valid)

  4. Application

In practice, this is equivalent to a call to the Java PageContext.findAttribute() method. If you are maintaining legacy JSP code with embedded Java, you may see this call. You can consult the JSP Javadocs (API documentation) to see how this method works.

Figure 5-1 illustrates the search for an EL named variable.

Order of search for an EL named variable

Figure 5.1. Order of search for an EL named variable

In Figure 5-1, you can see the search order for an EL named variable: First the set of EL implicit objects is searched for a matching name (EL implicit objects are covered later in this chapter), and then the four scopes. If the named variable is not found, some action may create it.

If the attribute with the specified name cannot be located in any scope, a null value is returned. The null value will render as a "" (empty string) in the output, and will not trigger any error.

Applying EL

As the name implies, the Expression Language works with expressions. It is a programming language used in the construction of expressions. All EL expressions are enclosed in the ${...} notation. The expression is evaluated before the rest of the JSP is evaluated. You can place EL expressions in two places within a JSP:

  • Inline with template data

  • Within attributes of JSP actions, standard or custom

Using EL expressions inline with template data

The most typical use of EL expressions is to render a textual string inline with template data. For example, consider the following JSP fragment:

<b>There are ${5 + 1} bears in the cave.</b>

In this case, the EL expression is placed inline with the HTML template data. At JSP processing time, the expression ${5+1} will evaluate to 6, and be placed at the same position as the original expression. This will result in the following HTML:

<b>There are 6 bears in the cave.</b>

Using EL expressions in attribute values

The other place where you will see EL expressions used is within the attributes of certain tags, including JSTL tags, standard JSP actions, and custom tags.

For example, consider the following JSP fragment using JSTL:

<c:if test="${salary > 100000}">
  <b>Rich cousin!</b><br/>
</c:if>

In this case, the EL expression ${salary > 100000} is used to conditionally render the body of the JSTL tag. It is placed in the test attribute of the <c:if> custom JSTL action. This will cause the EL expression to be evaluated before the JSTL custom action is evaluated. The HTML <b>Rich cousin!</b><br/> will be rendered only if the named variable called salary is greater in value than 100,000.

For example, consider the following JSP fragment featuring the JSTL <c:set> tag:

<c:set var="datetime" val='${dateNow} - ${timeNow}'/>

If the dateNow named variable contains the string "May 1, 2005" and timeNow contains "11:00 AM", then the resulting datetime named variable will contain "May 1, 2005 - 11:00 AM".

As shown in the preceding section, an EL expression can be an arithmetic expression, or an expression featuring a comparison. The following Try It Out section explores some of these EL expressions.

How It Works

The JSP used to generate the output shown in Figure 5-2 is located at <Tomcat Installation Directory>/webapps/ch05/example1/index.jsp. The code in this index.jsp is reproduced here:

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

<html>
<head>
  <title>EL Expression Examples</title>
</head>
<body>
  <h1>EL Expression Examples</h1>

  <h2>Arithmetic Expressions</h2>
  <b>There are ${1 + 2 * 4 - 6 / 2} apples on the table.</b><br/>
  <b>There are
    <fmt:formatNumber pattern="#####"/>${1 + 2 * 4 - 6 / 2}</fmt:formatNumber>
    apples on the table.</b><br/>


  <b>It feels like ${-4 - 8} degrees today.</b><br/>
  <c:set var="myGrade" value="11"/><br/>
  <b>The average grade is ${(myGrade == 10) ? "perfect" : "good"}. </b><br/>
  <b>There are ${23/54} remaining. </b><br/>
  <b>There are ${6 div 2} apples on the table.</b><br/>
  <b>There are ${2003 div 8} apples on the table.</b><br/>
  <b>There are ${2003 mod 8} apples on the table.</b><br/>
  <b>There are ${2003 % 8} apples on the table.</b><br/>

  <h2>Logical Operators </h2>
  <c:set var="guess" value="12"/>
  <b>Your guess is ${guess}.</b><br/>

  <c:if test="${(guess >= 10)  && (guess <= 20)}">
    <b>You're in range!</b><br/>
  </c:if>
  <c:if test="${(guess < 10)  || (guess > 20)}">
    <b>Try again!</b><br/>
  </c:if>

  <c:set var="guess" value="1"/>
  <b>Your guess is ${guess}.</b><br/>

  <c:if test="${(guess >= 10)  and (guess <= 20)}">
    <b>You're in range!</b><br/>
  </c:if>
  <c:if test="${(guess < 10)  or (guess > 20)}">
    <b>Try again!</b><br/>
  </c:if>

  <h2>Comparison Operators </h2>

  4 > '3'   ${4 > '3'}<br/>
  '4' > 3   ${'4' > 3}<br/>
  '4' > '3' ${'4' > '3'} <br/>
  4 >= 3    ${4 >= 3}<br/>
  4 <= 3     ${4 < 3}<br/>
  4 == '4'   ${4 == 4}<br/>
  <h2>empty Operator</h2>
  empty "" ${empty ""}<br/>
  empty "sometext" ${empty "sometext"}<br/>
empty Junk ${empty Junk}<br/>
  empty guess ${empty guess}<br/>

  <h2>Boolean and Null Values</h2>

  <c:set var="StrVar" value="true"/>
  <c:if test="${StrVar}">
    equal!
  </c:if><br/>

  null == null  ${null == null}<br/>
  "null" == null ${"null" == null}<br/>

</body>
</html>

The page consists of many different EL expressions. The highlighted code shows the two major uses of EL expressions in JSP: inline with template data, and within attributes of tags.

The first highlighted line shows the EL expression ${1 + 2 * 4 - 6 / 2} used inline with the HTML template data:

<b>There are ${1 + 2 * 4 - 6 / 2} apples on the table.</b><br/>

The second highlighted line shows the same EL expression in the value attribute of the JSTL <fmt:formatNumber> tag:

<fmt:formatNumber pattern="#####"/>${1 + 2 * 4 - 6 / 2}</fmt:formatNumber>

Operators

The expressions in index.jsp are created using operators available within EL. These operators include the following:

  • Arithmetic operators

  • Logical operators

  • Comparison operators

  • The empty prefix operator

The preceding example contains expressions using every one of these operators. An explanation of these expressions used in the index.jsp file follows.

Arithmetic operators

All the basic arithmetic operators that you are familiar with are available within EL expressions. This includes addition, subtraction, multiplication, division, and modulus. For example, consider this line in index.jsp:

<b>There are ${1 + 2 * 4 - 6 / 2} apples on the table.</b>

This results in the following HTML:

<b>There are 6.0 apples on the table.</b>

Note that operator precedence has caused the multiplication and division to be executed first. Furthermore, the calculation has caused a decimal to appear in the output. You can use the numeric formatting tags in JSTL to eliminate this. For example, the following JSP fragment in index.jsp renders the same result without the decimal point:

<b>There are
<fmt:formatNumber value="${1 + 2 * 4 - 6 / 2}" pattern="#####"/>
apples on the table.</b><br/>

The formatNumber JSTL tag is used to format the numerical output, using a pattern that specifies no decimal point should be displayed. This results in the following output:

<b>There are 6 apples on the table.</b>

Note that the set of JSTL formatting tags must be included with the <taglib> directive at the top of index.jsp:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

This <taglib> directive also associates the namespace fmt with these formatting tags. Formatting tags and JSTL are covered extensively in Chapter 6, "JSP Tag Libraries and JSTL."

The div operator is another way to specify the divide (/) operator, and may be used interchangeably. Therefore, the following two lines are completely equivalent:

<b>There are ${1 + 2 * 4 - 6 div 2} apples on the table.</b>
<b>There are ${1 + 2 * 4 - 6 / 2} apples on the table.</b>

The mod operator, sometimes expressed by using the symbol %, may be used to obtain the remainder after a division. For example, consider the following EL expressions in index.jsp:

<b>There are ${2003 div 8} apples on the table.</b>
<b>There are ${2003 mod 8} apples on the table.</b>
<b>There are ${2003 % 8} apples on the table.</b>

The following code shows the resulting HTML output:

<b>There are 250.375 apples on the table.</b>
<b>There are 3 apples on the table.</b>
<b>There are 3 apples on the table.</b>

You can also work with negative numbers, using the unary operator, as in the following fragment from index.jsp:

<b>It feels like ${-4 - 8} degrees today.</b>

This will result in the following HTML output:

<b>It feels like −12 degrees today.</b>

Floating-point numbers are also supported; the following calculation from index.jsp results in a fractional number:

<b>There are ${23/54} remaining. </b>

This renders the following HTML output:

<b>There are 0.42592592592592593 remaining. </b>

The conditional operator can also be used:

<c:set var="myGrade" value="10"/>
<b>The average grade is ${(myGrade == 10) ? "perfect" : "good"}. </b>

The JSTL <c:set> custom action is used to create a named variable. It is an attribute (by default, created in page scope) called myGrade with the integer value 10. The EL expression will render "perfect" if the grade is 10, or "good" otherwise. If myGrade is 10, as in the case of index.jsp, the following HTML is rendered:

<b>The average grade is perfect. </b>

Logical operators

Logical operators can be used to combine multiple Boolean expressions. The two logical operators supported by EL are && and ||. Alternatively, the textual form and and or may also be used. For example, consider the following JSP segment from index.jsp:

<h2>Logical Operators </h2>
<c:set var="guess" value="12"/>
<b>Your guess is ${guess}.</b><br/>

<c:if test="${(guess >= 10)  && (guess <= 20)}">
  <b>You're in range!</b><br/>
</c:if>
<c:if test="${(guess < 10)  || (guess > 20)}">
  <b>Try again!</b><br/>
</c:if>

The JSTL <c:if> custom action is used to implement a simple "guess the number" game. If the guess is between 10 and 20 inclusive, the message "You're in range!" is printed; otherwise, the player is asked to "Try again!" Because guess in this case is set to 12, the resulting output is as follows:

Your guess is 12.
You're in range!

The following is the same expression, using the textual form of the logical operators:

<c:set var="guess" value="1"/>
<b>Your guess is ${guess}.</b><br/>

<c:if test="${(guess >= 10)  and (guess <= 20)}">
  <b>You're in range!</b><br/>
</c:if>
<c:if test="${(guess < 10)  or (guess > 20)}">
  <b>Try again!</b><br/>
</c:if>

Comparison operators

EL supports the entire range of comparison operators found in most programming languages. Each of the operators has a symbolic form and an abbreviated textual form. The following table enumerates the available operators.

Operator

Alternate Form

Description

>

Gt

Greater than

>=

Ge

Greater than or equal to

<

Lt

Less than

<=

Le

Lesser than or equal to

==

Eq

Equal to

!=

Ne

Not equal to

The following fragment of index.jsp tests some of these comparison operators:

<h2>Comparison Operators </h2>

4 > '3'   ${4 > '3'}<br/>
'4' > 3   ${'4' > 3}<br/>
'4' > '3' ${'4' > '3'} <br/>
4 >= 3    ${4 >= 3}<br/>
4 <= 3     ${4 < 3}<br/>
4 == '4'   $(4 == 4}<br/>

The resulting output is shown here:

4 > '3' true
'4' > 3 true
'4' > '3' true
4 >= 3 true
4 <= 3 false
4 == '4' true

Note that in the previous comparison EL always attempts to convert the type of the data being compared "in the right way." That is, the character data is converted to numeric value before being compared, except in the case where two characters are compared.

XML document validity

The >, >=, <, and <= operators contain the < and > special symbols. These symbols typically need to be escaped if the template text is an XML document. For example, consider the following expression:

<bucketLevel>
  <c:if  test="${appleCount >= 100}">
    full
  </c:if>
</bucketLevel>

The preceding JSP fragment is not valid XML due to the > character in the expression. Instead, you should use the alternate form, as follows:

<bucketLevel>
  <c:if  test="${appleCount ge 100}">
   full
  </c:if>
</bucketLevel>

Using this alternate form enables the gt, ge, lt, and le operators to be used without affecting the validity of the surrounding XML template text.

The empty operator

The empty operator is a prefix operator, meaning that it takes only one single operand on its right. It can be used to test for a null value. For example, consider the following JSP fragment from index.jsp in the previous Try It Out exercise:

<h2>empty Operator</h2>
empty "" ${empty ""}<br/>
empty "sometext" ${empty "sometext"}<br/>
empty Junk ${empty Junk}<br/>
empty guess ${empty guess}<br/>

The resulting output is as follows:

empty Operator
empty "" true
empty "sometext" false
empty Junk true
empty guess false

In the previous example, the empty string "" is considered empty while any other string value is not. A nonexistent variable, Junk, is given a null value in EL. This null value is considered empty when tested with the empty operator. On the other hand, the guess variable exists (used earlier) and therefore is not empty. In other words, depending on the data type of the operand, the empty operator can also be used to test for the conditions shown in the following table.

Operand Data Type

Empty Value

String

""

Any named variable

Null

Array

no elements

Map

no elements

List

no elements

An ambiguity exists if a named variable is tested to be empty, as it can either contain the null value or the empty string "".

Boolean variables and nulls

The following JSP fragment from index.jsp of the previous Try It Out exercise illustrates some interesting conversion properties to Boolean types and working with null values.

<h2>Boolean and Null Values</h2>
<c:set var="StrVar" value="true"/>
<c:if test="${StrVar}">
  equal!
</c:if><br/>

null == null  ${null == null}<br/>
"null" == null ${"null" == null}<br/>

The resulting output is as follows:

equal!
null == null true
"null" == null false

The named variable StrVar is initially set to the string true. This is a variable of type String. However, because the test attribute of the JSTL <c:if> tag requires a Boolean expression, it is automatically converted to a Boolean by EL before use. This causes the printing of the "equal!" message.

Finally, the comparison operator is being used on the special null value. It is shown here that while a null value can be successfully compared to another null value, the string "null" is not considered equal to the null value.

This concludes the coverage of the first example in this chapter. The next section takes a more detailed look at automatic type conversion, encountered earlier.

Coercion: Automatic Type Conversion

Programming in JSP in general, and in EL in particular, tends to be rather weakly typed. It is not necessary to declare the type of a variable before using it. This is rather unlike the Java programming language, where the data type and name of each variable must be declared before use.

The advantage of a weakly typed language such as EL is the ease of programming with it. The JSP/EL developer does not have to worry about declaring every variable used and figuring out the most appropriate type for each variable. Further adding to the ease of programming, the developer usually does not need to call any type of data-type conversion functions. Instead, developers can completely rely on a set of built-in rules, EL's type coercion rules in this case, to take care of type coercion for them.

The disadvantage of a weakly typed approach is that in some programming situations, you may need finer control over the data type conversion outcome. In these cases, you will need to understand different built-in rules and how they may affect the output.

Boxing and unboxing

The basic type conversion is based on boxing. Boxing is simply the action of creating an associated Java object from a primitive type. The following table shows the common Java primitive types and their boxed form.

Primitive Type

Boxed Type

int

Integer

long

Long

double

Double

char

Character

boolean

Boolean

To box an int variable means to wrap it in an Integer. To box a long, wrap it up in a Long instance. The action of converting a wrapped value to its associated primitive value is called unboxing. For example, unboxing a Boolean means obtaining the primitive boolean value from a Boolean instance.

Coercion, or automatic type conversion, occurs when the required type does not match the type of the incoming value/variable. For example, the attribute of a tag may require an Integer value, but the input value is a String. Before this conversion can happen, EL will always box a primitive type. The following sections take a look at the most commonly used coercions to examine what goes on under the hood.

Coercion to a string

Variable values are coerced to a String type as follows:

  1. Box the variable if it is primitive.

  2. Use the toString() method of the wrapping object to obtain the String equivalent.

Note that null values are returned as a null string, "". This ensures that nothing is rendered in the output if the object value is null. An error will result if the call of toString() throws an exception.

Coercion to a number

Number types include short, int, float, double, and their boxed types.

Variables of any type are coerced to number types by first boxing them if necessary; then, follow these steps:

  1. If the type is String, use the valueOf() method to get its value; "" (empty string) will return 0.

  2. If the type is Character, use new Short((short) v.charValue()), assuming the Character variable is called v.

  3. Unbox the variable if necessary.

Null values in this case are returned as 0. If the type is a Boolean, an error will result. Numbers can always be converted successfully among themselves (for example, Integer to Float). If the call to valueOf() throws an exception, it results in an error.

Coercion to a character

Variable values are coerced to Character type by the following rules:

  1. If the type is a Number type, first it is coerced to the type Short; then a Character is returned that is numerically equivalent to the short value

  2. If the type is String, the method charAt(0) is used to obtain the Character. This is essentially the first character of the string.

A null value causes a result of (char) 0. A Boolean incoming type will cause an error.

Best attempt to "do the right thing" without error

It should be clear that the automatic type conversion rules are designed to "do the right thing" in most circumstances. They will always try directing conversion if possible—for example, converting directly between the numeric data types.

Null values will always be converted to trivial type-correct values. For example, a null value for a String type is converted to an empty string, "". Null is converted to 0 for Numeric type, and (char) 0 to Character type. This enables a JSP to render a null value in most cases, without resulting in an error.

The following Try It Out exercise shows this automatic type conversion in action.

How It Works

You can find the JSP that produced the output in Figure 5-3 in <Tomcat Installation Directory>/webapps/ch05/example2/index.jsp. The content of this file is reproduced here:

<%@ taglib prefix="wroxtags" tagdir="/WEB-INF/tags" %>

<html>
<head>
  <title>EL Type Conversion Examples</title>
</head>
<body>
  <h1>EL Type Conversion Examples</h1>

  <wroxtags:CharacterType val="this is it"/>
  <wroxtags:CharacterType val="8"/>
<wroxtags:CharacterType val="3.0001"/>
  <br/>
  <wroxtags:DoubleType val=""/>
  <wroxtags:DoubleType val="-3"/>
  <br/>
  <wroxtags:BooleanType val=""/>
  <wroxtags:BooleanType val="true"/>
  <wroxtags:BooleanType val="t"/>
  <wroxtags:BooleanType val="3.1"/>

</body>
</html>

The custom tags are included in the wroxtags namespace using the initial taglib directive:

<%@ taglib prefix="wroxtags" tagdir="/WEB-INF/tags" %>

All the tags are implemented using the JSP 2.0 tag file mechanism. This allows custom tags to be created using JSP coding. Tags and tag files are covered in Chapter 11, "Building Your Own Custom JSP Tag Library." For now, focus your attention on the type of the tag attribute.

The first tag, <wroxtags:CharacterType>, requires a Character typed val attribute. In the index.jsp code, a String, an int, and a float value are supplied:

<wroxtags:CharacterType val="this is it"/>
<wroxtags:CharacterType val="8"/>
<wroxtags:CharacterType val="3.0001"/>
<br/>

This will trigger the EL coercion. In the case of the String "this is it", the charAt(0) method is used, resulting in a value of 't'. See the earlier section entitled "Coercion to a character" for details. The corresponding output from the tag is as follows:

The Character value is 't'.

In the case of the int 8, the number is boxed into an Integer object and coerced into a Short, and then a Character numerically equal to the Short is returned. The corresponding output from the tag follows:

The Character value is '8'.

In the case of the float 3.001, the number is boxed into a Float object and coerced into Short, and then a Character numerically equal to the Short is returned. The corresponding output from the tag follows:

The Character value is '3'.

The next tag is called <wroxtags:DoubleType> and requires a Double typed attribute. The following JSP code fragment from index.jsp tries to supply the value of various data types:

<wroxtags:DoubleType val=""/>
<wroxtags:DoubleType val="-3"/>
<br/>

The first line supplies an empty string as the value. According to the "Coercion to number" section earlier, an "" (empty string) will result in a numeric value of 0. The resulting output is as follows:

The Double value is 0.0.

The second line supplies an integer value of −3. This Numeric type is boxed and converted to Double, resulting in the following output:

The Double value is −3.0.

The last tag is called <wroxtags:BooleanType> and requires a Boolean typed attribute. The code in index.jsp tries to assign the attribute with values of different data types:

<wroxtags:BooleanType val=""/>
<wroxtags:BooleanType val="true"/>
<wroxtags:BooleanType val="t"/>
<wroxtags:BooleanType val="3.1"/>

If you consult the JSP 2.0 specification, you will find that the coercion uses the Boolean.valueOf() method to obtain the value. The API documentation of this method basically says that only the text string "true" can be coerced into the Boolean value of true. Any other data type (except boolean or Boolean, of course) or value will result in false. Therefore, the following output results from the preceding JSP fragment:

The Boolean value is false.
The Boolean value is true.
The Boolean value is false.
The Boolean value is false.

For completeness, and the more curious readers, the rest of this section examines the tag's source code.

The source code to the tag files can be located at <Tomcat Installation Directory>/webapps/ch05/WEB-INF/tags. The CharacterType.tag file contains the following source code:

<%@attribute name="val" type="java.lang.Character" %>
<b>The Character value is '${val}'.</b><br/>

The DoubleType.tag file contains this source code:

<%@ attribute name="val" type="java.lang.Double" %>
<b>The Double value is ${val}.</b><br/>

The BooleanType.tag file contains this source code:

<%@ attribute name="val" type="java.lang.Boolean" %>
<b>The Boolean value is ${val}.</b><br/>

This concludes our examination of the second Try It Out exercise and EL's automatic type conversions.

The EL named variables refer to scoped attributes. Frequently, these attributes are Java objects or beans that have various properties. Occasionally, an attribute may be a Java collection that can be iterated through to obtain contained values. The following section examines how EL can be used to access properties of Java objects and collections.

Accessing Object Properties and Collections

When using EL to address the properties of a named variable, the "." or "[ ]" (square brackets) operators are used. For example, consider the following JSP fragment:

<b>You must earn ${member.minQual} points to maintain your membership.</b>

If the member named variable refers to a JavaBean, its minQual property is read and substituted. Of course, the property must exist and be readable. The getMinQual() method of the underlying JavaBean will be invoked to obtain the property value.

With EL, the preceding syntax is completely interchangeable with the following:

<b>You must earn ${member["minQual"]} points to maintain your membership.</b>

In addition to JavaBeans, the preceding syntax can also be used to address the following Java object types:

  • Map

  • List

  • Array

For example, the expression ${pointsArray[8]} refers to the ninth element of the pointsArray array.

For a more complex data structure, consider a named variable (a JavaBean) called car that has a property called door, which is in turn a JavaBean that has a property called color that is a String type. The EL expression that accesses the color of the door will be ${car.door.color}. The "." operator can be used to access nested properties in this way.

For another example, consider a named variable (a JavaBean) called newsfeed. This named variable has a property (a Java HashMap) called temp containing world temperatures. This map consists of entries that map city names to their current temperatures. For example, {"Hong Kong", "28 C"} may be an entry in this map, and {"Mumbai", "30 C"} may be another. Using EL, the temperature of Hong Kong can be referred to via ${newsfeed.temp ["Hong Kong"]}. The temperature of Mumbai can be accessed via the EL expression ${newsfeed.temp.Mumbai}.

Occasionally, you may need to work with an attribute attached to a JSP implicit scope object that may have a name containing the "." character, other special characters, or even characters from foreign character sets. In this case, the [] notation is your only choice. For example, to obtain the value of an attribute named "javax.security.password" attached to the request scope, you must use the EL expression ${requestScope["javax.security.password"]}. The EL implicit object, requestScope, will be covered shortly in this chapter.

Time to see this in action. The next Try It Out example illustrates nested property access and the equivalence of the "." and "[ ]" notations.

How It Works

The index.jsp that produced the output in Figure 5-4 is located at <Tomcat Installation Directory>/webapps/ch05/example3/index.jsp. The content of this file is reproduced here:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<jsp:useBean id="newsfeed" class="com.wrox.begjsp.ch5.NewsFeed" scope="page" />
<html>
<head>
  <title>EL Property Access and Nested Properties Examples</title>
</head>
<body>
  <h1>EL Property Access and Nested Properties Examples</h1>

  <jsp:setProperty name="newsfeed"  property="topic" value="news"/>
  News headline is <b>${newsfeed.value}</b>.<br/>

  <jsp:setProperty name="newsfeed"  property="topic" value="entertainment"/>
  Entertainment headline is <b>${newsfeed["value"]}</b>.<br/>
  <jsp:setProperty name="newsfeed"  property="topic" value="weather"/>
  The weather in Tokyo right now is ${newsfeed.values.Tokyo}.<br/>
  The weather in Mumbai right now is ${newsfeed["values"].Mumbai}.<br/>
  The weather in Hong Kong right now is ${newsfeed.values["Hong Kong"]}.<br/>
</body>
</html>

As a refresher, recall from Chapter 2 that the NewsFeed object can be used as follows:

  • First set the topic property to either news or entertainment, and then read the value property for the headline of the news or entertainment section.

  • First set the topic property to weather, and then read the values property for the temperature of various cities.

In this case, the values property for reading the weather information is actually a Java Map, with the name of the city as the key and the temperature of the city as the value.

First, an instance of the NewsFeed object is created by the standard <jsp:useBean> action:

<jsp:useBean id="newsfeed" class="com.wrox.begjsp.ch5.NewsFeed" scope="page" />

This action creates a page scoped attribute that is accessible as an EL named variable, via the name newsfeed. The newsfeed named variable can immediately be used in EL expressions.

To print out the news headline, first the topic property of newsfeed is set to news; then the value property is read to get the headline. This is done via the following JSP code, involving the <jsp:setProperty> standard action and an inline EL expression:

<jsp:setProperty name="newsfeed"  property="topic" value="news"/>
News headline is <b>${newsfeed.value}</b>.<br/>

Note that the ${newsfeed.value} expression is used to access the value property of the newsfeed JavaBean. The resulting HTML output is as follows:

News headline is <b>JSP Programmer Won 10 Million in Lottery.</b><br/>

To print out the entertainment headline, the exact same approach is used. This time, the topic property is set to entertainment and the value property is read to get the headline. The following JSP code from index.jsp is responsible for this:

<jsp:setProperty name="newsfeed"  property="topic" value="entertainment"/>
Entertainment headline is <b>${newsfeed["value"]}</b>.<br/>

Note that the ${newsfeed["value"]} EL expression is used to access the entertainment headline. As mentioned earlier, this is entirely equivalent to the expression ${newsfeed.value} used to fetch the news headline. The resulting HTML output is as follows:

Entertainment headline is <b> Reality TV Show Ratings Falling.</b><br/>

To access the weather information, a more complex data structure needs to be accessed. This is the values property of the newsfeed object. Figure 5-5 shows this Java data structure.

Newsfeed data structure

Figure 5.5. Newsfeed data structure

In Figure 5-5, the values property is a readable property of the newsfeed JavaBean. This property is accessible only after the topic is set to weather. The property itself is a Map. The key of the map is the name of the cities, and the associated value is the temperature.

The following code in the index.jsp file used in this example will access and print out the cities and their temperature:

<jsp:setProperty name="newsfeed"  property="topic" value="weather"/>
The weather in Tokyo right now is ${newsfeed.values.Tokyo}.<br/>
The weather in Mumbai right now is ${newsfeed["values"].Mumbai}.<br/>
The weather in Hong Kong right now is ${newsfeed.values["Hong Kong"]}.<br/>

The EL expression ${newsfeed.values.Tokyo} is used to access the temperature in Tokyo; note the nested property access using the . operator. As a variation, the temperature of Mumbai is accessed using the EL expression ${newsfeed["values"].Mumbai}; of course, this is entirely equivalent to the EL expression ${newsfeed.values.Mumbai}. You may want to try changing it and see for yourself. Finally, the temperature in Hong Kong is displayed using the EL expression ${newsfeed.values["Hong Kong"]}. Because there is a space character in the city name, this is the most convenient way of accessing the temperature value. Executing the previous JSP fragment will result in all the temperatures being displayed via the following HTML:

The weather in Tokyo right now is 18 C.<br/>
The weather in Mumbai right now is 30 C.<br/>
The weather in Hong Kong right now is 28 C.<br/>

For those curious to see the Java source code of NewsFeed.java, especially the complex values property, it is located at <Tomcat Installation Directory>/webapps/ch05/WEB-INF/classes/com/wrox/begjsp/ch5/NewsFeed.java, and is reproduced here:

package com.wrox.begjsp.ch5;

import java.beans.*;
import java.util.*;

public class NewsFeed extends Object implements java.io.Serializable
{
    private String topic;
    private String value;
    private HashMap values;

    public NewsFeed()
    {
    }

    public void setTopic(String topic)
    {
        value = "";
        values = null;
        if (topic.equals("news"))
        {
            value = "JSP Programmer Won 10 Million in Lottery";
        }
if (topic.equals("entertainment"))
        {
            value = "Reality TV Show Ratings Falling";
        }
        if (topic.equals("weather"))
        {
            values = new HashMap();
            values.put("Mumbai", "30 C");
            values.put("Tokyo", "18 C");
            values.put("Hong Kong", "28 C");
        }
    }

    public String getValue()
    {
        return this.value;
    }

    public Map getValues()
    {
        return this.values;
    }
}

This concludes the coverage of this Try It Out example and EL-based property access.

When named variables were discussed earlier, you learned that EL will first try to match a name to EL implicit objects before attributes attached to scoping objects are checked. Now is a good time to take a look at the set of available EL implicit objects and how you can use them.

Implicit EL Objects in JSP 2.0

Implicit objects in EL are available to the JSP developer, within an EL expression, without any explicit coding or declarations. Implicit objects are designed to facilitate JSP programming and make the most common aspects of a JSP page immediately available to code written in EL.

There are a total of 11 implicit objects. These 11 implicit objects can be classified into five major categories:

  • JSP implicit object

  • Convenience scoping access implicit objects

  • Convenience parameter access implicit objects

  • Convenience header access implicit objects

  • The convenience initialization parameter access implicit object

The only EL implicit object in the JSP implicit object category is the pageContext implicit object. This is the very same object as the JSP implicit object of the same name (JSP implicit objects and their use are covered later in Chapter 9, "JSP and JavaBeans"). The rest of the EL implicit objects are Java maps, and they simply provide easier means for accessing certain properties of the pageContext implicit object.

There are four convenience scoping access implicit objects, called pageScope, requestScope, sessionScope, and applicationScope. These are maps that enable easy access to scoped attributes. For example, an attribute called username attached to the request scope can be accessed directly via the EL expression ${requestScope.username}.

There are two convenience parameter access implicit objects for accessing the HTTP request parameters (the form submission parameters): param and paramValues. The param is a map used to access single-valued parameters, and paramValues can be used to access parameters that may contain multiple values. The next Try It Out example shows how this is handled.

There are three convenience header access implicit objects for accessing the HTTP headers: header, headerValues, and cookie. These are maps that are useful in cases where you may need raw access to HTTP header and/or cookies.

There is one convenience initialization parameter access implicit object, initParam. This map can be used to access the value of initialization parameters, typically set in web.xml.

Any information obtainable using a convenience object may also be obtained via the pageContext implicit object, although the access may involve complex nested property access.

If you use one of the names mentioned in this section for any attributes that you attach to scoping objects, the attribute may become inaccessible. The names provided here always return the implicit object instead of any attributes. For example ${param} always refers to the EL implicit object, and not a named attribute called param.

The next Try It Out example shows how to work with several of the EL convenience access implicit objects.

How It Works

The index.jsp that creates the cake creation form in Figure 5-6 is located at <Tomcat Installation Directory>/webapps/ch05/example4/index.jsp. The content of this JSP is reproduced here:

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

<html>
<head>
  <title>EL Implicit Object Example</title>
</head>
<body>
  <h1>EL Implicit Object Examples</h1>
  <form action="formproc.jsp" method="post">
    <table>
      <tr>
        <td colspan="2"><h3>Design a Cake</h3></td>
      </tr>
      <tr>
        <td>Cake shape:</td>
        <td>
          <select name="shape">
<option>round</option>
            <option>square</option>
            <option>heart</option>
          </select>
        </td>
      </tr>
      <tr>
        <td valign="top">Toppings</td>
        <td>
          <input type="checkbox" name="topping" value="choc">Chocolate</input><br/>
          <input type="checkbox" name="topping" value="cane">Candy Cane</input><br/>
          <input type="checkbox" name="topping" value="flower">Flower</input><br/>
        </td>

      </tr>

      <tr>
        <td colspan="2">
        <center><input type="submit" value="Send"/></center>
        </td>
      </tr>
    </table>
  </form>
</body>
</html>

This JSP page has no active JSP code, just an HTML form. The shape selection is offered through a <select> HTML tag. Upon form submission, this will result in an HTTP request parameter (form submission) called shape, with a value of round, square, or heart:

<select name="shape">
    <option>round</option>
    <option>square</option>
    <option>heart</option>
    </select>

The selection of toppings is provided through a series of HTML check boxes. This allows for the selection of multiple values:

<input type="checkbox" name="topping" value="choc">Chocolate</input><br/>
  <input type="checkbox" name="topping" value="cane">Candy Cane</input><br/>
  <input type="checkbox" name="topping" value="flower">Flower</input><br/>

Upon form submission, this will result in an HTTP request parameter called topping that can contain zero or more of choc, cane, and/or flower.

When the form is submitted, the POST method is used to send the request parameters via an HTTP header back to the server. The attributes of the HTML <form> tag specified this:

<form action="formproc.jsp" method="post">

The form processing JSP is formproc.jsp, located at <Tomcat Installation Directory>/webapps/ch05/example4/formproc.jsp and reproduced here:

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

<html>
<head>
  <title>EL Implicit Object Example Form Processor</title>
</head>
<body>
  <h1>EL Implicit Object Example Form processor</h1>

  <b>Shape of cake selected:</b> ${param.shape}<br/>
  <b>Toppings selected:</b>

  <c:forEach var="aTopping" items="${paramValues.topping}">
    &nbsp;&nbsp;${aTopping}&nbsp;&nbsp;
  </c:forEach>
  <br/>

  <b>Browser:</b> ${header["user-agent"]}<br/>

  <br/>
  <small><a href="index.jsp">back to form</a></small>
</body>
</html>

The convenience access implicit object, param, is used to render the value of the cake's shape. This is done in formproc.jsp via the following code:

<b>Shape of cake selected:</b> ${param.shape}<br/>

Note how easy it is to access form submission parameters through the param implicit object. In this case, this will result in the following output:

<b>Shape of cake selected:</b> square<br/>

Because the topping parameter may have multiple values, it is necessary to access it through the paramValues implicit object. The following code in formproc.jsp renders all the selected toppings:

<b>Toppings selected:</b>
<c:forEach var="aTopping" items="${paramValues.topping}">
  &nbsp;&nbsp;${aTopping}&nbsp;&nbsp;
</c:forEach>

The JSTL <c:forEach> iterator tag is used to go through each value of the paramValues.topping request parameter. Note that the paramValues implicit object has made the processing of multivalued form parameters quite simple. In this case, all toppings are selected, with the resulting HTML:

<b>Toppings selected:</b>
&nbsp;&nbsp;choc&nbsp;&nbsp;
&nbsp;&nbsp;cane&nbsp;&nbsp;
&nbsp;&nbsp;flower&nbsp;&nbsp;

Last but not least, the final active line in formproc.jsp accesses the HTTP header called user-agent, which contains an identifier to the browser being used by the client. The following code renders this identifier:

<b>Browser:</b> ${header["user-agent"]}<br/>

Note the use of the EL implicit header object. The EL expression ${header["user-agent"]} accesses the HTTP header called user-agent directly. When Internet Explorer 6 on Windows XP is used to access this Try It Out example, the following browser identifier is rendered:

<b>Browser:</b> Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)<br/>

This concludes our coverage of the Try It Out example and EL implicit objects.

User-Supplied Functions within EL

When you are using JSP to create your application's Web user interface, you may need to transform, manipulate, or format the data that you are rendering. Typically, a custom tag library can be used to achieve this. However, you may occasionally have a need to do this at the EL expression level. Unfortunately, EL has no built-in function library for this purpose. Thankfully, EL does support the notion of user-supplied EL functions.

Namespace and EL functions

The EL syntax to access a user-supplied function includes the use of a namespace. This is a borrowed concept from tags. In fact, EL functions are described in the Tag Library Descriptors (TLD) file. Creating tags and TLDs is covered in detail in Chapter 11. The information provided here will enable you to create some EL-accessible functions.

For example, to use an EL function that returns the absolute value of a number, called abs(), you may use the following EL expression: ${wf:abs(num)}.

This means that the wf namespace is defined in a <taglib> directive earlier—for example, a <taglib> directive similar to the following:

<%@ taglib prefix="wf" uri="http://www.wrox.com/begjsp/el-functions-taglib" %>

This syntax enables you to use functions with the same name, but with totally different implementations, using different namespace prefixes. For example, wf:abs() may have a completely different implementation than wroxdp:abs() has.

Static methods of a Java class

EL functions are static methods defined in Java code. They can return the value of any data type, although the String return type is most useful when rendering in EL expressions. These methods may also have any number of arguments. The TLD must describe the return data type and the arguments' data types of the methods. For example, the following TLD fragment describes a function that returns a String and takes a String and an int as arguments:

<function>
  <description>Repeat String Function</description>
  <name>rep</name>
  <function-class>com.wrox.begjsp.ch05.ElFuncs</function-class>
  <function-signature>String rep(String,  int )</function-signature>
 </function>

The final Try It Out example in this chapter shows how to expose a couple of java.lang.Math methods for use in EL expressions.

How It Works

Instead of coding our own static methods in our own Java classes, the code in this Try It Out example simply exposes the abs() and round() static methods from the java.lang.Math Java library package.

The index.jsp that exercises the two functions, as in Figure 5-8, can be located at <Tomcat Installation Directory>/webapps/ch05/example5/index.jsp. The content of this JSP is reproduced here:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="wf" uri="http://www.wrox.com/begjsp/el-functions-taglib" %>

<html>
<head>
  <title>EL Function Examples</title>
</head>
<body>
  <h1>EL Function Examples</h1>
  <c:set var="num" value="-500"/>
  The absolute value of ${num} is ${wf:abs(num)}.<br/>

  <c:set var="calc" value="${1 + 2 * 3 + 4 div 6}"/>
  The rounded value of ${calc} is ${wf:round(calc)}.<br/>

</body>
</html>

Note that the namespace used to map the functions is wf, and is defined by the <taglib> directive:

<%@ taglib prefix="wf" uri="http://www.wrox.com/begjsp/el-functions-taglib" %>

The abs() function is called in the following code from the index.jsp:

<c:set var="num" value="-500"/>
The absolute value of ${num} is ${wf:abs(num)}.<br/>

The function is invoked in the EL expression ${wf:abs(num)}. The resulting output, after the abs() function is called, is as follows:

The absolute value of −500 is 500.

The round() function is called in the following code from the index.jsp:

<c:set var="calc" value="${1 + 2 * 3 + 4 div 6}"/>
The rounded value of ${calc} is ${wf:round(calc)}.<br/>

The round function is invoked in the EL expression ${wf:round(calc)}. The resulting output is as follows:

The rounded value of 7.666666666666667 is 8.

The <taglib> directive in index.jsp uses a URI of http://www.wrox.com/begjsp/el-functions-taglib to select the TLD to use. The following section shows how this is mapped to the java.lang.Math methods.

Deployment descriptor entries

The first file to look at is the ch05 application's web.xml file, its deployment descriptor. You can locate this file at <Tomcat Installation Directory>/webapps/ch05/example5/WEB-INF/web.xml. This file is reproduced here, with the tag library declaration entry highlighted:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 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-app_2_4.xsd"
    version="2.4">

  <description>
    Wrox Beginning JSP Examples - Chapter 5
  </description>
  <display-name>Chapter 5 Example (Wrox Beginning JSP)</display-name>

    <taglib>
     <taglib-uri>
       http://www.wrox.com/begjsp/el-functions-taglib
     </taglib-uri>
     <taglib-location>
       /WEB-INF/jsp/function-taglib.tld
     </taglib-location>
    </taglib>

</web-app>

The URI http://www.wrox.com/begjsp/el-functions-taglib is mapped to a TLD file, located at WEB-INF/jsp/function-taglib.tld as indicated by the <taglib> declaration in the preceding code.

TLD function definitions

The EL functions are declared within the function-taglib.tld file. This file is located at <Tomcat Installation Directory>/webapps/ch05/example5/WEB-INF/jsp/function-taglib.tld. This TLD file is reproduced here, with the function declarations highlighted:

<?xml version="1.0" encoding="UTF-8" ?>

<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 web-jsptaglibrary_2_0.xsd"
    version="2.0">
  <description>A taglib to define some EL accessible functions.</description>
  <tlib-version>1.0</tlib-version>
  <short-name>ELFunctionTaglib</short-name>
  <uri>/ELFunctionTagLibrary</uri>
<function>
    <description>Exposes the abs() function from java.lang.Math package</description>
    <name>abs</name>
    <function-class>java.lang.Math</function-class>
    <function-signature>int abs( int )</function-signature>
  </function>

  <function>
    <description>Exposes the round() function from java.lang.Math package</description>
    <name>round</name>
    <function-class>java.lang.Math</function-class>
    <function-signature>int round( double )</function-signature>
  </function>
</taglib>

Note how the class implementing the function is specified within the <function-class> sub-element, and the signature of the function is declared in the <function-signature> sub-element of the declaration.

This concludes our coverage of the final Try It out example and EL functions.

Summary

This chapter covered the JSP Expression Language (EL) in detail. EL is essential to JSP 2.0 because it enables the creation of scriptless JSP applications. Scriptless JSPs focus on the presentation of the data, do not contain embedded Java language elements, and are easier to maintain for the long term.

To summarize what we covered:

  • EL expressions may be used inline with template data, or within certain attributes of standard or custom actions.

  • EL provides a rich set of operators, including arithmetic operators, logical operators, the comparison operator, and the empty prefix operator.

  • Working together with JSTL custom tags, EL expressions can be used in the flow control of JSP logic, eliminating the need for scriptlets.

  • Named variables in EL are scoped attributes. The properties of any JavaBean-based object can be accessed via the "." operator, and this can be applied in a nested fashion. The "." operator is equivalent to the "[..]" operator. Either notation can be used.

  • EL features 11 implicit objects that can be used to access the PageContext, attributes attached to JSP scoping objects, HTTP headers, request parameters, JSP initialization parameters, and HTTP cookies.

  • EL programming is weakly typed. The developer relies on the automatic type conversion provided by EL to coerce data into the required data type. The automatic type conversion provided by EL is well documented. It will attempt to do the right thing most of the time. However, understanding how this conversion takes place can be useful in certain uncommon programming situations.

  • Whenever possible, null values are converted into the appropriate type (for example, null strings or zero value) to avoid errors during JSP processing.

  • Static functions of Java classes can be mapped via a Tag Library Descriptor to functions that can be accessed through EL expressions. This can be used to extend EL's functionality.

Exercises

  1. Create a JSP-based application that takes a number between 1 to 10 as input, and then prints a simple multiplication table. For example, if the number 5 is entered, the following should appear in the output page:

    • 5 times 1 is 5.

    • 5 times 2 is 10.

    • 5 times 3 is 15.

    • 5 times 4 is 20.

    • 5 times 5 is 25.

    • 5 times 6 is 30.

    • 5 times 7 is 35.

    • 5 times 8 is 40.

    • 5 times 9 is 45.

    • 5 times 10 is 50.

      Use EL and EL expressions wherever possible in your solution.

  2. Write code to expose the following additional functions from the java.lang.Math package to EL expressions:

    • min()

    • max()

    • sin()

    • cos()

    • sqrt()

  3. Create a JSP page to test the functions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.146.113