Search This Blog


Friday, July 27, 2012

EL: Expression language 2.2 Distilled

Here I will give a brief introduction and also some improvement done in JSR 245, The Expression Language (also referred to as the EL),
which provides an important mechanism for enabling the presentation layer (web pages) to communicate with the application logic (managed beans).

The EL is used by both JavaServer Faces technology and JavaServer Pages (JSP) technology.

The EL represents a union of the expression languages offered by JavaServer Faces technology and JSP technology.

The EL allows page authors to use simple expressions to dynamically access data from JavaBeans components.

For example, the test attribute of the following conditional tag is supplied with an EL expression that compares 0 with the number of items in the session-scoped bean named cart.

JavaServer Faces technology uses the EL for the following functions:
  • Deferred and immediate evaluation of expressions.

  • The ability to set as well as get data.

  • The ability to invoke methods.

To summarize, the EL provides a way to use simple expressions to perform the following tasks:
  • Dynamically read application data stored in JavaBeans components, various data structures, and implicit objects.

  • Dynamically write data, such as user input into forms, to JavaBeans components.

  • Invoke arbitrary static and public methods.

  • Dynamically perform arithmetic operations.

The EL is also used to specify the following kinds of expressions that a custom tag attribute will accept:
  • Immediate evaluation expressions or deferred evaluation expressions. An immediate evaluation expression is evaluated at once by the underlying technology, such as JavaServer Faces.

    A deferred evaluation expression can be evaluated later by the underlying technology using the EL.

  • Value expression or method expression. A value expression references data, whereas a method expression invokes a method.

  • Rvalue expression or lvalue expression. An rvalue expression can only read a value, whereas an lvalue expression can both read and write that value to an external object.

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 returned as soon as the page is first rendered.

Deferred evaluation means that the technology using the expression language can use its own machinery to evaluate the expression sometime later during the page’s lifecycle, whenever it is appropriate to do so, because of its multiphase lifecycle, JavaServer Faces technology uses mostly deferred evaluation expressions.

Those expressions that are evaluated immediately use the ${} syntax. Expressions whose evaluation is deferred use the #{} syntax.
  1. Immediate Evaluation
    All expressions using the ${} syntax are evaluated immediately. These expressions can be used only 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:

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

    Immediate evaluation expressions are always read-only value expressions. The preceding example expression cannot set the total price, but instead can only get the total price from the cart bean.

  2. 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 h:inputText tag, which represents a text field component into which a user enters a value. The h:inputText tag’s value attribute references a deferred evaluation expression that points to the name property of the customer bean:

    For an initial request of the page containing this tag, the JavaServer Faces implementation evaluates the #{} 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.

    • 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 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:

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.

Method Expressions
Another feature of the EL 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 for validating component data, as shown in this example:

The h:inputText tag displays as a text field. The validator attribute of this h: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.

Parameterized Method Calls
The EL offers support for parameterized method calls.Method calls can use parameters without having to use static EL functions.

Both the . and [] operators can be used for invoking method calls with parameters, as shown in the following expression syntax:
  • expr-a[expr-b](parameters)

  • expr-a.identifier-b(parameters)
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 that 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 zero 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 the guessnumber application, a random number is provided as an argument rather than from user input to the method call:

The preceding example uses a value expression.

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

The EL expression calls 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:

In the preceding example, you are passing the string ’SOMESTOCK’ (a stock symbol) as a parameter to the buy method.

Literal Expressions
A literal expression is evaluated to the text of the expression, which is of type String. A literal expression 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:
  • By creating a composite expression as shown here:
    • ${’${’}exprA}
    • #{’#{’}exprB}
    The resulting values would then be the strings ${exprA} and #{exprB}.

  • By using the escape characters \$ and \# to escape what would otherwise be treated as an eval-expression:
    • \${exprA}
    • \#{exprB}
The resulting values would again be the strings ${exprA} and #{exprB}. When a literal expression is evaluated, it can be converted to another type.

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, when referencing a value, the literal expression is evaluated at a point in the lifecycle that is determined by other factors, such as 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.