Bug 52970 - MethodNotFoundException when using enum as one of method arguments
MethodNotFoundException when using enum as one of method arguments
Status: RESOLVED FIXED
Product: Tomcat 7
Classification: Unclassified
Component: Servlet & JSP API
7.0.26
PC All
: P2 normal (vote)
: ---
Assigned To: Tomcat Developers Mailing List
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2012-03-22 12:28 UTC by balusc
Modified: 2012-03-24 21:34 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description balusc 2012-03-22 12:28:52 UTC
Consider this JSF view snippet:

----------------------------------------------------------------------
<h:form>
    <h:commandButton value="submit" action="#{bean.submit('FOO')}" />
</h:form>
----------------------------------------------------------------------

And this JSF bean snippet:

----------------------------------------------------------------------
@ManagedBean
@RequestScoped
public class Bean {
    public enum Type { FOO, BAR }

    public void submit(Type type) {
        System.out.println(type);
    }
}
----------------------------------------------------------------------

This results in a javax.el.MethodNotFoundException. It works in Glassfish 3. EL 2.2 spec 1.18.6 tells that a string must be coerced to enum of type T.
Comment 1 Konstantin Kolinko 2012-03-22 14:03:47 UTC
What stacktrace is there in MethodNotFoundException?
Comment 2 balusc 2012-03-22 14:06:13 UTC
Here it is:

javax.faces.el.MethodNotFoundException: javax.el.MethodNotFoundException: /index.xhtml @15,58 action="#{bean.submit('FOO')}": Method not found: com.example.Bean@385c1187.submit(java.lang.String)
	at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:92)
	at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
	at javax.faces.component.UICommand.broadcast(UICommand.java:315)
	at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
	at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
	at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)
Caused by: javax.el.MethodNotFoundException: /index.xhtml @15,58 action="#{bean.submit('FOO')}": Method not found: com.example.Bean@385c1187.submit(java.lang.String)
	at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:109)
	at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
	... 24 more
Comment 3 Konstantin Kolinko 2012-03-22 14:25:10 UTC
There is nothing in your stacktrace that comes from Tomcat EL implementation. There should be other "Caused by" somewhere further.


Looking at method selection code in
javax.el.BeanELResolver#invoke(..)

- The "paramTypes" argument there is usually null.

In that case the method is identified by the count of parameters, not by their types.

If that were the case, type coercion will happen later and would not result in MethodNotFoundException. So where is it thrown from?

- If the "paramTypes" argument is not-null then it will be used to select exact method.  Is it your case?

The requirements for BeanELResolver#invoke() API are set in EL 2.2 specification (see 2.2.9, page 38). I see no provision to respect EL coercion rules when paramTypes != null.
Comment 4 balusc 2012-03-22 14:31:23 UTC
It's indeed been swallowed/wrapped by Facelets. Here's the stacktrace as it is coming from `invoke()`:

javax.el.MethodNotFoundException: Method not found: com.example.Bean@66a01572.submit(java.lang.String)
	at org.apache.el.util.ReflectionUtil.getMethod(ReflectionUtil.java:225)
	at org.apache.el.parser.AstValue.invoke(AstValue.java:251)
	at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
	at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:111)
	at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
	at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
	at javax.faces.component.UICommand.broadcast(UICommand.java:315)
	at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
	at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
	at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)
Comment 5 balusc 2012-03-22 14:35:56 UTC
Indeed, the params being passed is null in Tomcat 7.0.26 while it contains the right values in Glassfish 3.x.
Comment 6 Mark Thomas 2012-03-24 21:34:10 UTC
This has been fixed in trunk and 7.0.x and will be included in 7.0.27 onwards.