String to Long comparison throws "ELException: Cannot convert" in Tomcat 7, works in Tomcat 6
Asked Answered
H

1

6

The following snippet works fine in Tomcat 6,

<c:set var="abc" value="$12,345" />
<c:choose>
    <c:when test="${abc ne 0}">
        <c:out value="PASS"></c:out>
    </c:when>
    <c:otherwise>
        <c:out value="FAIL"></c:out>
    </c:otherwise> 
</c:choose>

but throws exception in Tomcat 7.

javax.el.ELException: Cannot convert $1,2345 of type class java.lang.String to class java.lang.Long
    at org.apache.el.lang.ELSupport.coerceToNumber(ELSupport.java:304)
    at org.apache.el.lang.ELSupport.coerceToNumber(ELSupport.java:283)
    at org.apache.el.lang.ELSupport.equals(ELSupport.java:143)
    at org.apache.el.parser.AstNotEqual.getValue(AstNotEqual.java:40)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:185)
    at org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:1026)
    at org.apache.jsp.WEB_002dINF.jsp.web.statussummary.status_005fsummary_jsp._jspx_meth_c_005fwhen_005f0(status_005fsummary_jsp.java:290)

Looks like there is a difference in the way the expression ${abc ne 0} is evaulted in Tomcat 7. In Tomcat 6 both ${abc} and ${0} are compared as Strings but in Tomcat 7 I get this exception. I do not know why this should happen and which class file of which API is responsible for this.

How is this caused and how can I solve it?

Hideaway answered 12/8, 2014 at 21:36 Comment(0)
T
3

This is because you are trying to compare a string to an int. Per the EL docs, section 1.9.2:

1.9.2 A {==,!=,eq,ne} B

  • If A==B, apply operator
  • If A is null or B is null return false for == or eq, true for != or ne
  • If A or B is BigDecimal, coerce both A and B to BigDecimal and then:
    • If operator is == or eq, return A.equals(B)
    • If operator is != or ne, return !A.equals(B)
  • If A or B is Float or Double coerce both A and B to Double, apply operator
  • If A or B is BigInteger, coerce both A and B to BigInteger and then:
    • If operator is == or eq, return A.equals(B)
    • If operator is != or ne, return !A.equals(B)
  • If A or B is Byte, Short, Character, Integer, or Long coerce both A and B to Long, apply operator
  • If A or B is Boolean coerce both A and B to Boolean, apply operator
  • If A or B is an enum, coerce both A and B to enum, apply operator
  • If A or B is String coerce both A and B to String, compare lexically
  • Otherwise if an error occurs while calling A.equals(B), error
  • Otherwise, apply operator to result of A.equals(B)

The problem with your test is that you are trying to compare "$12,345" (String) with 0 (Integer). Since 0 is an Integer, it falls into the bold If in their docs (above), where A or B is an Integer. Both are trying to be forced into a Long, which Java won't convert the String value "$12,345" into a long. If you change your code to either of the following you will see that it works:

String comparison:

<c:set var="abc" value="$12,345" />
<c:choose>
    <c:when test="${abc ne '0'}"> <!-- Change Integer to String -->
        <c:out value="PASS"></c:out>
    </c:when>
    <c:otherwise>
        <c:out value="FAIL"></c:out>
    </c:otherwise> 
</c:choose>

Integer comparison:

<c:set var="abc" value="12345" /> <!-- Change String to Integer -->
<c:choose>
    <c:when test="${abc ne 0}">
        <c:out value="PASS"></c:out>
    </c:when>
    <c:otherwise>
        <c:out value="FAIL"></c:out>
    </c:otherwise> 
</c:choose>
Teague answered 8/3, 2016 at 22:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.