JSF and the Unified Expression Language (EL)

The expression language (EL) was introduced as part of the JavaServer Pages Standard Tag Library (JSTL) version 1.0 as a simple way to access external data objects ie. JavaBeans. ${employee.name} this expression calls the getName method of the employee JavaBean. The expression language greatly reduced scripting in JSPs, flattened the learning curve for front-end development etc.

The expression language became included in the JSP 2.0 specification as a result of its popularity, and it was enhanced. As well as using expressions in standard tag attributes as they could in version 1.0, they could also be used in template text and with custom tags to call functions on those tags which could invoke static methods.

JavaServer Faces (JSF)

Around the same time that JSP 2.0 was released, JSF was introduced. JSF has a flexible UI component model and includes:

  • a set of classes that define UI components
  • an event handling mechanism for the events those components generate
  • process for conversion and validation of component data
  • set of component tags that are used to map directly to stateful, server-side data objects

It was clear that JSF required an expression language to wire component events to handlers, bind the component tags to data objects, and register convertors and validators with components. The expression language included as part of JSP 2.0 wasn’t sufficient however, mainly due to the different way that JSP and JSF work. The main limitation of the JSP EL is that its expressions are evaluated immediately ie. the JSP container immediately parses and resolves the expression when it processes the page and returns the response.

Immediate evaluation is sufficient for the first time that a JSF page gets rendered, but not for subsequent requests. This is because, in JSF, when data is submitted by a user with a component, there are 4 separate tasks which are split into different life-cycle phases:

  1. data is converted into appropriate types
  2. data is validated
  3. then is is propogated to server-side objects
  4. component events are processes

Because of this life-cycle, it is important that expressions can be evaulated at the different phases rather than immediately as is done in JSPs. Another issue is that immediate evaluation is read-only whereas JSF components need to be able to write data to server-side objects during the postback. Lastly, JSF components need to be able to invoke public methods on server-side objects in order to validate data and handle events, but JSP functions can only call static methods defined in a TLD file.

The new expression language required:

  • deferred expressions, evaluated at different stages in the page life-cycle
  • expressions that can set data as well as read it
  • method expressions that can invoke public methods on server-side objects that handle events, validation and other functions

Conflicts between JSP EL and JSF EL

It is possible to mix JSF component tags with JSTL tags, however this causes problems because the JSP EL expressions used in the JSTL tags are evaluated immediately, whereas the  expressions used in the JSF component tags are evaluated at different phases.

<c:forEach var=”employee” items=”${company.employees}” > – JSTL tag with JSP EL expression

<h:inputText id=”name” value=”#{employee.name}” /> – JSF component tag with JSF EL expression

The Unified Expression Language

Because of these problems it was necessary to unify these expression languages if java-based web component development was to continue. The new expression language is flexible and pluggable, and as well as having deferred evaluation, expressions to set data, and method expressions, it also supports using JSTL iteration tags with deferred expressions and provides a pluggable API for resolving expressions

Immediate vs. Deferred Evaluation

The JSP engine evaluates expressions such as the one below immediately, in this case reading the ‘total’ value from the ‘inventory’ object, formatting(converting) it and passes it back to the tag handler. These expressions are always read-only

<fmt:formatNumber value=”${inventory.total}” />

Deferred evaluation means that the unified EL expressions #{expr} are not evaluated by the JSP engine but are managed by the JSF controller which can evaulate them at different phases in the life-cycle – the phase being determined by how they have been used in the page.

<h:inputText id=”name” value=”#{employee.name}” />

In the above example, the JSF evaluates the employee.name during the render response phase for the initial page request. For subsequent postbacks however, the expression gets evaluated during the following phases:

  1. apply request values – value retrieved from request
  2. process validations
  3. update model phases – validated data propagated to the bean

The unified EL supports 2 kinds of expressions:

  1. Value Expressions
    these reference data – ie. bean properties, other data structure, literal values. They can be further categorized asRvalue expressions which only read data, and Lvalue expressions which can do both. Expressions that are evaluated immediately are always rvalue expressions whereas deferred evaluation expressions can be both.${employee.name} – rvalue expression (immediate evaluation )syntax
    #{employee.name} – lvalue expression, can be immediate or deferred (deferred evaluation syntax)

During an initial request, the second expression will be evaluated immediately, so although it uses the deferred syntax, it will be an rvalue expression. During postback however, the second one may set propertys and so it will be an lvalue expression

  1. Method Expressions
    Another motivation for creating JSF EL was method epxression support, where public methods can be called to handle events and validate data.

NOTE: The unified EL means that features such as method expressions are not exclusively for JSF applications but can be used by any supporting technology.

Pluggable Resolver

The JSP engine (immediate evaluation) or the JavaServer Faces implementation (deferred evaluation) know how expressions refer to objects or methods via resolvers. The unified EL specification defines a generic ELResolver class and a set of ELResolver implementations that define how to resolve various kinds of expressions. The set of standard resolvers include those that resolve expressions that point to arrays, JavaBeans components, lists, maps, and resource bundles.

Application developers can also provide their own custom ELResolver implementations to resolve expressions that can’t be handled by the standard resolvers and plug these resolvers into their applications.

Examples of pluggable resolvers include those that handle:

* Connections to resources such as JNDI and JDBC resources
* Implicit objects
* Methods that don’t follow JavaBeans conventions

Writing a custom resolver and including it in your application can be quite simple. In general, it involves:

* Writing an implementation of ELResolver
* Registering the ELResolver implementation with the application
* Using expressions in the page

Leave a Reply

Your email address will not be published. Required fields are marked *