The Java EE 6 Tutorial, Volume I

Overview of EL

The unified expression language allows page authors to use simple expressions to dynamically access data from JavaBeansTM components. For example, the test attribute of the following conditional tag is supplied with an EL expression that compares the number of items in the session-scoped bean named cart with 0.

<c:if test="${sessionScope.cart.numberOfItems > 0}">
  ...
</c:if>

JavaServer Faces technology uses EL for the following functions:

See Using the EL to Reference Backing Beans for more information on how to use the EL in JavaServer Faces applications.

To summarize, the unified expression language provides a way to use simple expressions to perform the following tasks:

The EL is also used to specify the following kinds of expressions that a custom tag attribute will accept:

Finally, the EL provides a pluggable API for resolving expressions so custom resolvers that can handle expressions not already supported by the EL can be implemented.

This section gives an overview of the unified expression language features by explaining the following topics:

In addition to the above, JSP technology-related topics such as implicit objects and functions are also relevant to EL users but they are not covered in this tutorial.

Immediate and Deferred Evaluation Syntax

The EL supports both immediate and deferred evaluation of expressions. Immediate evaluation means that the expression is evaluated and the result is returned immediately when the page is first rendered. Deferred evaluation means that the technology using the expression language can employ its own machinery to evaluate the expression sometime later during the page’s lifecycle, whenever it is appropriate to do so.

Those expressions that are evaluated immediately use the ${} syntax. Expressions whose evaluation is deferred use the #{} syntax.

Because of its multiphase lifecycle, JavaServer Faces technology mostly uses deferred evaluation expressions. During the lifecycle, component events are handled, data is validated, and other tasks are performed in a particular order. Therefore, a JavaServer Faces implementation must defer evaluation of expressions until the appropriate point in the lifecycle.

Other technologies using the EL might have different reasons for using deferred expressions.

Immediate Evaluation

All expressions using the ${} syntax are evaluated immediately. These expressions can only be used within template text or as the value of a tag attribute that can accept runtime expressions.

The following example shows a tag whose value attribute references an immediate evaluation expression that gets the total price from the session-scoped bean named cart:

<fmt:formatNumber value="${sessionScope.cart.total}"/>

The JavaServer Faces implementation evaluates the expression, ${sessionScope.cart.total}, converts it, and passes the returned value to the tag handler.

Immediate evaluation expressions are always read-only value expressions. The example expression shown above can only get the total price from the cart bean; it cannot set the total price.

Deferred Evaluation

Deferred evaluation expressions take the form #{expr} and can be evaluated at other phases of a page lifecycle as defined by whatever technology is using the expression. In the case of JavaServer Faces technology, its controller can evaluate the expression at different phases of the lifecycle depending on how the expression is being used in the page.

The following example shows a JavaServer Faces inputText tag, which represents a text field component into which a user enters a value. The inputText tag’s value attribute references a deferred evaluation expression that points to the name property of the customer bean.

<h:inputText id="name" value="#{customer.name}" />

For an initial request of the page containing this tag, the JavaServer Faces implementation evaluates the #{customer.name} expression during the render response phase of the lifecycle. During this phase, the expression merely accesses the value of name from the customer bean, as is done in immediate evaluation.

For a postback request, the JavaServer Faces implementation evaluates the expression at different phases of the lifecycle, during which the value is retrieved from the request, validated, and propagated to the customer bean.

As shown in this example, deferred evaluation expressions can be value expressions that can be used to both read and write data. They can also be method expressions. Value expressions (both immediate and deferred) and method expressions are explained in the next section.

Value and Method Expressions

The EL defines two kinds of expressions: value expressions and method expressions. Value expressions can either yield a value or set a value. Method expressions reference methods that can be invoked and can return a value.

Value Expressions

Value expressions can be further categorized into rvalue and lvalue expressions. Rvalue expressions are those that can read data, but cannot write it. Lvalue expressions can both read and write data.

All expressions that are evaluated immediately use the ${} delimiters and are always rvalue expressions. Expressions whose evaluation can be deferred use the #{} delimiters and can act as both rvalue and lvalue expressions. Consider the following two value expressions:

${customer.name}
#{customer.name}

The former uses immediate evaluation syntax, whereas the latter uses deferred evaluation syntax. The first expression accesses the name property, gets its value, adds the value to the response, and gets rendered on the page. The same can happen with the second expression. However, the tag handler can defer the evaluation of this expression to a later time in the page lifecycle, if the technology using this tag allows.

In the case of JavaServer Faces technology, the latter tag’s expression is evaluated immediately during an initial request for the page. In this case, this expression acts as an rvalue expression. During a postback request, this expression can be used to set the value of the name property with user input. In this case, the expression acts as an lvalue expression.

Referencing Objects Using Value Expressions

Both rvalue and lvalue expressions can refer to the following objects and their properties or attributes:

To refer to these objects, you write an expression using a variable which is the name of the object. The following expression references a backing bean (a JavaBeans component) called customer.

${customer}

The web container evaluates the variable that appears in an expression by looking up its value according to the behavior of PageContext.findAttribute(String), where the String argument is the name of the variable. For example, when evaluating the expression ${customer}, the container will look for customer in the page, request, session, and application scopes and will return its value. If customer is not found, null is returned.

You can alter the way variables are resolved with a custom EL resolver. For instance, you can provide an EL resolver that intercepts objects with the name customer, so that ${customer} returns a value in the EL resolver instead. Creation of custom EL resolvers is an advanced topic covered in Java EE 6 Tutorial, Volume II: Advanced Topics.

To reference an enum constant with an expression, use a String literal. For example, consider this Enum class:

public enum Suit {hearts, spades, diamonds, clubs}

To refer to the Suit constant, Suit.hearts with an expression, you use the String literal, "hearts". Depending on the context, the String literal is converted to the enum constant automatically. For example, in the following expression in which mySuit is an instance of Suit, "hearts" is first converted to Suit.hearts before it is compared to the instance.

${mySuit == "hearts"}

Referring to Object Properties Using Value Expressions

To refer to properties of a bean or an Enum instance, items of a collection, or attributes of an implicit object, you use the . or [] notation, which is similar to the notation used by ECMAScript language. For more information on ECMAScript, see http://www.ecmascript.org.

If you want to reference the name property of the customer bean, use either the expression ${customer.name} or the expression ${customer["name"]}. The part inside the square brackets is a String literal that is the name of the property to reference.

You can use double or single quotes for the String literal. You can also combine the [] and . notations, as shown here:

${customer.address["street"]}

Properties of an enum can also be referenced in this way. However, as with JavaBeans component properties, the properties of an Enum class must follow JavaBeans component conventions. This means that a property must at least have an accessor method called get<Property> where <Property> is the name of the property which can be referenced by an expression.

For example, consider an Enum class that encapsulates the names of the planets of our galaxy and includes a method to get the mass of a planet. You can use the following expression to reference the method getMass of the Planet Enum class:

${myPlanet.mass}

If you are accessing an item in an array or list, you must use either a literal value that can be converted to int or the [] notation with an int and without quotes. The following examples could all resolve to the same item in a list or array, assuming that socks can be converted to int:

In contrast, an item in a Map can be accessed using a string literal key; no coercion is required:

${customer.orders["socks"]}

An rvalue expression also refers directly to values that are not objects, such as the result of arithmetic operations and literal values, as shown by these examples:

The unified expression language defines the following literals:

You can also write expressions that perform operations on an enum constant. For example, consider the following Enum class:

public enum Suit {club, diamond, heart, spade }

After declaring an enum constant called mySuit, you can write the following expression to test if mySuit is spade:

${mySuit == "spade"}

When the EL resolving mechanism resolves this expression, it will invoke the valueOf method of the Enum class with the Suit class and the spade type, as shown here:

mySuit.valueOf(Suit.class, "spade"}

Where Value Expressions Can Be Used

Value expressions using the ${} delimiters can be used in the following places:

The value of an expression in static text is computed and inserted into the current output. Here is an example of an expression embedded in static text:

<some:tag>
    some text ${expr} some text
</some:tag>

If the static text appears in a tag body, note that an expression will not be evaluated if the body is declared to be tagdependent.

Lvalue expressions can only be used in tag attributes that can accept lvalue expressions.

There are three ways to set a tag attribute value using either an rvalue or lvalue expression:

All expressions used to set attribute values are evaluated in the context of an expected type. If the result of the expression evaluation does not match the expected type exactly, a type conversion will be performed. For example, the expression ${1.2E4} provided as the value of an attribute of type float will result in the following conversion:

Float.valueOf("1.2E4").floatValue()

See Section 1.18 of the JavaServer Pages 2.1 Expression Language Specification (available from http://jcp.org/aboutJava/communityprocess/final/jsr245/) for the complete type conversion rules.

Method Expressions

Another feature of the unified expression language is its support of deferred method expressions. A method expression is used to invoke an arbitrary public method of a bean, which can return a result.

In JavaServer Faces technology, a component tag represents a component on a page. The component tag uses method expressions to invoke methods that perform some processing for the component. These methods are necessary for handling events that the components generate and validating component data, as shown in this example:

<h:form>
    <h:inputText
        id="name"
        value="#{customer.name}"
        validator="#{customer.validateName}"/>
    <h:commandButton
        id="submit"
        action="#{customer.submit}" />
</h:form>

The inputText tag displays as a text field. The validator attribute of this inputText tag references a method, called validateName, in the bean, called customer.

Because a method can be invoked during different phases of the lifecycle, method expressions must always use the deferred evaluation syntax.

Like lvalue expressions, method expressions can use the . and the [] operators. For example, #{object.method} is equivalent to #{object["method"]}. The literal inside the [] is converted to String and is used to find the name of the method that matches it. Once the method is found, it is invoked or information about the method is returned.

Method expressions can be used only in tag attributes and only in the following ways:

Parameterized Method Calls

The updated EL version 2.1.2 included in Java EE 6 offers support for parameters to method calls. Method calls can now use parameters (or arguments) without having to use static EL functions.

Both the . and [] operators can be used for invoking method calls with parameters as shown in expression syntax below:

In the first expression syntax, expr-a is evaluated to represent a bean object. The expression expr-b is evaluated and cast to a string which represents a method in the bean represented by expr-a. In the second expression syntax, expr-a is evaluated to represent a bean object and identifier-b is a string that represents a method in the bean object. The parameters in parentheses are the arguments for the method invocation. Parameters can be 0 or more values or expressions, separated by commas.

Parameters are supported for both value expressions and method expressions. In the following example, which is a modified tag from guessNumber application, a random number is provided as an argument rather than from user input to the method call:

<h:inputText value="#{userNumberBean.userNumber('5')}">

The above example uses a value expression.

Consider the following example of a JavaServer Faces component tag which uses a method expression:

<h:commandButton action="#{trader.buy}" value="buy"/>

where EL expression trader.buy is calling the trader bean's buy method. You can modify the tag to pass on a parameter. Here is the revised tag where a parameter is passed:

<h:commandButton action="#{trader.buy('JAVA')}" value="buy"/>

In the above example you are passing the string 'JAVA' (a stock symbol) as a parameter to the buy method.

For more information on the updated EL, see https://uel.dev.java.net.

Defining a Tag Attribute Type

As explained in the previous section, all kinds of expressions can be used in tag attributes. Which kind of expression and how that expression is evaluated (whether immediately or deferred) is determined by the type attribute of the tag’s definition in the Page Description Language (PDL) that defines the tag.

If you plan to create custom tags, for each tag in the PDL, you need to specify what kind of expression to accept. Table 6–1 shows the three different kinds of tag attributes that accept EL expressions, gives examples of expressions they accept, and the type definitions of the attributes that must be added to the PDL. You cannot use #{} syntax for a dynamic attribute, meaning an attribute that accepts dynamically-calculated values at runtime. Similarly, you also cannot use the ${} syntax for a deferred attribute.

Table 6–1 Definitions of Tag Attributes That Accept EL Expressions

Attribute Type 

Example Expression 

Type Attribute Definition 

dynamic 

"literal"

<rtexprvalue>true</rtexprvalue>

${literal}

<rtexprvalue>true</rtexprvalue>

deferred value 

"literal"

<deferred-value>
   <type>java.lang.String</type>
</deferred-value>

#{customer.age}

<deferred-value>
   <type>int</type>
</deferred-value>

deferred method 

"literal"

<deferred-method>
   <method-signature>
      java.lang.String submit()
   </method-signature>
<deferred-method>

#{customer.calcTotal}

<deferred-method>
   <method-signature>
      double calcTotal(int, double)
   </method-signature>
</deferred-method>

In addition to the tag attribute types shown in Table 6–1, you can also define an attribute to accept both dynamic and deferred expressions. In this case, the tag attribute definition contains both an rtexprvalue definition set to true and either a deferred-value or deferred-method definition.

Literal Expressions

A literal expression is evaluated to the text of the expression, which is of type String. It does not use the ${} or #{} delimiters.

If you have a literal expression that includes the reserved ${} or #{} syntax, you need to escape these characters as follows.

When a literal expression is evaluated, it can be converted to another type. Table 6–2 shows examples of various literal expressions and their expected types and resulting values.

Table 6–2 Literal Expressions

Expression 

Expected Type 

Result 

Hi

String

Hi

true

Boolean

Boolean.TRUE

42

int

42

Literal expressions can be evaluated immediately or deferred, and can be either value or method expressions. At what point a literal expression is evaluated depends on where it is being used. If the tag attribute that uses the literal expression is defined to accept a deferred value expression, then when the literal expression references a value, it is evaluated at a point in the lifecycle that is determined by other factors. The other factors include where the expression is being used and to what it is referring.

In the case of a method expression, the method that is referenced is invoked and returns the specified String literal. For example, the commandButton tag of the guessNumber application uses a literal method expression as a logical outcome to tell the JavaServer Faces navigation system which page to display next.

Operators

In addition to the . and [] operators discussed in Value and Method Expressions, the unified expression language provides the following operators, which can be used in rvalue expressions only:

The precedence of operators highest to lowest, left to right is as follows:

Reserved Words

The following words are reserved for the unified expression language and should not be used as identifiers.

and

or

not

eq

ne

lt

gt

le

ge

true

false

null

instanceof

empty

div

mod

Examples of EL Expressions

Table 6–3 contains example EL expressions and the result of evaluating them.

Table 6–3 Example Expressions

EL Expression 

Result 

${1 > (4/2)}

false

${4.0 >= 3}

true

${100.0 == 100}

true

${(10*10) ne 100}

false

${'a' < 'b'}

true

${'hip' gt 'hit'}

false

${4 > 3}

true

${1.2E4 + 1.4}

12001.4

${3 div 4}

0.75

${10 mod 4}

2

${!empty param.Add}

False if the request parameter named Add is null or an empty string

${pageContext.request.contextPath}

The context path. 

${sessionScope.cart.numberOfItems}

The value of the numberOfItems property of the session-scoped attribute named cart.

${param['mycom.productId']}

The value of the request parameter named mycom.productId.

${header["host"]}

The host. 

${departments[deptName]}

The value of the entry named deptName in the departments map.

${requestScope[’javax.servlet.forward.servlet_path’]}

The value of the request-scoped attribute named javax.servlet.forward.servlet_path.

#{customer.lName}

Gets the value of the property lName from the customer bean during an initial request. Sets the value of lName during a postback.

#{customer.calcTotal}

The return value of the method calcTotal of the customer bean.