Specification Issues

JUEL tries to be as close as possible to the EL specification. However, the spec isn't always clear, leaves some details open and sometimes even seems to be incorrect. For these certain gaps, JUEL had to make decisions that could not be derived from the specification. We still hope that the specification could be updated to make things more clear. Until then, we will have this section to list the specification issues.

  1. In section 1.19, "Collected Syntax", the specification defines Nonterminal LValueInner (which describes an lvalue expression) as
    LValueInner ::= Identifier | NonLiteralValuePrefix (ValueSuffix)*
    This would mean - since NonLiteralValuePrefix can be expanded to a nested expression or function invocation - that ${(1)} or ${foo()} were lvalue expressions. JUEL considers this to be a bug and guesses that the above should read as
    LValueInner ::= Identifier | NonLiteralValuePrefix (ValueSuffix)+
    instead.
  2. In section 1.2.3, "Literal Expressions", the specification states that "the escape characters \$ and \# can be used to escape what would otherwise be treated as an eval-expression". The specification doesn't tell us if '\' is used to escape other characters in literal expressions, too. Consequently, JUEL treats '\' as escape character only when immediately followed by '${' and '#{'.

    Note
    Expression \\${ evaluates to '\${', whereas \$ evaluates to '\$' and \\ evaluates to '\\'.

  3. In section 1.3, "Literals", the specification states that "Quotes only need to be escaped in a string value enclosed in the same type of quote". This suggests that, e.g., "You could escape a single quote in a double-quoted string, but it's not necessary". JUEL guesses that you can't and that the above should read as "Quotes can only be escaped in a string value enclosed in the same type of quote".

    Note
    The '\' in expression ${'\"'} doesn't escape the double quote.

  4. From section 1.2.1.2, "Eval-expressions as method expressions", it is clear that a single identifier expression, e.g. ${foo}, can be used as a method expression. However, the specification doesn't tell how to evaluate such a method expression! Unfortunately, there's no obvious guess, here... JUEL evaluates method expression ${foo} as follows (let paramTypes be the supplied expected method parameter types, returnType the expected return type):

    • Evaluate ${foo} as a value expression
    • If the result is an instance of java.lang.reflect.Method
      • if the method is not static, then error.
      • if the method's parameter types do not match the paramTypes, then error.
      • if returnType is not null and the method's return type does not match returnType, then error.
      • If MethodExpression.invoke(...) was called, invoke the found method with the parameters passed to the invoke method.
      • If MethodExpression.getMethodInfo(...) was called, construct and return a new MethodInfo object.
    • JUEL 2.2.6 and later: If the result is an instance of javax.el.MethodExpression
      • If MethodExpression.invoke(...) was called, delegate to invoke(...) on the found method expression.
      • If MethodExpression.getMethodInfo(...) was called, delegate to getMethodInfo(...) on the found method expression.
    • Otherwise, error
  5. Section 1.6, "Operators [] and .", describes the semantics of base[property]. If property is null, the speciification states not to resolve null on base. Rather, null should be returned if getValue(...) has been called and a PropertyNotFoundException should be thrown else. As a consequence, it would not be possible to resolve null as a key in a map. We think that this restriction is not really wanted and more generally, that property == null should not even have been treated as a special case. We have made an enhancement request, hoping that this will be changed in the future. Because this has been explicitly stated in the spec, we had to implement it this way. However, JUEL's builder supports a feature NULL_PROPERTIES to let you resolve null like any other property value.

    Note
    Assume that map resolves to a java.util.Map. Further assume that feature NULL_PROPERTIES is enabled. Evaluating ${base[null]} as an rvalue (lvalue) will get (put) the value for key null in that map.

  6. Section 1.19, "Collected Syntax" defines Nonterminal IntegerLiteral to be an unsigned integer constant. Then it is said that "The value of an IntegerLiteral ranges from Long.MIN_VALUE to Long.MAX_VALUE". We take that as a hint that the spec wants us to parse integer literals into Long values. However, the positive number |Long.MIN_VALUE| cannot be stored in a Long since Long.MAX_VALUE = |Long.MIN_VALUE| - 1. We think that the specification should have said that "The value of an IntegerLiteral ranges from 0 to Long.MAX_VALUE". Consequently, JUEL rejects |Long.MIN_VALUE| = 9223372036854775808 as an illegal integer literal.
  7. Section 1.19, "Collected Syntax" defines Nonterminal FloatingFointLiteral to be an unsigned floating point constant. Then it is said that "The value of a FloatingPointLiteral ranges from Double.MIN_VALUE to Double.MAX_VALUE". We take that as a hint that the spec wants us to parse floating point literals into Double values. However, since Double.MIN_VALUE is the smallest positive value that can be stored in a Double, this would exclude zero from the range of valid floating point constants! We think that the specification should have said that "The value of a FloatingPointLiteral ranges from 0 to Double.MAX_VALUE". Consequently, JUEL accepts 0.0 as a legal floating point literal.