@Override
    public String execute(CommandContext commandContext, String[] args) {
        if (ArrayUtils.isEmpty(args)) {
            return "Please input method name, eg: \r\ninvoke xxxMethod(1234, \"abcd\", {\"prop\" : \"value\"})\r\n"
                    + "invoke XxxService.xxxMethod(1234, \"abcd\", {\"prop\" : \"value\"})\r\n"
                    + "invoke com.xxx.XxxService.xxxMethod(1234, \"abcd\", {\"prop\" : \"value\"})";
        }
        Channel channel = commandContext.getRemote();
        String service = channel.attr(ChangeTelnet.SERVICE_KEY) != null
                ? channel.attr(ChangeTelnet.SERVICE_KEY).get()
                : null;

        String message = args[0];
        int i = message.indexOf("(");

        if (i < 0 || !message.endsWith(")")) {
            return "Invalid parameters, format: service.method(args)";
        }

        String method = message.substring(0, i).trim();
        String param = 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();
        }

        if (StringUtils.isEmpty(service)) {
            return "If you want to invoke like [invoke sayHello(\"xxxx\")], please execute cd command first,"
                    + " or you can execute it like [invoke IHelloService.sayHello(\"xxxx\")]";
        }

        List<Object> list;
        try {
            list = JsonUtils.toJavaList("[" + param + "]", Object.class);
        } catch (Throwable t) {
            return "Invalid json argument, cause: " + t.getMessage();
        }
        StringBuilder buf = new StringBuilder();
        Method invokeMethod = null;
        ProviderModel selectedProvider = null;
        if (isInvokedSelectCommand(channel)) {
            selectedProvider = channel.attr(INVOKE_METHOD_PROVIDER_KEY).get();
            invokeMethod = channel.attr(SelectTelnet.SELECT_METHOD_KEY).get();
        } else {
            for (ProviderModel provider : frameworkModel.getServiceRepository().allProviderModels()) {
                if (!isServiceMatch(service, provider)) {
                    continue;
                }

                selectedProvider = provider;
                List<Method> methodList = findSameSignatureMethod(provider.getAllMethods(), method, list);
                if (CollectionUtils.isEmpty(methodList)) {
                    break;
                }

                if (methodList.size() == 1) {
                    invokeMethod = methodList.get(0);
                } else {
                    List<Method> matchMethods = findMatchMethods(methodList, list);
                    if (CollectionUtils.isEmpty(matchMethods)) {
                        break;
                    }
                    if (matchMethods.size() == 1) {
                        invokeMethod = matchMethods.get(0);
                    } else { // exist overridden method
                        channel.attr(INVOKE_METHOD_PROVIDER_KEY).set(provider);
                        channel.attr(INVOKE_METHOD_LIST_KEY).set(matchMethods);
                        channel.attr(INVOKE_MESSAGE_KEY).set(message);
                        printSelectMessage(buf, matchMethods);
                        return buf.toString();
                    }
                }
                break;
            }
        }

        if (!StringUtils.isEmpty(service)) {
            buf.append("Use default service ").append(service).append('.');
        }
        if (selectedProvider == null) {
            buf.append("\r\nNo such service ").append(service);
            return buf.toString();
        }
        if (invokeMethod == null) {
            buf.append("\r\nNo such method ")
                    .append(method)
                    .append(" in service ")
                    .append(service);
            return buf.toString();
        }
        try {
            Object[] array =
                    realize(list.toArray(), invokeMethod.getParameterTypes(), invokeMethod.getGenericParameterTypes());
            long start = System.currentTimeMillis();
            AppResponse result = new AppResponse();
            try {
                Object o = invokeMethod.invoke(selectedProvider.getServiceInstance(), array);
                boolean setValueDone = false;
                if (RpcContext.getServerAttachment().isAsyncStarted()) {
                    AsyncContext asyncContext = RpcContext.getServerAttachment().getAsyncContext();
                    if (asyncContext instanceof AsyncContextImpl) {
                        CompletableFuture<Object> internalFuture =
                                ((AsyncContextImpl) asyncContext).getInternalFuture();
                        result.setValue(internalFuture.get());
                        setValueDone = true;
                    }
                }
                if (!setValueDone) {
                    result.setValue(o);
                }
            } catch (Throwable t) {
                result.setException(t);
                if (t instanceof InterruptedException) {
                    Thread.currentThread().interrupt();
                }
            } finally {
                RpcContext.removeContext();
            }
            long end = System.currentTimeMillis();
            buf.append("\r\nresult: ");
            buf.append(JsonUtils.toJson(result.recreate()));
            buf.append("\r\nelapsed: ");
            buf.append(end - start);
            buf.append(" ms.");
        } catch (Throwable t) {
            return "Failed to invoke method " + invokeMethod.getName() + ", cause: " + StringUtils.toString(t);
        }
        return buf.toString();
    }
@Test
    void testInvokeWithoutServicePrefixAndWithoutDefaultService() throws RemotingException {
        registerProvider(DemoService.class.getName(), new DemoServiceImpl(), DemoService.class);
        String result = invoke.execute(mockCommandContext, new String[] {"echo(\"ok\")"});
        assertTrue(result.contains(
                "If you want to invoke like [invoke sayHello(\"xxxx\")], please execute cd command first,"
                        + " or you can execute it like [invoke IHelloService.sayHello(\"xxxx\")]"));
    }