Uploaded image for project: 'XWiki Commons'
  1. XWiki Commons
  2. XCOMMONS-710

Velocity parameter conversion fails under some circumstances

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 6.3
    • Fix Version/s: 6.4-milestone-3
    • Component/s: Velocity
    • Labels:
      None
    • Tests:
      Unit
    • Documentation:
      N/A
    • Documentation in Release Notes:
      N/A
    • Similar issues:

      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

        Attachments

          Activity

            People

            Assignee:
            vmassol Vincent Massol
            Reporter:
            vmassol Vincent Massol
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: