Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Unified Expression Language Support
Requirements for Unified Expression Language (EL) Support WTP 2.0/JSF 1.0 tooling
Contents
Summary
The JavaEE 5.0 specification defines a new "Unified Expression Language" that is to be used by both release 1.2 of Java Server Faces (JSF) and release 2.1 of Java Server Pages (JSP). The new EL language is intended to be completely independent of its container (i.e. JSP). A new Java API and expression evaluation mechanism has been defined to support this container independence. The new evaluation mechanism, although mostly backward compatible, has a significant impact on the way tooling supports design time expression evaluation for the purposes of such features as validation and auto-completion.
This document enumerates the changes to EL as they affect the JSP/JSF tooling and discusses framework changes that will be required to support Unified EL for Faces 1.2. Previous limitations of the framework and backward compatibility are also considered.
Appendix A contains a line item summary of new features and other requirements.
Significant language changes
The following are significant changes in Unified EL compared to the prior definition in JSP 2.0:
- Qualified functions now take precedence over the ternary operator when the ":" operator is in use. This impacts the EL parser.
- EL now supports "literal expressions". This means that what was previously considered to be non-EL value text must now be considered an EL expression.
- EL now supports Java 5.0 enumerations.
- The collected syntax now differentiates between l-value and r-value expressions.
Significant semantic changes
The following are significant changes to the way Unified EL expressions are evaluated compared to the prior definitions in JSP 2.0/JSF 1.1:
- Symbol resolution is performed by a new "container agnostic" API that defines a context and resolver chaining mechanism for determining the type and value of user symbols (i.e. model objects \[previously called variables\], properties, methods and functions).
- A new concept of EL variables is introduced. What previously were known as variables (those objects resolved by a VariableResolver) are now called "model objects". The new concept allows expressions themselves to become value objects that are stored and resolved later. This behavior is intended to support nesting of EL expressions in loop structures like c:forEach.
- EL functions are now fully supported.
Symbol Resolution
Background
In JSP 2.0 EL, there were three types of user-defined symbols: variables, properties (includes methods as a special case) and functions. In Unified EL there are now four kinds of symbols: model objects (what used to be called variables), properties (still including methods), functions and EL variables (unevaluated EL expressions stored for later use).
Resolving each type of symbol was left to the specific JSP or JSF implementation in JSP 2.0. In Unified EL however, a new API has been defined to determine how user-defined symbols should be resolved. It should be noted that only the mechanism is defined and not the source of the symbols. The source of the symbols is still left to each implementer of the EL specification to decide. The implementer provides sources of symbols by adding "Resolvers" and "Mappers" for each type of symbol. Model objects, properties and methods are resolved through a chain of ELResolver instances. Functions are resolved through a FunctionMapper. EL variables are resolved through a VariableMapper. All of these resolution classes are rooted in an ELContext that is provided by the implementer, for each context in which it wishes to support expressions.
JSF 1.2 supports two contexts for EL resolution: one for JSP and one for Java. Each context contains its own chain of resolvers.
Design Time Requirements
To support design time resolution of EL symbols, a new analog to the runtime behavior must be created. This new analog must maintain the following existing contract of the design time resolver framework:
- Allow each web application (as defined at design time by a dynamic web project rooted in an IProject) to have its own customized resolution mechanism for each kind of EL symbol.
- Enable the symbol context resolver to serve as a single point of access through which all the symbols available in a particular design time context can be obtained.
- Allow third parties to modify the way symbols are resolved in ways that match the way the can be modified at runtime. Third parties may change symbol resolution by either changing the configuration (i.e. adding resolver information to a faces-config.xml) or by generalized mechanisms for adding symbols to the runtime scoped symbol maps (i.e. f:loadBundle adds a model object symbol and related property symbols to the request map through execution of its tag library code).
To support both new requirements and backward compatibility, the new framework must also conform to the following new contract:
- The behavior of the framework must adapt to the version of JSF/JSP selected by JSFDeveloper for each project. The versioning is tied to the facet version in use. Projects flagged as being JSF 1.1 must continue to work as before, whereas JSF 1.2 projects must use the new behavior.
- The framework must flag illegal combinations of different J2EE runtime versions. For example, Java 1.5 or above is required for JSF 1.2. Attempting to use Java 1.4 with JSF 1.2 must be constrained by the framework.
- The framework must be flexible enough to allow each web application (as defined at design time by a dynamic web project rooted in an IProject) to have entirely different symbol resolution in different application contexts. For example, Faces 1.2 supports two different ELResolvers depending on where an expression is being resolved.
- The framework must allow third parties to modify the way symbols are resolved in each of the possible application contexts. This matches the previous requirement with respect to third party modifications but is now expanded to each application context (i.e. JSP vs. Faces).
- The framework must provide a simple but comprehensive way for JSFDeveloper to manage these new behaviors on each web application within the constraints of providing correct design time behavior. This includes managing third-party contributions and the ability to enable or disable functionality in ways that match what could happen at runtime.
EL Variables
Here is an example of the use of an EL variable:
<c:forEach var="book" items="\#\{BooksBean.books\}"> <h:inputText id="quantity" value="\#\{book.quantity\}" ... /> </c:forEach>
The fragment shows a c:forEach creating a variable called "book" whose value is the expression "\#\{BooksBean.books\}". When h:inputText evaluates "book" in its value attribute, the correct instance is evaluated based on the instance of BooksBean.books that was selected for that collection on a particular iteration of the forEach.
EL variables represent a problem space for design time symbol resolution that is already solved by the contextSymbolFactory extension point. However, the introduction of EL variables expands the problem space because non-JSF tags such as c:forEach can now declare EL model object symbols.
We need to add a contextSymbolFactory provider for all JSTL tags that contribute EL Variables in this way and ensure that third parties can contribute similar providers for other non-JSF tag libraries.
EL Functions
EL functions were supported in JSP 2.0 EL, but there was no direct way to use them in JSF 1.1. Unified EL now provides a way for EL functions to be used by EL in JSF.
EL functions are a way of accessing static (not associated with a model object) methods from Java classes. Unified EL provides a class called FunctionMapper accessible from the ELContext that maps a function name to a static method on a Java class.
An EL function has the following general structure:
ns:funcName(arg1, arg2 … )
Here "ns" refers to a namespace and "funcName)" is the name of a function. Namespace normally corresponds to a class or tag library and function name to a static method name on some class. The actual meaning is dependent on what the installed FunctionMapper does with the namespace/function name combination. Note that the namespace is optional; if missing then a "default namespace" is assumed. Notice how these semantics are similar to XML element namespaces.
To support similar features for functions to those we support for model objects (i.e. validation, content assist), a new DTFunctionResolver is required that mirrors the FunctionMapper behavior in each application context.
Syntax Changes
Colon operator precedence
Modifications of the parser is required to support the change in precedence of the function namespace operator ":". In JSP 2.0 EL, there was an ambiguity created in the specification between the function and ternary operators. This ambiguity has been fixed by making ":" associate to functions have precedence over ternary association. So:
x ? y : z()
is illegal since "y:z()" will resolve to a function and the ternary operator started with the "x ? ", will be incomplete because it lacks an else statement. To express this in a way that says "if x then y else call z()", explicit associatively must be declared using extra braces:
x ? y : (z())
WTP 1.5 shipped with a bug related to parsing ternaries related to this ambiguity (see bugzilla: 145934). This bug can be fixed at same time as updating for the clarified precedence rule.
Expression evaluation changes
The grammar has been changed to differentiate between r-value and l-value expressions. R-value expressions are pure value expressions and map to those that could exist on the right side of an assignment (\’=\’) statement. L-value expressions are those that point to an assignable storage location – that is, an expression that could exist on the left side of an assignment statement. Depending what is already known about an expression (for example it is a method or value expression), parsing proceeds along one of two paths:
- Value expressions are first parsed as l-value expressions. If this fails, they are parsed as r-values.
- Method expressions are effectively parsed as l-value expressions only.
In addition, literal expressions must be detected separately to support both stand-alone literal expressions and mixed expressions (those containing both value expressions and static text). This requires changing the parser to detect non-value and mixed expressions.
Language Semantic Changes
Unified EL adds support for Java 1.5 enumerations. All EL AST analyzers (currently there are two for JSF: one for validation and one for content assist) must be updated to handle semantic resolution and validation of Java 1.5 enumerations.
Impact of Java 1.5
In addition to supporting enumerations, JSP 2.1 and Faces 1.2 add full support for Java 1.5. This means that generic types may now be found referenced indirectly in EL expressions. The Java type signature resolution mechanism must now be extended to support generic type matching. This includes a more robust type coercion and compatibility mechanism (i.e. TypeComparator) to ensure attribute expected types are correctly matched when generics are used.
Previous Limitations
The previous version of the JSF tooling had limitations that are addressed in WTP 2.0.
Array support (145938)
There are two ways to index properties of model objects in EL: the dot method and the array method. The dot method constitutes syntax like "obj.property". The same syntax can be expressed in the array style like this: "obj\[\’property\’\]". The WTP 1.5 release of JSF tooling does not support evaluating the array method for the purposes of supporting features like validation and content assist (although the parser appears to correctly construct the AST). In addition, where \’obj\’ can be resolved to an integer indexable list (like a java.util.List), properties can be evaluated like this: "obj\[0\]\’. There is currently no validation for integer-indexed objects.
List support (145936)
EL model objects that implement the java.util.List interface can be treated as lists when resolved in EL expressions. This limitation is partially solved in Unified EL, since a ListELResolver needs to be supported as part of basic chained resolver support. However, for JSF 1.1 applications, there is currently no tooling support for these types of model objects.
Mixed expression support (151181)
EL expressions can be "mixed" groupings of both value expression and literals (static text). For example:
<h:outputLabel value="This is a mixed expression using this value: \#\{obj.value\}"/>
In this case, the expression "obj.value" is resolved and then concatenated to the static text (literal expression) to form a final String value.
Complete EL support for core and html libraries (144525, 145939, 145288)
Full support for core (f) and html (h) component libraries was left out in WTP 1.5. Currently only limited support for loadBundle tags exists. The following additional support needs to be added to ensure complete support of the core tag libraries:
- Complete support for loadBundle including localization and default package support
- Add support for the var attribute of the h:dataTable
Composite Type Descriptors (146921)
Although not currently visible to the user the EL symbols API needs to add support for CompositeTypeDescriptors. This is necessary to resolve model objects that may be of more than one interesting type to EL. For example, a managed bean may also implement both Map and List. In this case, to more correctly evaluate EL expression types at design time, the framework must support the ability to recognize any value symbols (those that are not method expressions) as being an "instanceof" not only their core types but also all interface and super-types that may be of interest to ELResolvers (1.2) and Variable/Property Resolvers (1.1).
Validation Rule Modification
Provides new UI for JSFDeveloper to configure the enablement and severity of different EL validation rules.
Fully Managed-Bean Data (partially 146921)
Provides support for bean property data that can be associated with managed-bean instances though application configuration files. This data can be used to add additional information to such features as validation and content assist. Appendix A: Summary of New Features and Functionality
Appendix A
Table A1: Features that impact both JSP and JSF tooling.
Summary | Purpose | New API | Further Notes |
New DTFunctionResolver | Supports EL function resolutions in Unified EL | Yes. Need to support third-party replacement or decoration of function resolution | A FunctionMapper in runtime applications resolves EL functions. This FunctionMapper can be changed programmatically on any ELContext meaning that the design time must also support emulation of the capability. |
Parser changes for EL functions | Change to support EL function precedence and fix bug 145934. | No. | The common EL parser has several implementation problems that need to be fixed. |
Parser changes for l/r-value resolution. | Supports new rules introduced by Unified EL for determining how an EL expression is parsed. | No. | Changes make parsing a multi-pass exercise to determine if it is a valid l-value and r-value. |
Parser changes for literal expressions. | Requirement of Unified EL. | No. | Literal expressions (as distinct from literal values in value expressions) need to be handled to support non-value and mixed expressions. |
Table A2: Features that impact JSF tooling only
Summary | Purpose | New API | Further Notes |
Java enumeration support | New requirement in Unified EL. | No. | Java enumerations can now be used directly in EL expressions. To correctly validate and provide content assistance, support needs to be added to resolve these enumerations correctly. |
Facet-driven version of JSF application | Allow user to continue to develop JSF 1.1 application with the framework. | No. | A WTP facet-based mechanism for ensuring that a web project is internally consistent and uses the correct EL evaluation rules depending on JSFDeveloper\’s desired application version. Mechanism controls which ELResolver mechanism is used (Variable/Property Resolver for 1.1/ELResolver for 1.2). Also allows validation that the Faces implementation, application configuration, container version, tag libraries and JDK versions are all consistent, valid and properly supported for the desired JSF version. |
Multiple design time resolver context support. | Supports the requirements in Faces 1.2 and Unified EL that allow different application contexts (e.g. JSP vs. JSF) to have separately customized ELContext objects. | Yes. | In order to support new requirements such as allowing non-JSF tags to pass EL variables to JSF tags, the Unified EL design time framework must now be (or able to be) aware of all EL expressions in a JSP/JSF page and know what ELContext would be used to declare and evaluate these objects. This feature must be extensible so that third party developers can extend the mechanism to match their matching runtime behavior. |
User interface dialog tied to project/facet for EL resolver management. | Provide the user with a mechanism to modify what and how EL is being evaluated and validated. | Yes. | Unified EL creates a much more complicated scheme by which expressions are evaluated and encourages the proliferation of custom EL resolvers. There is no a priori way to control this complexity, so new UI is provided to allow JSFDeveloper determine what resolvers and resolution rules are use in a particular project and to modify these parameters within the constraints of what makes sense for a JSF application (i.e. the user is somewhat protected from themselves). |
New contextSymbolFactory for all JSTL tags that introduce EL variables that may be accessible by JSF tags. | Supports new features in JSF 1.2 that allows use of iterative (i.e. c:forEach) tags in JSF applications. | No new extension point although may need to modify existing. New API required to support 3^rd^ parties in creating their own non-JSF EL variable providers. | |
Generic type support in expression type resolution. | Because JSP2.1 requires Java 1.5, generics can be used indirectly in EL expressions (by using Java classes that use generics). | No. | The type resolution mechanisms must be updated. There are effectively two such mechanisms: one for use during evaluation of expressions and one (TypeComparator) for comparing the fully resolved type of an expression with it\’s expected type and defined in meta-data. |
Array support | Bug 145938 | No. | |
List support | Bug 145936 | No. | |
Mixed expression support | Bug 151181 | No. | |
Full support for core and html library variable contributors | Bugs 144525, 145939 | No. | |
Composite Type Descriptor | Resolves internal design flaw. | Possibly. Design analysis required. | The internal framework for describing EL symbols currently can\’t accommodate the situation where a symbol is more than one type. For example, a managed-bean can only be treated like a bean and not like a List or Map if it should also happen to be an instance of those interfaces. A new composite type descriptor is required that wraps multiple type descriptors – each one describing an individual role and type behavior for a symbol. |
Validation Rule Modification | New feature. | Yes, new extension point required allowing contributed resolvers to be configured by JSFDeveloper. | There are many validation rules which are not critical and which JSFDeveloper may wish to disable or lower the severity of. Furthermore, the new, chained ELResolver scheme introduces many more sources of symbols and their validation. UI support similar to that provided by JDT is required to allow JSFDeveloper to configure individual validation rules for EL. |
Fully Managed-Bean Data | Bug 146921 |
Appendix B: Important Feature Dependencies
B1: JSF-only dependencies on common features
- "Mixed expression support" depends on "Parser changes for literal expressions" because literal expressions may be sub-expressions of mixed expressions.
B2: Internal JSF dependencies
- "Facet-driven version of JSF application" gates all other Faces 1.2 features because it formulates the basic strategy for what version of the tooling framework to use based on what version of the application runtime (pre-1.1 vs. 1.2) the user has selected.
- "Fully Managed Bean Data" is gated by "Composite Type Descriptor" because managed bean data requires the framework to support multiple types (and thus type descriptors) on a managed bean at one time (i.e. it may be initialized as a list 'and' a map).
- "Multiple design time resolver context support" partially gates all validation and content-assist related features that rely on correct resolving of user identifies (i.e. managed beans, tag variables etc.).