Help

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

Proposed enhancements to Unified EL

This page consists of an agenda and proposals put forth by Red Hat and its community for the (planned) Unified EL JSR. Each issue is prioritized by importance, P1 being the highest and P3 the lowest.

Current status

Previously, the Unified EL specification existed as Part II of JSR-245: JavaServer Pages 2.1. The last maintenance release (Dec 2009) covers the specification for EL 2.2.

Table of contents

Bootstrapping the ELContext (P1)

Current the ELContext is created in the UI layer, either by JavaServer Faces or JSP. However, EL is an essential part of the Java EE programming model. It would make a lot more sense if the ELContext would be created at the start of the request so that components such as filters, custom servlets and third-party frameworks could access the EL. Currently, it's necessary to manually construct an EL context if an expression needs to be resolved outside of JSF or JSP.

What we are looking for is something similar to the bootstrap that was introduced for Bean Validation. Like Bean Validation, EL transcends the layers of the programming model and should therefore be universally accessible.

Simplifying the expression evaluator API (P1)

It's way too complicated to resolve an EL expression. If you think about it, the task is quite simple. Take an expression string and get a result. We need to make the API as simple as the task.

Part of the problem with the Unified EL is that just trying to figure out what you need to actually resolve an expression is a nightmare. It breaks down into three parts:

  • ELContext - Simply put, To evaluate an Expression, an ELContext must be provided. A real bitch.
  • ExpressionFactory - Needed to create a ValueExpression or MethodExpression from a string
  • ELResolver - The thing that actually parses the expression and deferences its parts; each job is handled by a different resolver (one being to find CDI beans by name) and those resolvers are wrapped in a resolver which is a chain of resolver

What isn't provided is a simple API to just take an expression and get a result from it.

API for registering functions (P1)

There are currently two options for registering a function. You can either introduce your own FunctionMapper into the ELContext or you can register a function using a UI-specific configuration file (Facelets, JSP). There should be a way to associate a function with a namespace using a Java API and an alternate UI-agnostic configuration format.

Java 5 Enum support (P1)

Need first class support for Java 5 Enums constants. Either the constants should be allowed to be referenced from a base that resolves to the Enum:

  • days.MONDAY -> com.acme.Days.MONDAY

or the EL should allow the fully qualified Enum class to be referenced:

  • com.acme.Days.MONDAY -> com.acme.Days.MONDAY

The second option may be better because it doesn't require a context variable to resolve to an Enum instance just to access the other constants.

Evaluation of static members (P1)

The EL has always dealt with instance methods, but there is no reason why static methods--or even static members in general--cannot be supported. In this case, both non-static and static members are searched when resolving a method.

  • person.formatName(person, formatType) -> formatName(com.acme.Person, java.lang.String) static method on the com.acme.Person class, passing the value of the person and formatType instance variables as arguments

It would also be convenient to support direct access of public static fields as well

  • registration.DEFAULT_ROLE -> DEFAULT_ROLE static field on the com.acme.Registration class

In both cases, the resolved base serves only to determine the class to search (rather than a specific instance).

Proper coercion (P2)

EL tries to coerce a null-value to the expected type.

An example: you bind the collapsed property of a container to a backing-bean property, and return null, to indicate that this container should not be collapsible at all - the specified EL conversion will create false out of this value.

This could be an issue which is specific to an EL consumer, such as Facelets, but there are some concerns over the way that values are coerced by the EL. The issue is described in the following blog entry:

EL namespaces (P2)

JSR-299 is introducing several standard EL names, one of which is javax.enterprise.conversation. As you can see, the name uses the familiar namespace syntax from Java. Therefore, it would be ideal if EL could formally recognize the use of namespaces for two reasons:

  1. Efficiency in resolving
  2. Namespace imports

Importing namespaces would allow for libraries to define standard EL names with namespace prefixes, but allow the page author the convince of using the unqualified name. The import mechanism should be a feature of the EL API and the declaration of the import be left up to the EL environment (e.g., JSF template).

Collection size operator (P2)

Amazingly, there is no simple way to determine the size of a collection in EL! Literal methods in EL 2.2 get you part of the way there:

#{collection.size()}

But that only works for collections that have a size method. Remaining consist with the empty operator, we should offer a sizeof (or size) operator as well.

#{sizeof collection}

This operator should work for any Collection, Map, String or Iterable. Furthermore, the empty operator should be extended to support Map and Iterable.

Date and time support (P2)

Currently, there is no way to compare dates and times in EL. The <, >, <= and >= operators should be extended to support java.util.Date. It may also be worth introducing a syntax for date/time literals.

String concatenation (P2)

#{query.order == property + ' asc' ? ' desc' : ' asc'}

Object equality operator (P2)

Introduce the === operator to test for object identity (the reserved word for this could be is to complement eq)

EL interceptors (P2)

e.g., for timing

Caching (P2)

EL Cache scoped to the request, for larger pages this provides an immediate sizable speed increase.

Projections / Collection iteration (P3)

This feature is a kind of poor-man's closure support. It should work for all instances of Iterable.

The following suggested syntax returns the list {2, 3, 4}:

#{{1, 2, 3} collect { x -> x+1 }}

The following returns {2, 3}:

#{{1, 2, 3} select { x -> x>1 }}

The following returns the object 2:

#{{1, 2, 3} detect { x -> x>1 }}

The following returns the object 3:

#{{1, 2, 3} detect { max, x -> max>=x }}

The following returns {3, 2, 1}:

#{{1, 2, 3} desc}#

The following sorts the customers by name:

#{{customers asc { c -> customer.name }}

An alternative approach might be to copy Python's list comprehensions:

#{[ x+1 for x in {1, 2, 3} where x>1 ]}

which results in {3, 4}.

JBoss EL supports a feature known as projections, which is similar to this request. Projections are rudimentary closures that allow the dynamic creation of collections from properties of child elements:

  • blocks.{b|b.color} -> a collection (java.util.List) of colors read from each block in the collection resolved from the instance variable named blocks

Switch statements (P3)

In JSP or JSF pages it's very useful to be able to handle multiple cases in a single expression.

Suggested syntax:

#{switch (order.status) { case OPEN: 'Open' case CLOSED: 'Closed' else '' }}

Collection constructors (P3)

When defining pages, it is useful to be able to iterate over collection literals.

Suggested syntax for creating a java.util.List instance:

#{{'foo', 'bar', 'baz'}}

Suggested syntax for creating a java.util.Map instance:

#{{'foo'->1, 'bar'->3}}

Suggested syntax for creating a java.util.List instance with for a specified range of integers:

#{{1...100}}

Resources

Below are links to sources of ideas for EL features.