Enterprise Java Technologies Tech Tips
Tips, Techniques, and Sample Code
Welcome to the Enterprise Java Technologies Tech Tips for
January 26, 2004. Here you'll get tips on using enterprise Java
technologies and APIs, such as those in Java 2 Platform,
Enterprise Edition (J2EE).
This issue covers JSP 2.0 Expression Language.
These tips were developed using the Java 2, Enterprise Edition,
v 1.4 SDK. You can download the SDK at
http://java.sun.com/j2ee/1.4/download-dr.html.
This issue of the Tech Tips is written by Mark Johnson, president
of elucify technical communications (http://www.elucify.com/),
and co-author of Designing Enterprise Applications with the J2EE
Platform, 2nd Edition (http://java.sun.com/blueprints/guidelines/
designing_enterprise_applications_2e/). Mark Johnson runs an open
forum for discussion of the tips at
http://groups.yahoo.com/group/techtipsarchive/.
You can view this issue of the Tech Tips on the Web at
http://java.sun.com/developer/EJTechTips/2004/tt0126.html.
See the Subscribe/Unsubscribe note at the end of this newsletter
to subscribe to Tech Tips that focus on technologies and products
in other Java platforms.
You can download the sample archive for these tips at
http://java.sun.com/developer/EJTechTips/download/ttjan2004.ear.
The context root for the application is ttjan2004, and the
index.html welcome file indicates how to use the sample code. Any
use of this code and/or information below is subject to the
license terms at
http://developers.sun.com/dispatcher.jsp?uid=6910008.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
JSP 2.0 EXPRESSION LANGUAGE
The December 22, 2003 Tech Tip titled "The JavaServer Pages Standard
Tag Library (JSTL)" showed how to use some of the new features of
JSP 2.0, including the new Expression Language. The following tip
covers the expression language in more detail. The sample code
accompanying the tip is a Web application that contains a single
JSP page. The page demonstrates several types of expressions and
some odd conditions.
Why Another Language?
Before JSP 2.0, you could use only a scriptlet, JSP expression,
or a custom tag to include server state in the JSP page output.
Although these solutions are useful, they require a relatively
large amount of work for even the simple job of accessing
server-side state. JSP 2.0 incorporates the Expression Language
(EL) first introduced in JSTL 1.0. EL makes it easier to integrate
server-side state with presentation output. Let's start with
a quick review of scriptlets, JSP expressions, and custom tags.
Consider a Web application that maintains information about usage
statistics in an object of class ServerStats. Class ServerStats
has a method getUserCount, which returns the number of users
currently logged on. The application maintains a single instance
of ServerStats in a ServletContext attribute called stats. Here's
a comparison of how you could create usage statistics output
using a scriptlet, a JSP expression, and a custom tag:
o Creating output with a scriptlet: With JSP version 1, you can
print the number of users logged on to the system using a
scriptlet. Any output the scriptlet produces has to be
explicitly written to the out stream. A JSP page could report
the number of users with the following scriptlet and template
text:
There are currently <%
ServerStats ss =
(ServerStats)application.getAttribute("stats");
out.print(ss.getUserCount());
%> userslogged on.
The result would look something like this:
There are currently 15 users logged on.
o Creating output with a JSP expression: You can simplify things
a bit by placing the code in a JSP expression. The expression
text within the JSP expression is evaluated, and the result is
coerced to a String for output. The result of the expression
replaces the expression tag in the JSP page output. Writing the
resulting text to the JSP page output is implicit.
There are currently
<%= (ServerStats)(application.getAttribute("stats")).
getUserCount() %> users logged on.
This is somewhat easier to write, but is still a bit difficult
to read and maintain.
o Creating output with a custom tag: In JSP 1, the way to make
dynamic content on a page more readable and reusable is to
create custom tags. Custom tags are JSP page tags defined by a
programmer. The behavior of the tag is implemented in a tag
handler class, which must be written (usually in Java). A tag
library descriptor (TLD) file defines the correspondence
between the custom tag and its handler class. A Web container
uses the TLD file and the custom tag class to generate code
dynamically. Custom tags produce a cleaner JSP page and enable
code reuse. Remembering that the actual code that implements
the lookup is in the handler class, the JSP code for the
example message would look like this:
There are currently users logged in.
Of course, to get to such a clean presentation, a developer
would have to write both a Java class and an XML-format TLD
file.
JSP 2.0 now offers a expression language that makes accessing
server-side state even easier. The syntax of the expression
language is simpler than a custom tag, and usually requires no
associated Java code. Also, the expression language automatically
handles typecasting, null values, and error handling. The JSP 2.0
expression language provides a way to access server-side state
with less effort than the approaches shown above. The JSP 2.0 way
to print the "number of users" message would look like this:
There are currently ${stats.userCount} users logged in.
Where EL Expressions Can Be Used
The JSP 2.0 specification
(http://jcp.org/aboutJava/communityprocess/final/jsr152/)
describes the expression language in detail. The expression
language is an extension of the JSTL 1.0 EL, that adds several
new features.
A JSP 2.0 EL expression is always written between the delimiters
${ and }. In the JSP page response, the result of expression
evaluation replaces the expression and its delimiters in the
template text. Within tags, expressions can be used only in
attribute values. For example, the following code from the sample
page is legal, because it uses tags only in template text and in
attributes.
Here's an example of a tag that is used illegally:
<${tag} var="x"/> <%-- INVALID SYNTAX --%>
The variables in an EL expression are Web-tier state. They are
values that can be in any scope: page, request, session, or
application. Unless you specify otherwise, variables are in page
scope.
In general, the values of EL variables are objects. When a
variable's value is an enterprise beans reference, data from the
enterprise bean can be included in the page with little
difficulty. For example, a shopping application could keep a
reference to a ShoppingCart stateful session bean in an
HttpSession attribute, under the name "cart". Printing the number
of items in the cart would then be as simple as the following:
You have ${cart.itemCount} items in your cart.
EL Syntax
EL expressions are comprised of literals, operators, and variables.
Expressions can also contain functions, but these are not covered
here. See the JSP 2.0 specifications and the J2EE 1.4 Tutorial
(http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html) for
details.
Literals can be of type boolean ("true" or "false"), integer,
floating point, or string. The token "null" denotes the null
literal.
The language offers the following operators (parentheses here are
used only for grouping):
o binary logical operators
(<, <=, ==, >=, >, lt, le, eq, ge, gt)
o binary arithmetic operators
(+, -, *, /, div, %, mod)
o indexing operators
(.) and ([])
o (equivalent) unary negation operators
(!, not)
o arithmetic unary minus
(-)
o (empty) operator, which evaluates to true if the expression
evaluates to null, or evaluates to a container object that
contains no items.
o ternary operator for simple if-then-else
(?:)
o parentheses for controlling evaluation precedence
The operators with the highest precedence are "[]" and ".", in
that order, followed by (). The precedence for the rest of the
operators is conventional: see the JSP 2.0 specifications for
details.
Literal Expressions
Any expression containing only literals and operators are
evaluated as arithmetic expressions. This is shown in the sample
page for the tip:
Expression Value
${1} 1
${1==1} true
${1==2} false
${22/7} 3.1428...
${123*234} 27872
Variable names in expressions evaluate to values of a type
appropriate for the operation in which it is involved. For
example, the expression ${x + 1} tries to coerce "x" to a number
before performing the addition.
EL Variables
Variables are accessed by name. Type coercion is automatic from
the variable's native type to a type that is compatible with the
requested operation. Variables can be either defined by the page,
or can be JSP implicit objects. (See the JSP 2.0 specifications
and the J2EE 1.4 tutorial for a complete list of implicit
objects.)
Variable names can be composed with expressions involving the
operators "." and "[]". These operators provide a great deal of
the power of EL, because they work for all collection types, as
well as for Java language arrays, maps, lists, and JavaBeans
property accessors. The operators allow you to navigate through
a network of JavaBeans or enterprise beans. You can move from one
bean to the next by simply dereferencing or indexing one of its
properties each time you use the operator.
The "." Operator
The "." operator is shorthand for calling a JavaBeans property
accessor for the property whose name is on the right-hand side of
the operator. For example, the following expression in the
sample page:
${pageContext.servletContext.servletContextName}
actually executes as:
pageContext.getServletContext().getServletContextName()
EL is more forgiving than is the Java programming language
regarding null values in expressions. In the Java programming
language, the expression a.getB().getC() throws a
NullPointerException if a.getB() returns null. Not so in EL. The
EL expression ${a.b.c} returns null if ${a.b} is null -- it does
not throw an exception. This makes writing expressions easier. To
check for null explicitly, use either the empty operator, or
compare the expression to null using == or the is keyword, like
this:
If the object being accessed is a Map, the "." operator uses the
name of the right-hand side as a string literal, and uses it as
a key to fetch the result. This is demonstrated in the sample
code in the two following expressions. The expressions are
equivalent (both reference the host HTTP header):
${header["host"]}
${header.host}
The "[]" Operator
The [] operator is a polymorphic indexing operator that can be
used to index collections (including Maps and Lists) and arrays.
The value inside the brackets is used as a key into a map, or as
a List or array index. On the sample page, the [] operator is
used to access a List and a Map:
${colors[1]} orange
${colors[5]} violet
${colors[1] > colors[5]} false
${colors[1024]}
${colors[1024] == null} true
Note that ${colors[1024]} has no value (because the array isn't
that long). Evaluating the expression produces null, not an "out
of bounds" error.
The [] operator can also be used to call JavaBeans property
accessors. In that case, the string in the bracket is the
property name. For example, given a JavaBean a, both of the
expressions ${a["b"]} and ${a.b} evaluate to the Java method call
a.getB().
The "." and [] operators are almost, but not quite, equivalent
for accessing Maps. The difference between the two is illustrated
below:
${header["host"]} localhost:8080
${header.host} localhost:8080
${header["user-agent"]} Mozilla/5.0 (Macintosh;...)
${header.user-agent} 0
Notice that ${header["host"]} and ${header.host} both look up the
key "host" in the Map called "header" (which is a JSP implicit
object containing HTTP headers for the request). But, while
${header["user-agent"]} produces the name of a browser,
${header.user-agent} produces 0. What does this mean?
The problem here is that "user-agent" isn't a well-formed Java
identifier. The value is 0 because the expression evaluator
parses the expression as the difference of the variable
header["user"] minus the value of the (nonexistent) variable
"agent". Both of these values are null, so the result is 0 (this
is by convention defined in the specification). The lesson here
is: it's best to always use [] for indexing Maps, and use "."
for calling property accessors.
A final difference between "[]" and "." is that the value
of an expression can be used to indicate a name using "[]".
The example in the sample code looks like this:
${header[headerName]}
The result of this block is the same as for the other two
expressions that look up the "host" header: "localhost:8080".
The first line sets the page variable "headerName" to the string
"host". The second line uses the value of the variable to look up
the HTTP header "host". Although this code simply uses a variable
name, the contents of the "[]" could be any EL expression that
yields the name of an HTTP header.
Controlling Variable Scope
Unless defined to be otherwise, variables defined on a page with
the assignment operator "=", or with a JSTL tag are in
page scope (in other words, they are PageContext attributes). If
a variable doesn't indicate its scope, the expression evaluator
searches attributes in page, request, session, and application
scope, and returns the first one it finds. If no variable of that
name is found, the expression evaluates to null.
A variable in an explicit scope can be accessed using one of the
four implicit scope objects: pageScope, requestScope,
sessionScope, or applicationScope. For example,
${sessionScope.myVariable} returns the value of the session
attribute myVariable. A variable's scope can be defined using the
scope attribute of , for example:
Defining Default Values
Like many scripting languages, EL is forgiving of null values.
When it can, EL simply substitutes an empty string, or zero, for
null. The problem with this behavior is that sometimes you want
to have special behavior if the value is null.
If you are using JSTL, the tag has a default attribute
you can use in case the value you're trying for is null. This
example from the sample page shows how to use it:
The result is the string "transparent". To do the same thing
using pure EL, you can use the ternary ?: operator, like this:
${colors[1024] == null ? "transparent" : colors[1024]}
This expression also returns "transparent", for the same reason
as before.
Iterating Maps
When using the JSTL tag to iterate on the values of
a Map, the iteration variable is of type java.util.Map.Entry. To
access the key and value of the map entry, use .key and .entry on
the iteration variable name.
The sample page shows an example of this, dumping the HTTP
headers to the page:
${hdr.key}=${hdr.value}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RUNNING THE SAMPLE CODE
Download the sample archive for these tips (from
http://java.sun.com/jdc/EJTechTips/download/ttjan2004.ear).
The application's context root is ttjan2004. The downloaded
ear file also contains the complete source code for the sample.
You can deploy the application archive (ttjan2004.ear) on
the J2EE 1.4 Application Server using the deploytool program or
the admin console. You can also deploy it by issuing the asadmin
command as follows:
asadmin deploy install_dir/ttjan2004.ear
Replace install_dir with the directory in which you installed the
ear file.
You can access the application at http://localhost:8000/ttjan2004.
For a J2EE 1.4-compliant implementation other than the J2EE 1.4
Application Server, use your J2EE product's deployment tools to
deploy the application on your platform.
. . . . . . . . . . . . . . . . . . . . . . .
IMPORTANT: Please read our Terms of Use, Privacy, and Licensing
policies:
http://www.sun.com/share/text/termsofuse.html
http://www.sun.com/privacy/
http://developers.sun.com/dispatcher.jsp?uid=6910008
* FEEDBACK
Comments? Send your feedback on the Enterprise Java Technologies
Tech Tips to:
http://developers.sun.com/contact/feedback.jsp?category=sdn
* SUBSCRIBE/UNSUBSCRIBE
Subscribe to other Java developer Tech Tips:
- Core Java Technologies Tech Tips. Get tips on using core
Java technologies and APIs, such as those in the Java 2
Platform, Standard Edition (J2SE).
- Wireless Developer Tech Tips. Get tips on using wireless
Java technologies and APIs, such as those in the Java 2
Platform, Micro Edition (J2ME).
To subscribe to these and other JDC publications:
- Go to the JDC Newsletters and Publications page,
(https://softwarereg.sun.com/registration/developer/en_US/subscriptions),
choose the newsletters you want to subscribe to and click
"Update".
- To unsubscribe, go to the subscriptions page,
(https://softwarereg.sun.com/registration/developer/en_US/subscriptions),
uncheck the appropriate checkbox, and click "Update".
- To use our one-click unsubscribe facility, see the link at
the end of this email:
- ARCHIVES
You'll find the Enterprise Java Technologies Tech Tips archives at:
http://java.sun.com/developer/EJTechTips/index.html
- COPYRIGHT
Copyright 2004 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.
This document is protected by copyright. For more information, see:
http://java.sun.com/developer/copyright.html
Enterprise Java Technologies Tech Tips
January 26, 2004
Trademark Information: http://www.sun.com/suntrademarks/
Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks
or registered trademarks of Sun Microsystems, Inc. in the
United States and other countries.