You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by ke...@kjaklive.com on 2012/03/07 16:59:48 UTC

Tomcat 7.0.26 Expression Language Issue when Comparing Character Objects

Hello. I have been testing a Java Web Application to upgrade from Tomcat
6.0.32 (x86) to Tomcat 7.0.26 (x64). I am using Java 6 update 31. I have
also tried pointing Tomcat 7.0.26 (x64) to Java 7 Update 3 and
experience the same issue.

Windows 7 x64
IDE is Netbeans 7.0.1
Tomcat 7.0.26 x64
Java 6 update 31
Hibernate
Spring MVC 2.5.6
JSTL 1.1

I have come across an issue with existing code in the application. This
code has been in production using Tomcat 6.0.32 (x86) for over 1 year
and has not had a problem.

My issue is with the Expression Language and how a Character object is
compared to an in-line Character object in order to decide what content
to display on the web page.

My original comparison code is as follows:
<c:if test="${program.isGeneralPublicYN == 'N'}">
 <!-- Show General Public Information -->
</c:if>

Where program is a Program object and isGeneralPublicYN is a char
property of the program object.

When I access this page running on Tomcat 7.0.26 (x64), I receive the
following error:
 javax.el.ELException: Cannot convert N of type class
java.lang.String to class java.lang.Long

I started looking around and found the following in section 1.8.1 of the
Expression Language Specification Version 2.2 Maintenance Release
(http://download.oracle.com/otn-pub/jcp/expression_language-2.2-mrel-eval-oth-JSpec/expression_language-2_2-mrel-spec.pdf)
=> 
A {<,>,<=,>=,lt,gt,le,ge} B
■ If A==B, if operator is <=, le, >=, or ge return true.
■ If A is null or B is null, return false
■ If A or B is BigDecimal, coerce both A and B to BigDecimal and use
the return
value of A.compareTo(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 use
the return
value of A.compareTo(B).
Chapter 1 Language Syntax and Semantics 13
■ If A or B is Byte, Short, Character, Integer, or Long coerce both A
and B to
Long and apply operator
■ If A or B is String coerce both A and B to String, compare lexically
■ If A is Comparable, then:
■ If A.compareTo(B) throws exception, error.
■ Otherwise use result of A.compareTo(B)
■ If B is Comparable, then:
■ If B.compareTo(A) throws exception, error.
■ Otherwise use result of B.compareTo(A)
■ Otherwise, error

I am particularly interested in the following line of logic:
■ If A or B is Byte, Short, Character, Integer, or Long coerce both A
and B to
Long and apply operator

The expression I am evaluating appears to meet the requirements here.
program.isGeneralPublicYN is a Character object. It is being converted
to a Long as the specification states. However, my in-line variable
('N') is not being converted to a Long, but is instead being converted
to a String.

Am I reading the specification wrong? Since program.isGeneralPublicYN is
a Character, shouldn't EL convert both sides to a Long for the
comparison? Was this implemented incorrectly in Tomcat 6.0.32 (x86) and
corrected in Tomcat 7.0.26 (x64)?

I have identified 2 workarounds for this issue:
(1) Since it is a character, I can use the EL Function "contains" for
the comparison
<c:if test="${fn:contains(program.is_general_public_yn, 'N')}"> 
 <div class="sub_question">Please explain:</div><br /> 
 <c:out value="${program.general_public_explain}" /> 
 <br /><br /> 
</c:if> 

(2) I can pass a character to the page via the reference map in the
controller to the page and then do the comparison on that object instead
of doing it in-line

Map refData = new HashMap();
....
refData.put("charN", 'N');

<c:if test="${program.isGeneralPublicYN == charN}">
 <div class="sub_question">Please explain:</div><br />
 <c:out value="${program.general_public_explain}" />
 <br /><br />
</c:if>

It doesn't make much sense that it would convert a referenced object,
but not an in-line object of the same type. Possibly because in-line the
compiler has a harder time differentiating a one-character string object
and a character object?

It seems a little crazy to have to workaround this issue. I shouldn't
have to change my code. This greatly increases the amount of code
changes and testing we have to do in order to move applications from
Tomcat 6 to 7. If this is a bug in Tomcat 7.0.26 (x64) then we may hold
off on the upgrade. However, if it is not a bug, then please explain to
me why my
original code no longer works and the best practices for implementation.

I appreciate your time looking into this concern and I hope to hear from
the community in the near future regarding this matter. Thank you,

--Kerry--

http://www.kjaklive.com


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


Re: Tomcat 7.0.26 Expression Language Issue when Comparing Character Objects

Posted by Konstantin Kolinko <kn...@gmail.com>.
2012/3/7 Christopher Schultz <ch...@christopherschultz.net>:
>
> I think that's the deal: Tomcat takes the character from your object's
> property and decides that everything should be coerced to Long, then
> tries to coerce your String literal to a Long, which obviously does
> not work (there appear to be no rules for coercing String to Number
> unless the target type is BigDecimal. It seems ambiguous to me since
> there is no "otherwise" in section 1.18.3 when String is being coerced
> to something other than BigDecimal.

The "If N is BigInteger then:" line below it is misaligned.

After the BigInteger cases there is
"If N.valueOf(A) throws an exception, then error."

So Long.valueOf(A).

>
>> It seems a little crazy to have to workaround this issue. I
>> shouldn't have to change my code. This greatly increases the amount
>> of code changes and testing we have to do in order to move
>> applications from Tomcat 6 to 7. If this is a bug in Tomcat 7.0.26
>> (x64) then we may hold off on the upgrade. However, if it is not a
>> bug, then please explain to me why my original code no longer works
>> and the best practices for implementation.

A bug in implementation of ELSupport.equals(A,B),
https://issues.apache.org/bugzilla/show_bug.cgi?id=52666

Fixed in 7.0.26 and also in 6.0 with
http://svn.apache.org/viewvc?view=revision&revision=1245686

Before this change Strings were compared before numbers, contrary to the spec.

So you cannot stay on 6.0 without fixing your code.

>> I have identified 2 workarounds for this issue:
>> (1) Since it is a character, I can use the EL Function "contains" for
>> the comparison
>> <c:if test="${fn:contains(program.is_general_public_yn, 'N')}">
>>  <div class="sub_question">Please explain:</div><br />
>>  <c:out value="${program.general_public_explain}" />
>>  <br /><br />
>> </c:if>

fn:contains, fn:startsWith are good.

It is possible to force conversion of first operand to String and then
apply '==', e.g. ${fn:trim(program.is_general_public_yn) eq 'N'}, but
that will require more operations that just calling the above
functions.


Best regards,
Konstantin Kolinko

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


Re: Tomcat 7.0.26 Expression Language Issue when Comparing Character Objects

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Kerry,

On 3/7/12 10:59 AM, kerry@kjaklive.com wrote:
> My issue is with the Expression Language and how a Character object
> is compared to an in-line Character object in order to decide what
> content to display on the web page.
> 
> My original comparison code is as follows: <c:if
> test="${program.isGeneralPublicYN == 'N'}"> <!-- Show General
> Public Information --> </c:if>

I'm not that steeped in the EL spec, but it looks like Section 1.3 in
spec 2.2 MR says that there is no such thing as a character literal:
only strings (and others):

"
Literals
There are literals for boolean, integer, floating point, string, and
null in an eval- expression.
■ Boolean - true and false
■ Integer - As defined by the IntegerLiteral construct in Section 1.19
■ Floating point - As defined by the FloatingPointLiteral construct in
Section 1.19
■ String - With single and double quotes - " is escaped as \", ' is
escaped as \',
and \ is escaped as \\. Quotes only need to be escaped in a string
value enclosed
in the same type of quote
■ Null-null
"

The grammar for EL (section 1.19) also defines "StringLiteral" to be
anything between single- or double-quotes.

What if you did something like this:

<c:if test="${program.isGeneralPublicYN == 'N'.charAt(0)}">
 <!-- Show General Public Information -->
</c:if>

Or, if you can think of another way to coerce the string "N" to a
character, the spec says that coercing a String to a Character results
in the first character of the string being used.

> It doesn't make much sense that it would convert a referenced
> object, but not an in-line object of the same type. Possibly
> because in-line the compiler has a harder time differentiating a
> one-character string object and a character object?

I think that's the deal: Tomcat takes the character from your object's
property and decides that everything should be coerced to Long, then
tries to coerce your String literal to a Long, which obviously does
not work (there appear to be no rules for coercing String to Number
unless the target type is BigDecimal. It seems ambiguous to me since
there is no "otherwise" in section 1.18.3 when String is being coerced
to something other than BigDecimal.

> It seems a little crazy to have to workaround this issue. I
> shouldn't have to change my code. This greatly increases the amount
> of code changes and testing we have to do in order to move
> applications from Tomcat 6 to 7. If this is a bug in Tomcat 7.0.26
> (x64) then we may hold off on the upgrade. However, if it is not a
> bug, then please explain to me why my original code no longer works
> and the best practices for implementation.

Each version of Tomcat generally becomes more strict when it comes to
spec-compliance. That may be the case, here.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk9XphEACgkQ9CaO5/Lv0PCgkACfU83Xxek0aj+kJjrC59UWHwKN
MvcAnAoSKMO7Pby0zeRylOLqdTG3wBPn
=rSTu
-----END PGP SIGNATURE-----

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