[Bug 63898] New: JSP EL generation is wrong when using newer version of Java 1.8 & tag class uses method overloading and isELIgnored="false

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[Bug 63898] New: JSP EL generation is wrong when using newer version of Java 1.8 & tag class uses method overloading and isELIgnored="false

Bugzilla from bugzilla@apache.org
https://bz.apache.org/bugzilla/show_bug.cgi?id=63898

            Bug ID: 63898
           Summary: JSP EL generation is wrong when using newer version of
                    Java 1.8 & tag class uses method overloading and
                    isELIgnored="false
           Product: Tomcat 9
           Version: 9.0.x
          Hardware: PC
                OS: All
            Status: NEW
          Severity: regression
          Priority: P2
         Component: EL
          Assignee: [hidden email]
          Reporter: [hidden email]
  Target Milestone: -----

JSP EL generation is wrong when using newer version of Java 1.8 & tag class
uses method overloading and isELIgnored="false. Our tag class has an overloaded
method, setValue(String) & setValue(Object).  The TLD file defines the tag
attribute as java.lang.Object.

    <attribute>
        <name>value</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
        <type>java.lang.Object</type>
    </attribute>

All versions of tomcat using newer versions of Java 1.8 generate calls to
setValue(String) instead of setValue(Object).

// /tagUnitTests/sui/formatDate/ testCaliHDateTime1.jsp(20,0) name =
value type = java.lang.Object reqTime = true required = true fragment =
false deferredValue = false expectedTypeName = null deferredMethod =
false methodSignature = null
_jspx_th_sui_005fformatDate_005f0.setValue((java.lang.String)
org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${chdt}",
java.lang.String.class,
(javax.servlet.jsp.PageContext)_jspx_page_context, null));

Here's an example JSP:
<%@ page language="java" contentType="text/html" isELIgnored="false" %>
<%@ page import="java.util.Date" %>
<%@ taglib uri="/WEB-INF/tld/suitags.tld" prefix="sui" %>

<%
Date chdt = new Date();
request.setAttribute("chdt", chdt);
%>

<sui:formatDate value="${chdt}" type="date" dateStyle="shortfull" />


Here's an example tag class

    public void setValue(final String value) {
    }
    public void setValue(final Object value) {
    }

If we delete the setValue(String) setter then tomcat generates the correct
setter call.  The issue appears when using >= 1.8.0.222.

Adopt jdk standard (1.8.0.222) issue
Oracle jdk shiny new (1.8.0.231) issue
Oracle jdk 4.3.100 style (1.8.0.201) no issue
Adopt jdk older (1.8.0.202) NO ISSUE.

--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

[Bug 63898] JSP EL generation is wrong when using newer version of Java 1.8 & tag class uses method overloading and isELIgnored="false

Bugzilla from bugzilla@apache.org
https://bz.apache.org/bugzilla/show_bug.cgi?id=63898

Michael Osipov <[hidden email]> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |[hidden email]

--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

[Bug 63898] JSP EL generation is wrong when using newer version of Java 1.8 & tag class uses method overloading and isELIgnored="false

Bugzilla from bugzilla@apache.org
In reply to this post by Bugzilla from bugzilla@apache.org
https://bz.apache.org/bugzilla/show_bug.cgi?id=63898

Mark Thomas <[hidden email]> changed:

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

--- Comment #1 from Mark Thomas <[hidden email]> ---
TL;DR The JSP specification says that tags should only have one setter per
property.

I've spent some time looking into this an, interestingly, I have seen both
behaviours with Oracle Java 8u172. I'm not sure if using a debugger influenced
the behaviour or if other factors were involved.

Digging into the JavaBeans Introspector code, when there are multiple setters
and no other information to indicate that one should have priority over another
(such as only one having a matching getter) then the first setter found it
used. I suspect what is happening is that the order in which the methods are
returned is varying since the various reflection class to obtain methods don't
specify a return order.

However, all of this is moot due to text present in the JSP specification. The
section numbering seems a little off so if you search for the text
"implication" and then look at the second instance you'll find the following:

<quote>
The setter methods that should be used when assigning a value to an attribute
of a custom action are determined by using the JavaBeans introspector on the
tag handler class, then use the setter method associated with the property that
has the same name as the attribute in question. An implication (unclear in the
JavaBeans specification) is that there is only one setter per property.
</quote>

Interestingly, it is only the name that is used to do the matching. The type is
not used.

--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

[Bug 63898] JSP EL generation is wrong when using newer version of Java 1.8 & tag class uses method overloading and isELIgnored="false

Bugzilla from bugzilla@apache.org
In reply to this post by Bugzilla from bugzilla@apache.org
https://bz.apache.org/bugzilla/show_bug.cgi?id=63898

--- Comment #2 from Christopher Schultz <[hidden email]> ---
Is there scope for Tomcat to either (a) pick the "best" method (based upon
type-agreement) or (b) detect a conflict and throw an error?

A consistent error would be much better than inconsistent failure/success.

--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

[Bug 63898] JSP EL generation is wrong when using newer version of Java 1.8 & tag class uses method overloading and isELIgnored="false

Bugzilla from bugzilla@apache.org
In reply to this post by Bugzilla from bugzilla@apache.org
https://bz.apache.org/bugzilla/show_bug.cgi?id=63898

--- Comment #3 from Mark Thomas <[hidden email]> ---
(In reply to Christopher Schultz from comment #2)
> Is there scope for Tomcat to either (a) pick the "best" method (based upon
> type-agreement) or (b) detect a conflict and throw an error?
>
> A consistent error would be much better than inconsistent failure/success.

Anything is possible but it would require essentially re-implementing the
JavaBean Introspection code. The effort required seems out of proportion to the
size problem.

--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

[Bug 63898] JSP EL generation is wrong when using newer version of Java 1.8 & tag class uses method overloading and isELIgnored="false

Bugzilla from bugzilla@apache.org
In reply to this post by Bugzilla from bugzilla@apache.org
https://bz.apache.org/bugzilla/show_bug.cgi?id=63898

--- Comment #4 from Christopher Schultz <[hidden email]> ---
(In reply to Mark Thomas from comment #3)
> Anything is possible but it would require essentially re-implementing the
> JavaBean Introspection code. The effort required seems out of proportion to
> the size problem.

Of course: yuck.

Instead of:

Method m = IntrospectionUtils.getTheOneTrueSetterMethod(...);

Can we call:

Method[] candidates = IntrospectionUtils.getTheListOfCandidateMethods(...);

... and then throw an error if candidates.length != 1?

That would be a relatively minor change but catch lots of these errors.

--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

[Bug 63898] JSP EL generation is wrong when using newer version of Java 1.8 & tag class uses method overloading and isELIgnored="false

Bugzilla from bugzilla@apache.org
In reply to this post by Bugzilla from bugzilla@apache.org
https://bz.apache.org/bugzilla/show_bug.cgi?id=63898

--- Comment #5 from Mark Thomas <[hidden email]> ---
No we can't, because - as per the spec - we are using the JavaBeans
introspection machinery, not our own IntrospectionUtils.

--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

[Bug 63898] JSP EL generation is wrong when using newer version of Java 1.8 & tag class uses method overloading and isELIgnored="false

Bugzilla from bugzilla@apache.org
In reply to this post by Bugzilla from bugzilla@apache.org
https://bz.apache.org/bugzilla/show_bug.cgi?id=63898

--- Comment #6 from Konstantin Kolinko <[hidden email]> ---
1. (In reply to jeffrey.lobello from comment #0)
> Here's an example tag class
>
>     public void setValue(final String value) {
>     }
>     public void setValue(final Object value) {
>     }

And there is no "getValue()" method for this pair?


2. Note that the JavaBeans specification allows to bypass the introspection
logic in java.beans.Introspector and explicitly provide a description for one's
bean.

That is done by creating a class named FooBeanInfo for a bean class named Foo.

I think that a possible workaround for the OP is to create such a class.


3. (In reply to Christopher Schultz from comment #2)
> Is there scope for Tomcat to either (a) pick the "best" method (based upon type-agreement) or (b) detect a conflict and throw an error?

In OP's case the attribute type is explicitly declared as "java.lang.Object" in
a TLD file for the tag library.  There is an explicit mismatch with the method
returned by introspection. It is not a question of choosing the "best" method.


BTW, I think that the relevant code in Jasper is the TagHandlerInfo class
declared in org/apache/jasper/compiler/Generator.java. See its constructor that
does the introspection. See calls to its getSetterMethod() method, such as

   m = handlerInfo.getSetterMethod(localName);
   if (m == null) { (... - reporting an error) }
   c = m.getParameterTypes();

Technically, the name of c[0] class could be compared as string with the value
of javax.servlet.jsp.tagext.TagAttributeInfo.getTypeName(), but

a) There are likely to be some edge cases.

b) What do we do with the result? Generate an error?

In OP's case the web application is failing. If I understand correctly it
compiles successfully, but fails at run time? If so, implementing an explicit
check will make it to fail at compile time.

--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]