You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bu...@apache.org on 2013/11/18 14:42:42 UTC

[Bug 55792] New: Collection literals not recognized within stream lambda expression, result in syntax error

https://issues.apache.org/bugzilla/show_bug.cgi?id=55792

            Bug ID: 55792
           Summary: Collection literals not recognized within stream
                    lambda expression, result in syntax error
           Product: Tomcat 8
           Version: 8.0.0-RC5
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: EL
          Assignee: dev@tomcat.apache.org
          Reporter: nicholas@nicholaswilliams.net

I have the following EL expression in a JSP. The expression evaluates and
executes correctly without error:

    ${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()}

I want to apply the map operation to this as well. Section 2.3.6.4 of the JUEL
3.0 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()

So I tried applying the exact same pattern to my map operation (the new map
operation is the only change to 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 -> [u.username, u.firstName, u.lastName])
        .toList()}

I also tried using a map-literal:

    ${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()}

However, using the list-literal in my map lambda expression results in this
error, indicating that it doesn't recognize the list-literal as a list-literal:

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)
      ...

And using the map-literal results in this error, indicating that it doesn't
recognize the map-literal as a map-literal (instead, it thinks the closing
brace of the map-literal is the end of the EL expression:

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...

Putting parentheses around the list- and map-literals does not work, but the
Section 2.3.6.4 example doesn't use parentheses. Section 1.20 also indicates
that collection literals as bodies of lambda expressions are legal:

    customers.select(c->[c.name, c.orders.sum(o->o.total)])

Collection literals are described in more detail in Section 2.2.

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 55792] EL expression containing a map is not parsed correctly. '}' is interpreted as closing brace of the EL expression.

Posted by bu...@apache.org.
https://issues.apache.org/bugzilla/show_bug.cgi?id=55792

--- Comment #4 from Konstantin Kolinko <kn...@gmail.com> ---
Created attachment 31054
  --> https://issues.apache.org/bugzilla/attachment.cgi?id=31054&action=edit
2013-11-19_55792_tc8_tests.patch

Amendment to the tests. This is currently failing.

Notes:
1. This issue affects not only maps, but sets as well. In my reproducer
"{1,2,3,4}" is a set, not a map.

2. I am using sorted() so that the result of evaluation were not affected by
the order of items in a HashSet.

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 55792] EL expression containing a map is not parsed correctly. '}' is interpreted as closing brace of the EL expression.

Posted by bu...@apache.org.
https://issues.apache.org/bugzilla/show_bug.cgi?id=55792

Konstantin Kolinko <kn...@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Collection literals not     |EL expression containing a
                   |recognized within stream    |map is not parsed
                   |lambda expression, result   |correctly. '}' is
                   |in syntax error             |interpreted as closing
                   |                            |brace of the EL expression.

--- Comment #2 from Konstantin Kolinko <kn...@gmail.com> ---
(For reference - discussion on users@ before filing this issue
http://tomcat.markmail.org/thread/mohw6qhaauez27h5

The only issue here is that '}' in declaration of a map is interpreted as
closing brace of EL expression.  I am changing TITLE accordingly.


Searching through Tomcat 8 sources, we have a similar test:
/test/webapp/el-misc.jsp

The code there is
<tags:echo echo='19-${{1,2,3,4}.stream().max().orElse(-1)}' />

The above works when EL is used in an attribute of a tag.
But when I move the EL expression into the body of the document, it starts to
fail. The following simple JSP fails
[[[
<%@page contentType="text/plain; charset=UTF-8"%>
${{1,2,3,4}.stream().max().orElse(-1)}
]]]

javax.el.ELException: Failed to parse the expression [${{1,2,3,4}]


For completeness, '}' in string literals is parsed correctly.
The following JSP does work
[[[
<%@page contentType="text/plain; charset=UTF-8"%>
${'}A'}B
${"}C"}D
]]]

It prints
}AB
}CD

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 55792] EL expression containing a map is not parsed correctly. '}' is interpreted as closing brace of the EL expression.

Posted by bu...@apache.org.
https://issues.apache.org/bugzilla/show_bug.cgi?id=55792

Mark Thomas <ma...@apache.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |FIXED

--- Comment #5 from Mark Thomas <ma...@apache.org> ---
Nick, thanks for the report.

Konstantin, thanks for the test case.

Thsi has been fixed in trunk and will be in 8.0.0-RC6 onwards.

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 55792] Collection literals not recognized within stream lambda expression, result in syntax error

Posted by bu...@apache.org.
https://issues.apache.org/bugzilla/show_bug.cgi?id=55792

--- Comment #1 from Nick Williams <ni...@nicholaswilliams.net> ---
Please note the following revision to this bug:

It's only the map-literal that isn't working. The list-literal is working fine.
When I used the list-literal originally, I mapped before sorting, like so:

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

This caused the NumberFormatException, which makes sense. When mapping happens
after sorting:

    ${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 -> [u.username, u.firstName, u.lastName])
        .toList()}

The expression works correctly. So the ONLY expression that isn't working uses
the map-literal for the mapping:

    ${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()}

This is definitely broken, as the } ending the map-literal makes the EL engine
think the expression has ended prematurely.

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 55792] EL expression containing a map is not parsed correctly. '}' is interpreted as closing brace of the EL expression.

Posted by bu...@apache.org.
https://issues.apache.org/bugzilla/show_bug.cgi?id=55792

--- Comment #3 from Konstantin Kolinko <kn...@gmail.com> ---
Created attachment 31053
  --> https://issues.apache.org/bugzilla/attachment.cgi?id=31053&action=edit
test_55792.jsp - Sample JSP page

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 55792] EL expression containing a map is not parsed correctly. '}' is interpreted as closing brace of the EL expression.

Posted by bu...@apache.org.
https://issues.apache.org/bugzilla/show_bug.cgi?id=55792

--- Comment #6 from Nick Williams <ni...@nicholaswilliams.net> ---
I can confirm that this is fixed. Thanks!

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org