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/08/26 14:27:34 UTC

[Bug 55483] New: ELException when object has overloaded methods

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

            Bug ID: 55483
           Summary: ELException when object has overloaded methods
           Product: Tomcat 8
           Version: trunk
          Hardware: PC
                OS: Mac OS X 10.4
            Status: NEW
          Severity: normal
          Priority: P2
         Component: EL
          Assignee: dev@tomcat.apache.org
          Reporter: dmikusa@gopivotal.com

Included below are two test cases which fail.  The first calls an overloaded
method on an object.  The second calls an overloaded constructor.  More details
below.


1.) Here's the first test.

   @Test
   public void test01() {
       ELProcessor processor = new ELProcessor();
       processor.defineBean("sb", new StringBuilder());
       Assert.assertEquals("a", processor.eval("sb.append('a');
sb.toString()"));
   }

This fails with the following stack trace.

javax.el.ELException: Cannot convert a of type class java.lang.String to long
    at org.apache.el.lang.ELSupport.coerceToNumber(ELSupport.java:349)
    at org.apache.el.lang.ELSupport.coerceToNumber(ELSupport.java:328)
    at org.apache.el.lang.ELSupport.coerceToType(ELSupport.java:450)
    at
org.apache.el.ExpressionFactoryImpl.coerceToType(ExpressionFactoryImpl.java:48)
    at javax.el.Util.buildParameters(Util.java:351)
    at javax.el.BeanELResolver.invoke(BeanELResolver.java:173)
    at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:84)
    at org.apache.el.parser.AstValue.getValue(AstValue.java:157)
    at org.apache.el.parser.AstSemicolon.getValue(AstSemicolon.java:35)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:188)
    at javax.el.ELProcessor.getValue(ELProcessor.java:45)
    at javax.el.ELProcessor.eval(ELProcessor.java:38)
    at
org.apache.el.parser.TestAstMethodCalls.test01(TestAstMethodCalls.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Looking into this, it appears that the EL is having trouble because
StringBuilder's append method is overloaded.  It is instructed to call append
with the character 'c', but instead is trying to coerce the character 'c' to a
long and call append with the long.

This chain of events seems to be kicked off in AstValue.getValue() line #157,
where it's calling resolver.invoke(..).  The call to resolver.invoke() is
passing null as the paramTypes argument.  This trickles down to
BeanELResolver.invoke(), which calls Util.findMethod().  Because paramTypes is
null, Util.findMethod() selects the first method it finds with the expected
number of arguments.  In the case above, it selects StringBuilder.append(long),
which causes the problem above.



2.) Here's the second test.

   @Test
   public void test02() {
       ELProcessor processor = new ELProcessor();
       processor.getELManager().importClass("java.util.Date");
       Date result = (Date) processor.eval("Date(86400)");
       Assert.assertEquals(86400, result.getTime());
   }

This one fails intermittently with the following stack trace.

javax.el.ELException: java.lang.IllegalArgumentException
    at javax.el.StaticFieldELResolver.invoke(StaticFieldELResolver.java:118)
    at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:84)
    at org.apache.el.parser.AstFunction.getValue(AstFunction.java:138)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:188)
    at javax.el.ELProcessor.getValue(ELProcessor.java:45)
    at javax.el.ELProcessor.eval(ELProcessor.java:38)
    at
org.apache.el.parser.TestAstMethodCalls.test02(TestAstMethodCalls.java:39)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.IllegalArgumentException
    at java.util.Date.parse(Date.java:615)
    at java.util.Date.<init>(Date.java:272)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at javax.el.StaticFieldELResolver.invoke(StaticFieldELResolver.java:111)
    ... 29 more

Looking into this error, it seems similar to #1.  The difference is that
AstFunction.getValue() line #138 is calling invoke on the resolver and passing
null as the paramTypes.  This trickles down to the
StaticFieldELResolver.invoke() method, which calls Util.findConstructor(). 
Again, because paramTypes is null, Util.findConstructor() searches the
available constructors for the one with the same number of arguments.  The
reason that this intermittently fails is because on my system, the call to
Class.getConstructors() returns the list of constructs in an arbitrary order.
So it fails when Date(String) is listed first, but succeeds when Date(long) is
listed first.

-- 
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 55483] ELException when object has overloaded methods

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

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

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

--- Comment #2 from Mark Thomas <ma...@apache.org> ---
Thanks for the report and the unit tests. This has been fixed in trunk and will
be included in 8.0.0-RC2 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 55483] ELException when object has overloaded methods

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

--- Comment #7 from Christopher Ng <cn...@gmail.com> ---
The fix for this has broken one of our EL expressions, we have an overloaded
method like so:

doSomething(HttpServletRequest a, String b, String c, String d);
doSomething(String a, String b, String c, String d);

and we end up with an error 'Unable to find unambiguous method'.  It is
supposed to invoke the first method.

>From what I can tell it's because when it is assessing the suitability of each
method, it doesn't find an exact match for either as the actual request object
is a sub-class of HttpServletRequest, and can also be coerced into a String.

Perhaps this can be fixed by prioritising sub-class matches over coercions?

-- 
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 55483] ELException when object has overloaded methods

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

--- Comment #9 from gangsu_choi <ga...@tmax.co.kr> ---
This changes added Tomcat 7.0 but It has no unit tests.

Do Anyone have unit tests for Tomcat 7.0?

-- 
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 55483] ELException when object has overloaded methods

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

--- Comment #4 from Eugene Chung (TmaxSoft) <bl...@gmail.com> ---
org.apache.el.util.ReflectionUtil#getMethod(java.lang.Object, java.lang.Object,
java.lang.Class<?>[], java.lang.Object[])


            // If a method is found where every parameter matches exactly,
            // return it
            if (exactMatch == paramCount) {
                getMethod(base.getClass(), m);
            }


I haven't fully understand the recent patches but I think it should be 

return getMethod(base.getClass(), m);

as the comment says.

-- 
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 55483] ELException when object has overloaded methods

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

--- Comment #1 from Daniel Mikusa <dm...@gopivotal.com> ---
Created attachment 30764
  --> https://issues.apache.org/bugzilla/attachment.cgi?id=30764&action=edit
Unit test

Attaching a unit test to replicate the problem.

-- 
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 55483] ELException when object has overloaded methods

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

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

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

--- Comment #6 from Mark Thomas <ma...@apache.org> ---
Thanks for the report.

The missing return didn't change the behaviour, it just meant that the exact
match wasn't returned as quickly as it could have been.

-- 
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 55483] ELException when object has overloaded methods

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

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

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

--- Comment #5 from Mark Thomas <ma...@apache.org> ---
Re-open to review comment #4.

-- 
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 55483] ELException when object has overloaded methods

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

--- Comment #8 from Konstantin Kolinko <kn...@gmail.com> ---
(In reply to Christopher Ng from comment #7)
> The fix for this has broken one of our EL expressions, we have an overloaded method like so:
> 
> doSomething(HttpServletRequest a, String b, String c, String d);
> doSomething(String a, String b, String c, String d);
> ...

This issue has already been reported and is tracked as bug 56425.
(It has been fixed in 8.0.x for 8.0.6 onwards and in 7.0.x for 7.0.54 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 55483] ELException when object has overloaded methods

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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ujjets@gmail.com

--- Comment #3 from Mark Thomas <ma...@apache.org> ---
*** Bug 56147 has been marked as a duplicate of this bug. ***

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