On Nov 17, 2013, at 6:00 AM, Konstantin Kolinko wrote:

> 2013/11/17 Nick Williams <nicho...@nicholaswilliams.net>:
>> I have an EL 3.0 edge case that I need help understanding. Am I doing 
>> something wrong (I don't think so) or is the Tomcat 8.0 implementation 
>> missing something?
>> 
>> Consider the following EL expression:
>> 
>>        ${users.stream()
>>               .filter(u -> fn:contains(u.username, '1'))
>>               .sorted((u1, u2) -> u1.lastName.compareTo(u2.lastName) == 0 ? 
>> u1.firstName.compareTo(u2.firstName) : u1.lastName.compareTo(u2.lastName))
>>               .toList()}
>> 
>> This works as expected. However, it results in potentially evaluating 
>> u1.lastName.compareTo(u2.lastName) twice. My understanding is that the 
>> right-hand side of a lambda expression can be any valid EL expression, so I 
>> believe this should also work:
>> 
>>        ${users.stream()
>>               .filter(u -> fn:contains(u.username, '1'))
>>               .sorted((u1, u2) -> x = u1.lastName.compareTo(u2.lastName); x 
>> == 0 ? u1.firstName.compareTo(u2.firstName) : x)
>>               .toList()}
>> 
>> However, this doesn't evaluate. I get the following error instead:
>> 
>> org.apache.el.parser.ParseException: Encountered " "=" "= "" at line 3, 
>> column 38.
>> Was expecting one of:
>>    "." ...
>>    ")" ...
>>    etc ...
>> 
> 
> What if you add "(" ")" ?
> What operator has higher priority, "->" or ";" ?

"->" has higher priority than both "=" and ";", according to the spec. In this 
particular case, I'm not sure whether that means parenthesis are absolutely 
required or not. However, I can confirm that adding parenthesis here solves 
this problem, so perhaps that's what I was doing wrong for this error. This 
expression now works:

        ${users.stream()
               .filter(u -> fn:contains(u.username, '1'))
               .sorted((u1, u2) -> (x = u1.lastName.compareTo(u2.lastName); x 
== 0 ? u1.firstName.compareTo(u2.firstName) : x))
               .toList()}

>> Next I tried to reduce the properties present in each user using the stream 
>> "map" method. Once again, with the understanding that the right-hand side of 
>> a lambda expression can be any valid EL expression, I use an EL Map literal 
>> to construct a reduced set of properties:
>> 
>>        ${users.stream()
>>               .filter(u -> fn:contains(u.username, '1'))
>>               .map(u -> {'username':u.username, 'first':u.firstName, 
>> 'last':u.lastName})
>>               .sorted((u1, u2) -> u1.lastName.compareTo(u2.lastName) == 0 ? 
>> u1.firstName.compareTo(u2.firstName) : u1.lastName.compareTo(u2.lastName))
>>               .toList()}
>> 
>> However, that doesn't work and I get this error:
>> 
>> org.apache.el.parser.ParseException: Encountered "<EOF>" at line 3, column 
>> 88.
>> Was expecting one of:
>>    "." ...
>>    ")" ...
>>    etc ...
>> 
> 
> I do not understand the above.  Can you provide a simple test case?
> Which one of the expressions does not work? Can you remove the others?

So, as mentioned above, the following expression works:

        ${users.stream()
               .filter(u -> fn:contains(u.username, '1'))
               .sorted((u1, u2) -> (x = u1.lastName.compareTo(u2.lastName); x 
== 0 ? u1.firstName.compareTo(u2.firstName) : x))
               .toList()}

If I now add the "map" operation to it, I get the EOF error. Nothing else about 
the expression changed:

        ${users.stream()
               .filter(u -> fn:contains(u.username, '1'))
               .sorted((u1, u2) -> (x = u1.lastName.compareTo(u2.lastName);
                    x == 0 ? u1.firstName.compareTo(u2.firstName) : x))
               .map(u -> {'username':u.username, 'first':u.firstName, 
'last':u.lastName})
               .toList()}

javax.el.ELException: Failed to parse the expression [${users.stream()
               .filter(u -> fn:contains(u.username, '1'))
               .sorted((u1, u2) -> (x = u1.lastName.compareTo(u2.lastName);
                    x == 0 ? u1.firstName.compareTo(u2.firstName) : x))
               .map(u -> {'username':u.username, 'first':u.firstName,
                    'last':u.lastName}]
    ...
<root cause>
org.apache.el.parser.ParseException: Encountered "<EOF>" at line 6, column 38. 
Was expecting one of:
    "." ...
    ")" ...
    etc...

Notice that it thinks the expression is ending after the closing } of the 
map-literal. Now the example in 2.3.6.4 of the specification alludes to the 
fact that my use of the map-literal here is correct. In that example they use a 
list-literal instead (.map(p->[p.name, p.unitPrice])). I tried changing to use 
a list-literal instead of a map-literal, and that's when I got the 
NumberFormatException described earlier. I _believe_ both should be legal; the 
specification clearly intends that at least using the list-literal should be 
legal. Neither work in Tomcat.

Does this make sense?

>> Section 2.3.6.4 of the specification uses the following example, where a 
>> LIST literal is used as the right-hand side of the mapping lambda expression:
>> 
>> products.stream().filter(p->p.unitPrice >= 10).
>>        .map(p->[p.name, p.unitPrice])
>>        .toList()
>> 
>> I tried to use this exact syntax, as shown in the spec, with my example:
>> 
>>        ${users.stream()
>>               .filter(u -> fn:contains(u.username, '1'))
>>               .map(u -> [u.username, u.firstName, u.lastName])
>>               .sorted((u1, u2) -> u1.lastName.compareTo(u2.lastName) == 0 ? 
>> u1.firstName.compareTo(u2.firstName) : u1.lastName.compareTo(u2.lastName))
>>               .toList()}
>> 
>> And now I get this lovely error:
>> 
>> javax.el.ELException: java.lang.NumberFormatException: For input string: 
>> "lastName"
>>        javax.el.BeanELResolver.invoke(BeanELResolver.java:185)
>>        
>> org.apache.jasper.el.JasperELResolver.invoke(JasperELResolver.java:147)
>>        org.apache.el.parser.AstValue.getValue(AstValue.java:158)
>>        ...
>> 
>> I'm sure I'm doing something wrong here, but I'm not exactly sure what. On 
>> the other hand, it's possible that the Tomcat 8.0 implementation is just 
>> wrong. Can someone shed some light on this?
>> 
> 
> Best regards,
> Konstantin Kolinko

Thanks,

Nick
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to