- The Standard Actions
- The JSP Expression Language (EL)
- Summary
The JSP Expression Language (EL)
The remainder of this chapter will discuss the JSP expression language. The expression language has been developed by two expert groups at the Java Community Process. One is the JSP Standard Tag Library expert group, and the other is the JSP 2.0 expert group. The reason for the involvement of both groups becomes clear when you realize that the EL is designed to be used both within JSP tags, and also in line within JavaServer Pages directly. In fact, the EL is part of the JSP2.0 specification as opposed to the JSTL 1.1 specification.
The following syntax identifies EL expressions within pages.
${ EL expression }
When used within the attributes of tags from the JSTL, for example, you end up with JSP code that looks like this:
<prefix:tag attribute="${EL Expression}" />
When used directly within pages, you could get code like this:
<body bgcolor="${EL Expression}">
Listing 3.7 shows a basic JSP that is using the expression language directly in the page.
Listing 3.7 usingEL.jsp
<!-- be aware that this listing will not work in Tomcat 4.1, or any other JSP 1.2 container --> <html> <head> <title>Expression Language Examples</title> <% // set up a page context parameter for use later in the page // normally this would have been set within the context of // an application pageContext.setAttribute("pageColor", "yellow"); %> </head> <body bgcolor="${pageScope.pageColor}"> <h1>Welcome to the ${param.department} Department</h1> Here are some basic comparisons: <p> Is 1 less than 2? ${1<2} <br> Does 5 equal 5? ${5==5} <br> Is 6 greater than 7? ${6 gt 7}<br> <p>Now for some math:<br> 6 + 7 = ${6+7}<br> 8 x 9 = ${8*9}<br> <hr>You appear to be using the following browser: ${header["user-agent"]} </body> </html>
The output of Listing 3.7 with the JSP 2.0 early access preview version of Tomcat appeared as shown in Figure 3.4.
Figure 3.4 The output from usingEL.jsp in a browser.
Listing 3.7 will be referred to as we progress through the chapter. So, what does the EL look like? It draws its syntax from two other scripting languages: XPath and ECMAScript. XPath is used in XML applications and is discussed in Chapter 11, "Transforming XML Using XSLT and XSLFO." ECMAScript is mainly used as a client-side scripting language in Web applications, and is also commonly used in the development of Microsoft Active Server Pages.
NOTE
ECMAScript was developed within the context of the European Computer Manufacturers Association. It is essentially a standardization of Netscape's JavaScript, which has been widely used as a client-side scripting language in both Internet Explorer (implemented as JScript) and Netscape browsers.
The EL has the following features:
It has a set of implicit objects available to it.
It has a comprehensive set of operators.
It can access collections and nested properties in an intuitive way.
It has a selection of extensible functions mapping to static methods in Java classes.
EL Literal Types
The expression language has the following basic types that can be used for literal values:
StringThis is a value defined within double or single quotes.
BooleanLike Java, this type has only the possible values of true and false.
IntegerLiteralThis type represents signed integral numbers. It is implemented as a Java long.
FloatingPointLiteralThis type represents floating-point numbers.
NullLiteralThis is the same as the Java null. The literal value for this is null.
The EL Operators
The EL has a comprehensive set of operators as you might expect. We will explore these in this section. As you'll see, many of them are the same as those found in the Java Programming language. The main difference, however, is that for many operators there is a textual equivalent. The most commonly used operators are discussed here; for a complete list visit the JSP 2.0 specification at http://www.jcp.org/jsr/detail/152.jsp.
The Arithmetic Operators
There are the expected operators here: +, -, *, /, %. You can also use the following for the / and % operators: div and mod. You can see examples of these being used in Listing 13.7:
<p>Now for some math:<br> 6 + 7 = ${6+7}<br> 8 x 9 = ${8*9}<br>
The Relational Operators
The relational operators are shown in Table 3.2.
Table 3.2 The Relational Operators
Symbol Version |
Text Version |
== |
eq |
!= |
ne |
< |
lt |
> |
gt |
>= |
ge |
<= |
le |
Notice that they all have a text version in addition to the more familiar symbol version. These are also used in Listing 13.7:
Here are some basic comparisons:
<p> Is 1 less than 2? ${1<2} <br> Does 5 equal 5? ${5==5} <br> Is 6 greater than 7? ${6 gt 7}<br>
The Logical Operators
The logical operators are the same as the Java Programming Language, but they also have their textual equivalents within the EL. They are shown in Table 3.3.
Table 3.3 The Logical Operators
Symbol Version |
Text Version |
&& |
and |
|| |
or |
! |
not |
The empty Operator
The empty operator allows you to test the following:
Object references to see if they are null.
Strings to see if they are empty.
Arrays to see if they are empty.
Lists to see if they are empty.
Maps to see if they are empty.
You use the operator in the following way:
empty variableName
If any of the above conditions are met, then the operator returns true.
Operator Precedence
The operator precedence works from the highest precedence through to the lowest precedence, and then left to right - In other words, the same as the Java programming language. As with any other programming language, you can affect this precedence with the use of parentheses ().
The operator precedence table as defined by the JSP 2.0 specification is shown below in Table 3.4:
Table 3.4 The Operator Precedence Table for the EL
[] . |
() |
-(unary) not ! empty |
* / div % mod |
+ - (binary) |
<> <= >= lt gt le ge |
== !- eq ne |
&& and |
|| or |
Accessing Objects and Collections
In the Java Programming Language, objects and their properties are accessed using get and set methods. This is because of encapsulation, and it is not considered good practice to access object properties directly.
So, for example, if there were a hierarchy of objects such as a bookstore, with a book, and the book had a chapter, the code would be something like
getBookStore().getBook().getChapter("Ch03FurtherJSP");
This can look quite messy, and although hiding the variables provides encapsulation, it is not clear to read, especially within JSPs in code like this:
<%= getBookStore().getBook().getChapter("Ch03FurtherJSP") %>
If this were a scripting language such as ECMAScript, it would be something like
bookStore.book.chapters.Ch03FurtherJSP
If you are familiar with ECMAScript, you will have seen how objects can be accessed in a variety of ways in that language. This is also the case in the EL. So, taking our basic chapter example one step further, using the EL, you can access this chapter object in the following ways:
bookStore.book.chapters.Ch03FurtherJSP bookstore["book"].chapters.Ch03FurtherJSP bookstore['book'].chapters["Ch03FurtherJSP"]
Essentially, what we are saying here is that there are two operators that can be used to enable you to access objects. One is the dot operator (.), and the other is the [] brackets. When using the brackets, you can place the name of a subproperty as a String in either double or single quotes within them, as shown. Using the dot enables you to step down through properties and the various subproperties.
CAUTION
In ECMAScript, you can also access objects by putting an index number in the square brackets. This is not possible in the EL unless the property is a collection of some kind.
This mechanism for accessing objects makes the development of JSPs substantially easier. This is especially true for Web designers, who will most probably already be experienced in the ECMAScript object access mechanisms, which are now available to the JSP developer.
The previous caution mentions that the use of the square brackets is also used to access collections. The EL can handle the various Java collection types, and it uses a generic syntax for accessing a collection, regardless of the actual collection implementation. So, the collection could be an array, a List, a Vector, and so on, but the syntax would be the same. Collections are accessed in a similar way to how an array would be accessed in the Java Programming Language; in other words, an index is placed within the square brackets. So, in the earlier simple example, if the chapters were stored as a List rather than individual named properties, you could access Chapter 3 in the following way:
bookStore.book.chapters[2]
If the collection were a Map, instead of an index number being placed within the square brackets, a key would be used:
bookStore.book.chapters["Ch03FurtherJSP"]
The access of objects from the EL is illustrated by the following worked example, starting with the JSP shown in Listing 3.8.
Listing 3.8 ELAccessingObjects.jsp
<!-- be aware that this listing will not work in Tomcat 4.1, or any other container that does not support the use of the expression language outside of tags --> <html> <head> <title>Expression Language Accessing Objects</title> <p>Now lets use some objects. You will see more on the bean standard actions in chapter 6. But for now, remember that here useBean instantiates beans and setProperty sets the properties of beans. <%-- create a single Person object --%> <jsp:useBean id="man" class="com.conygre.Person"> <jsp:setProperty name="man" property="name" value="Nick"/> <jsp:setProperty name="man" property="password" value="pass"/> </jsp:useBean> <p>Now we will use the expression language to access the properties. The person is called ${man.name}, and the password is ${man.password}. Now a list and a map is created as properties of the GroupPeople class. <%-- create a GroupPeople object that contains a List and a Map --%> <jsp:useBean id="group" class="com.conygre.GroupPeople"/> The map is accessible using the following syntax:<br> The first author is called ${group.mapPeople["authorA"]}, and the second author is called ${group.mapPeople["authorB"]}. <p>The List is accessible also, but using the following syntax:<br> The first author is called ${group.listPeople[0]}, and the second author is called ${group.listPeople[1]}. </body> </html>
In Listing 3.8, you can see the JavaBean related standard actions being used to set up two beans. One is a Person bean, which is based upon the Java class shown in Listing 3.9, and the other is a GroupPeople bean, shown in Listing 3.10.
Listing 3.9 Person.java
package com.conygre; public class Person { private String name; private String password; public String getName(){ return name; } public void setName(String s){ name = s; } public String getPassword(){ return password; } public void setPassword(String s){ password = s; } }
Listing 3.10 GroupPeople.java
package com.conygre; import java.util.*; public class GroupPeople { private List listPeople; private Map mapPeople; public GroupPeople() { listPeople = new Vector(); listPeople.add("Nick"); listPeople.add("Mark"); mapPeople=new HashMap(); mapPeople.put("authorA", "Nick"); mapPeople.put("authorB", "Mark"); } public List getListPeople(){ return listPeople; } public void setListPeople(List s){ listPeople = s; } public Map getMapPeople(){ return mapPeople; } public void setMapPeople(Map s){ mapPeople = s; } }
The crucial lines within the JSP of Listing 3.8 are the ones that access bean properties using the EL. They are shown below:
The person is called ${man.name}, and the password is ${man.password}. . . . The map is accessible using the following syntax:<br> The first author is called ${group.mapPeople["authorA"]}, and the second author is called ${group.mapPeople["authorB"]}. <p>The List is accessible also, but using the following syntax:<br> The first author is called ${group.listPeople[0]}, and the second author is called ${group.listPeople[1]}.
The first line in this snippet is accessing the Person instance with the id of man. It is accessing the name and password properties directly.
The remainder of this snippet demonstrates how maps and lists are accessed. The GroupPeople bean has a Map property and a List property set up with some Strings as content, as shown in Listing 3.10. The GroupPeople object id is set up as group. Therefore the code accesses the properties listPeople and mapPeople as you would expect. Notice that the List values are accessed by their indices, and the Map values are accessed by their key names.
The EL Implicit Objects
In the previous chapter, you were exposed to the implicit objects available to the JSP developer for use within your pages. The Expression Language also provides a number of implicit objects that can be used directly from within EL code. Table 3.5 lists these objects and what they can be used for.
Table 3.5 The EL Implicit Objects
Name |
Description |
pageContext |
This is the page context object,. The the same object that is available as a JSP-implicit object. This was discussed in detail in Chapter 2. |
pageScope |
In the very last section of Chapter 1, the idea of scope was introduced. Page-scoped attributes can be accessed by name using this variable. This is because the variable is a Map. Here is an example of accessing a page-scoped object that we have called pageColor: <body bgcolor="${pageScope.pageColor}"> or <body bgcolor="${pageScope['pageColor']}"> This example can be seen in Listing 3.11. |
requestScope |
The requestScope is also a Map object, but it contains all the request-scoped attributes. It can be used in the same way as the pageScope. |
param |
The param object is another Map that contains any request parameters normally accessed using the request.getParameter(String paramName) method. This could be used as a more convenient mechanism for accessing parameters. The following fragment shown here could be rewritten from <h1><%=request.getParameter("department") %> Department</h1> To to a more simple <h1> ${param.department} Department</h1> This example can be seen in Listing 3.7. |
paramValues |
This object represents the result of the call to request.getParameterValues(String paramName). This method returns an array of parameter values based on a particular parameter name. The following would return all the values of a parameter called favoriteColors. ${paramValues.favoriteColors} |
header |
This implicit variable contains a Map of all the headers along with their values. It returns the result of the method request.getHeader(String headerName). The following example accesses the user agent, which details the client browser: ${header["user-agent"]} This is visible in Listing 3.7. |
headerValues |
This object represents the result of the call to request.getHeaders(String headerName). This method returns an array of header values based on a particular header name. |
sessionScope |
The sessionScope is a Map object that contains all the session-scoped attributes. It can be used in the same way as pageScope. |
cookie |
This variable provides access to the Cookies array that is available to JSP via the request.getCookies() method. Cookies are discussed in Chapter 8, "Session Tracking Using JSP." |
applicationScope |
The applicationScope is a Map object that contains all the application-scoped attributes. It can be used in the same way as pageScope. |
initParam |
This variable gives access to all the initialization parameters that may have been passed to the JSP when its corresponding servlet was initialized. |
Reserved Words
There are also a number of reserved words for the EL. Many of these are textual versions of the operators listed in Table 3.6. Others are words that currently have no use, but have been reserved for future use. They are all shown in Table 3.7.
Table 3.6 The Reserved Words
lt |
ge |
le |
eq |
and |
true |
ne |
or |
false |
gt |
not |
null |
instanceof |
empty |
div |
mod |
|
|
Expression Language Functions
The expression language also provides a number of functions, associated with string manipulation and for working with collections. These are shown in Table 3.7. Note that this list was taken from the JSTL 1.1 maintenance review proposals, and it is possible that this list is not the exact final list of functions.
Table 3.7 Expression Language Functions
Function |
Description |
boolean contains(string, |
Returns true if the specified String contains the |
substring) |
sequence of characters in the specified substring. |
boolean containsIgnoreCase(string, substring) |
Returns true if the specified String contains the sequence of characters in the specified substring, but not taking account of case. |
boolean endsWith(string, suffix) |
Returns true if the string ends with the supplied string suffix. |
String escapeXml(string) |
Escapes any XML sensitive characters in supplied string (&, <, >, ', ") with the predefined XML entity equivalents and returns the result as a String. See Chapter 10, "Utilising XML from JSP" for more information on XML. |
int indexOf(string, substring) |
Returns the index within this string of the first occurrence of the specified substring. |
String join(collection, separator) |
This method takes in a collection, and concatenates the values together in a String, using the supplied separator. |
int length(collection) |
Returns the length of a Collection as an int. |
String replace(inputString, beforeSubstring, afterSubstring) |
Replaces the characters in a substring of the input string with the additional characters specified. |
String[] split(string, separator) |
Takes in a String, and converts the contents into a String array, with each new array entry beginning when the separator character is found. |
boolean startsWith(string, prefix) |
Queries a String to see if it starts with the supplied prefix. |
String substring(string, beginIndex, endIndex) |
Returns a substring from a string based upon the supplied beginning and end indexes. |
String substringAfter(string, substring) |
Returns a substring from a supplied string. The substring is the contents of the supplied string located after the supplied substring. |
String substringBefore(string, substring) |
Returns a substring from a supplied string. The substring is the contents of the supplied string located before the supplied substring. |
String toLowerCase(string) |
Converts a supplied string to upper case. |
String toUpperCase(string) |
Converts a supplied string to lower case. |
String trim(string) |
Returns a copy of the supplied string with any leading and trailing white space removed. |
In addition to the supplied functions, you can also create your own. This is done by exposing static functions present in Java classes. For example, if a static method had the following signature:
public static String returnNewString(String oldString)
You would be able to invoke it from a page using the following style of EL construct:
${myTagLibrary:returnNewString("the old string value")}
Any parameters that the method takes are passed in as a comma-separated list. How these functions are set up is discussed in Chapter 9, "Developing Custom Tag Libraries."
Controlling Expression Language and Scriptlet Use
It is possible to deactivate the processing of EL elements within a JSP with the use of the following entry in the page directive. This might be necessary if aspects of the content of a page actually contained output of the format ${xxx}. To deactivate the expression language, you can disable it for entire groups of pages within a web application using an entry type in web.xml that is new in JSP 2.0. The entry is of the following format:
<jsp-property-group> <url-pattern>*.jsp</url-pattern> <el-ignored>true</el-ignored> </jsp-property-group>
The <jsp-property-group>, discussed earlier in the chapter, is an element that can be used in web.xml to configure groups of JSPs. In the above example, the expression language will be disabled for all JSP files.
Alternatively, you can disable the expression language for an individual page by setting the isELIgnored attribute of the page directive.
<%@page isELIgnored="false" %>
Using the <jsp-property-group> element, you can also disable scripting elements. The following is an example of a jsp-property-group that does this:
<jsp-property-group> <url-pattern>*.jsp</url-pattern> <scripting-invalid>true</scripting-invalid> </jsp-property-group>
This means that using these <jsp-property-group> elements, you can effectively enforce the use of the expression language instead of scriptlets using the two <jsp-property-group> elements shown above. This will enforce the separation of the Java from the JSPs.