Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dubbo - telnet] Unrecognized overload method #2766

Closed
2 tasks done
zonghaishang opened this issue Nov 9, 2018 · 9 comments · Fixed by #2801
Closed
2 tasks done

[Dubbo - telnet] Unrecognized overload method #2766

zonghaishang opened this issue Nov 9, 2018 · 9 comments · Fixed by #2801
Assignees
Labels
type/bug Bugs to being fixed

Comments

@zonghaishang
Copy link
Member

  • I have searched the issues of this repository and believe that this is not a duplicate.
  • I have checked the FAQ of this repository and believe that this is not a duplicate.

Environment

  • Dubbo version: 2.7.0+
  • Operating System version: mac
  • Java version: 1.8

Steps to reproduce this issue

Assume that there is an interface below:

package com.youzan.nova.service;

import java.util.Set;

public interface OverrideService {

    void invoke(Integer id, Set<String> orderNumbers);

    void invoke(Long id, Set<String> orderNumbers);

}

package com.youzan.nova.service;

import java.util.Set;

public class OverrideServiceImpl implements OverrideService {
    @Override
    public void invoke(Integer id, Set<String> orderNumbers) {
        System.out.println(id);
    }

    @Override
    public void invoke(Long id, Set<String> orderNumbers) {
        System.out.println(id);
    }
}

Start telnet call service:

invoke com.youzan.nova.service.OverrideService.invoke("13", Set["1"])
invoke com.youzan.nova.service.OverrideService.invoke("13L", Set["1"])

Always only call the method invoke(Long id, Set<String> orderNumbers).

@zonghaishang zonghaishang added the type/bug Bugs to being fixed label Nov 9, 2018
@zonghaishang zonghaishang self-assigned this Nov 9, 2018
@bert82503
Copy link

为何调用的第一个参数值是字符串,如("13", Set["1"]),而不是(13, Set["1"])

@zonghaishang
Copy link
Member Author

传递13也是可以的,一样

@kexianjun
Copy link
Member

`private static boolean isMatch(Class[] types, List args) { if (types.length != args.size()) { return false; } for (int i = 0; i < types.length; i++) { Class type = types[i];
Object arg = args.get(i);

        if (arg == null) {
            // if the type is primitive, the method to invoke will cause NullPointerException definitely
            // so we can offer a specified error message to the invoker in advance and avoid unnecessary invoking
            if (type.isPrimitive()) {
                throw new NullPointerException(String.format(
                        "The type of No.%d parameter is primitive(%s), but the value passed is null.", i + 1, type.getName()));
            }

            // if the type is not primitive, we choose to believe what the invoker want is a null value
            continue;
        }

        if (ReflectUtils.isPrimitive(arg.getClass())) {
            if (!ReflectUtils.isPrimitive(type)) {
                return false;
            }
        } else if (arg instanceof Map) {
            String name = (String) ((Map<?, ?>) arg).get("class");
            Class<?> cls = arg.getClass();
            if (name != null && name.length() > 0) {
                cls = ReflectUtils.forName(name);
            }
            if (!type.isAssignableFrom(cls)) {
                return false;
            }
        } else if (arg instanceof Collection) {
            if (!type.isArray() && !type.isAssignableFrom(arg.getClass())) {
                return false;
            }
        } else {
            if (!type.isAssignableFrom(arg.getClass())) {
                return false;
            }
        }
    }
    return true;
}` 

这个方法判断有问题吧
'if (ReflectUtils.isPrimitive(arg.getClass())) {
if (!ReflectUtils.isPrimitive(type)) {
return false;
}'
这里只判断了是不是同为基本类型,如果同为基本类型没有继续判断类型是否兼容了,导致不管示例中第一个参数传什么,都是匹配到第一个方法了

@zonghaishang
Copy link
Member Author

zonghaishang commented Nov 12, 2018

yes, @kexianjun Welcome to fix this bug, :-)

@tswstarplanet
Copy link
Contributor

  • I have searched the issues of this repository and believe that this is not a duplicate.
  • I have checked the FAQ of this repository and believe that this is not a duplicate.

Environment

  • Dubbo version: 2.7.0+
  • Operating System version: mac
  • Java version: 1.8

Steps to reproduce this issue

Assume that there is an interface below:

package com.youzan.nova.service;

import java.util.Set;

public interface OverrideService {

    void invoke(Integer id, Set<String> orderNumbers);

    void invoke(Long id, Set<String> orderNumbers);

}

package com.youzan.nova.service;

import java.util.Set;

public class OverrideServiceImpl implements OverrideService {
    @Override
    public void invoke(Integer id, Set<String> orderNumbers) {
        System.out.println(id);
    }

    @Override
    public void invoke(Long id, Set<String> orderNumbers) {
        System.out.println(id);
    }
}

Start telnet call service:

invoke com.youzan.nova.service.OverrideService.invoke("13", Set["1"])
invoke com.youzan.nova.service.OverrideService.invoke("13L", Set["1"])

Always only call the method invoke(Long id, Set<String> orderNumbers).

我试了下,参数带L后缀不能被正确解析成Long类型的数字

@tswstarplanet
Copy link
Contributor

  • I have searched the issues of this repository and believe that this is not a duplicate.
  • I have checked the FAQ of this repository and believe that this is not a duplicate.

Environment

  • Dubbo version: 2.7.0+
  • Operating System version: mac
  • Java version: 1.8

Steps to reproduce this issue

Assume that there is an interface below:

package com.youzan.nova.service;

import java.util.Set;

public interface OverrideService {

    void invoke(Integer id, Set<String> orderNumbers);

    void invoke(Long id, Set<String> orderNumbers);

}

package com.youzan.nova.service;

import java.util.Set;

public class OverrideServiceImpl implements OverrideService {
    @Override
    public void invoke(Integer id, Set<String> orderNumbers) {
        System.out.println(id);
    }

    @Override
    public void invoke(Long id, Set<String> orderNumbers) {
        System.out.println(id);
    }
}

Start telnet call service:

invoke com.youzan.nova.service.OverrideService.invoke("13", Set["1"])
invoke com.youzan.nova.service.OverrideService.invoke("13L", Set["1"])

Always only call the method invoke(Long id, Set<String> orderNumbers).

我试了下,参数带L后缀不能被正确解析成Long类型的数字

字符串带L不能正确解析

@tswstarplanet
Copy link
Contributor

#2787

@kexianjun
Copy link
Member

another problem,if a method contains complex parameters,Such as class Student below,the invoke command can never invoke the correct method since com.alibaba.fastjson.JSON#parseArray(java.lang.String, java.lang.Class) can not parse args to correct class,in blow method to parse the args (com.alibaba.dubbo.rpc.protocol.dubbo.telnet.InvokeTelnetHandler#telnet; list = JSON.parseArray("[" + args + "]", Object.class);)

public String telnet(Channel channel, String message) {
        if (message == null || message.length() == 0) {
            return "Please input method name, eg: \r\ninvoke xxxMethod(1234, \"abcd\", {\"prop\" : \"value\"})\r\ninvoke XxxService.xxxMethod(1234, \"abcd\", {\"prop\" : \"value\"})\r\ninvoke com.xxx.XxxService.xxxMethod(1234, \"abcd\", {\"prop\" : \"value\"})";
        }
        StringBuilder buf = new StringBuilder();
        String service = (String) channel.getAttribute(ChangeTelnetHandler.SERVICE_KEY);
        if (service != null && service.length() > 0) {
            buf.append("Use default service " + service + ".\r\n");
        }
        int i = message.indexOf("(");
        if (i < 0 || !message.endsWith(")")) {
            return "Invalid parameters, format: service.method(args)";
        }
        String method = message.substring(0, i).trim();
        String args = message.substring(i + 1, message.length() - 1).trim();
        i = method.lastIndexOf(".");
        if (i >= 0) {
            service = method.substring(0, i).trim();
            method = method.substring(i + 1).trim();
        }
        List<Object> list;
        try {
            list = JSON.parseArray("[" + args + "]", Object.class);
        } catch (Throwable t) {
            return "Invalid json argument, cause: " + t.getMessage();
        }
...
}
public class Student implements Serializable {
    private String name;
    private Integer age;
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

,not like the Telnet Command Reference decribed about the invoke command.So I think there is necessary to enhance the invoke command and make the argument type known to it.

@beiwei30
Copy link
Member

@kexianjun I merged your change. Pls. check my comments on the pull request, and consider to update doc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/bug Bugs to being fixed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants