Simplest Possible Expression Language (SPEL) for JSPSTL

Nathan Abramson (arista@atg.com)

Overview

The SPEL is designed to be the simplest possible JSPSTL expression language that is still useful. The only required features of the SPEL are:

The idea is to design a language that will eventually grow, keeping in mind that future versions of the language should be backwards compatible with this version of the SPEL.

Syntax

The syntax is extremely simple. Attributes are accessed by name, with an optional scope ("page:", "request:", "session:", "app:"). Properties of attributes are accessed using the "." operator, and may be nested arbitrarily. Attribute and property names must be java identifiers, unless they are quoted. Relational comparisons are allowed using the relational operators (==, !=, <, >, <=, >=). Comparisons may be made against other values, or against boolean, String, integer, or floating point literals.

The following are the constructs supported by the SPEL:
Expression ::= Value
    | RelationalExpression
RelationalExpression ::= Value RelOp Value
RelOp ::= '=='
    | '!='
    | '<'
    | '>'
    | '<='
    | '>='
Value ::= PropertyValue
    | Literal
PropertyValue ::= NamedValue
    | PropertyValue '.' Identifier
    | PropertyValue '.' StringLiteral
NamedValue ::= ScopedIdentifier
    | Identifier
ScopedIdentifier ::= ScopeName ':' Identifier
    | ScopeName ':' StringLiteral
    | ':' (Identifier | StringLiteral)
ScopeName ::= 'page'
    | 'request'
    | 'session'
    | 'app'
    | 'header'
    | 'param'
    | 'paramvalues'
Identifier ::= Java language identifier
Literal ::= BooleanLiteral
    | IntegerLiteral
    | FloatingPointLiteral
    | StringLiteral
    | NullLiteral
BooleanLiteral ::= 'true'
    | 'false'
StringLiteral ::= '([^'\]|\'|\\)*'
    | "([^'\]|\'|\\)*"
    i.e., a string of any characters enclosed by single or double quotes, where \ is used to escape ', ", and \.
IntegerLiteral ::= ["+","-"] ["1"-"9"] (["0"-"9"])*
FloatingPointLiteral ::= (["+","-"])? (["0"-"9"])+ "." (["0"-"9"])* (["e","E"] (["+","-"])? (["0"-"9"])+)?
    | (["+","-"])? "." (["0"-"9"])+ (["e","E"] (["+","-"])? (["0"-"9"])+)?
    | (["+","-"])? (["0"-"9"])+ ["e","E"] (["+","-"])? (["0"-"9"])+
NullLiteral ::= 'null'

Notes:

Reservered Words

The following words are reserved for the language and should not be used as identifiers without being quoted.

Note that these words may not be in the language now, but they may be in the future, so developers should avoid using these words now.

Named Values

If a named value is specified with a scope of "page", "request", "session", or "app", its value is the value of that name in the given scope. If no scope is given, the value is found according to the rules of PageContext.findAttribute(name).

If a named value is specified with a scope of "header", its value is obtained by calling HttpServletRequest.getHeader(String).

If a named value is specified with a scope of "param", its value is obtained by calling ServletRequest.getParameter(String).

If a named value is specified with a scope of "paramvalues", its value is obtained by calling ServletRequest.getParameterValues(String).

In any of these cases, if a value is not found, the result is an ExpressionException, not "null".

Property Values

The expression "value . propertyName" denotes a property expression. The property is found through introspection by treating the value as a JavaBean and calling the appropriate setter method. If the result is a primitive value, the result is converted to the Object equivalent of the primitive.

Note that these error conditions might be relaxed in the future, but for now they are as strict as possible.

In the future, the "." operator might be extended to interpret other name/value collections, such as Maps, but for now this is not the case. Note that in the future, the "Map behavior" might happen automatically, so JavaBeans should avoid implementing "java.util.Map" to avoid having their behavior change in the future.

Type Conversion

Every expression is evaluated in the context of an "expected type". The result of the expression evaluation may not match the expected type exactly, so the following rules are applied:

Relational Comparisons

The following rules are applied to evaluate a relational comparison.

Rules for == and !=

The rules for equality are as follows:

Rules for >, <, >=, <=

The rules for ordered comparisons are as follows:

ExpressionExceptions

The ExpressionException mechanism in the JSTL is provided as a way for expression languages to indicate that there was a problem evaluating an expression, but the problem was small enough that a default value could be substituted in its place without invoking the entire JSP error handling mechanism.

The SPEL throws javax.servlet.jsp.jstl.core.ExpressionException in the following situations:

Literals and Delimiter

The SPEL is responsible for handling both expressions and literals. Expressions begin with a "$" character. For example:

Any value that does not begin with "$" is treated as a literal that is parsed to the expected type using the PropertyEditor for the expected type:

There may be literal values that start with the "$" character. If that is the case, the value must be escaped using the "\" character.:

If a value starts with "\$", it is treated as a literal value with the leading "\" removed.

$Change: 181991 $$DateTime: 2001/07/02 16:12:52 $$Author$