Details
-
Bug
-
Resolution: Fixed
-
Major
-
6.3
-
None
-
Unit
-
N/A
-
N/A
-
Description
We have introduced a MethodArgumentsUberspector class to automatically convert parameters. I've just found a case where this fails:
- I have a MimeMessageWrapper class that extends MimeMessage
- MimeMessage has a setFrom() method
- MimeMessageWrapper adds a setFrom(Address) method
In MethodArgumentsUberspector.getMethod(..) we have:
VelMethod method = super.getMethod(obj, methodName, args, i); if (method == null && this.converterManager != null) {
The problem is that when getMethod is called with method name = "setFrom" and a String parameter, super.getMethod(...) doesn't return null. Instead Velocity finds the closest matching method and returns MimeMessage.setFrom()... Thus method == null is false and no conversion is applied (to convert from String to Address).
The problem comes from MethodMap.find(String methodName, Object[] args) throws AmbiguousException which according to its javadoc:
- Find a method. Attempts to find the
- most specific applicable method using the
- algorithm described in the JLS section
- 15.12.2 (with the exception that it can't
- distinguish a primitive type argument from
- an object type argument, since in reflection
- primitive type arguments are represented by
- their object counterparts, so for an argument of
- type (say) java.lang.Integer, it will not be able
- to decide between a method that takes int and a
- method that takes java.lang.Integer as a parameter.
Note that the code that calls MethodMap.find is in ClassMap.get(...):
// That one is expensive...
cacheEntry = methodMap.find(name, params);
An idea would be to:
- check in our code that the returned method fully matches the asked method signature
- if not, go into our conversion code
- If our conversion code finds no match, then return the method returned earlier by velocity