From 0ac0a4a6fd217457fca00e6fbe63b392ce704b0d Mon Sep 17 00:00:00 2001
From: fangyincheng <fangyincheng@sina.com>
Date: Thu, 23 May 2019 14:14:52 +0800
Subject: [PATCH] Imp:modify calling mode of server

---
 common/proxy/proxy.go                         |  2 +-
 common/rpc_service.go                         | 86 +++++++++++--------
 common/rpc_service_test.go                    | 29 +++----
 examples/dubbo/go-client/app/client.go        |  2 +-
 examples/dubbo/go-client/app/user.go          |  2 +-
 examples/dubbo/go-server/app/user.go          | 20 +++--
 .../main/java/com/ikurento/user/Consumer.java |  4 +
 .../java/com/ikurento/user/UserProvider.java  |  7 +-
 .../java/com/ikurento/user/UserProvider.java  |  2 +
 .../user/UserProviderAnotherImpl.java         |  4 +
 .../com/ikurento/user/UserProviderImpl.java   |  3 +
 examples/jsonrpc/go-client/app/client.go      |  2 +-
 examples/jsonrpc/go-client/app/user.go        |  2 +-
 examples/jsonrpc/go-server/app/user.go        | 18 ++++
 .../main/java/com/ikurento/user/Consumer.java |  4 +
 .../java/com/ikurento/user/UserProvider.java  |  7 +-
 .../java/com/ikurento/user/UserProvider.java  |  2 +
 .../user/UserProviderAnotherImpl.java         |  4 +
 .../com/ikurento/user/UserProviderImpl.java   |  4 +
 protocol/dubbo/client_test.go                 |  6 +-
 protocol/dubbo/listener.go                    | 40 ++++++---
 protocol/jsonrpc/http_test.go                 |  6 +-
 protocol/jsonrpc/server.go                    | 51 ++++++-----
 23 files changed, 197 insertions(+), 110 deletions(-)

diff --git a/common/proxy/proxy.go b/common/proxy/proxy.go
index 044f6018a..a7c0ab8be 100644
--- a/common/proxy/proxy.go
+++ b/common/proxy/proxy.go
@@ -150,7 +150,7 @@ func (p *Proxy) Implement(v common.RPCService) {
 
 			// reply must be Ptr when outNum == 1
 			if outNum == 1 && t.Type.In(inNum-1).Kind() != reflect.Ptr {
-				log.Warn("reply type of method %q is not a pointer or interface", t.Name)
+				log.Warn("reply type of method %q is not a pointer", t.Name)
 				continue
 			}
 
diff --git a/common/rpc_service.go b/common/rpc_service.go
index 827455276..60679e00d 100644
--- a/common/rpc_service.go
+++ b/common/rpc_service.go
@@ -51,9 +51,9 @@ var (
 
 type MethodType struct {
 	method    reflect.Method
-	ctxType   reflect.Type // type of the request context
-	argType   reflect.Type
-	replyType reflect.Type
+	ctxType   reflect.Type   // request context
+	argsType  []reflect.Type // args except ctx, include replyType if existing
+	replyType reflect.Type   // return value, otherwise it is nil
 }
 
 func (m *MethodType) Method() reflect.Method {
@@ -62,8 +62,8 @@ func (m *MethodType) Method() reflect.Method {
 func (m *MethodType) CtxType() reflect.Type {
 	return m.ctxType
 }
-func (m *MethodType) ArgType() reflect.Type {
-	return m.argType
+func (m *MethodType) ArgsType() []reflect.Type {
+	return m.argsType
 }
 func (m *MethodType) ReplyType() reflect.Type {
 	return m.replyType
@@ -224,51 +224,61 @@ func suitableMethods(typ reflect.Type) (string, map[string]*MethodType) {
 func suiteMethod(method reflect.Method) *MethodType {
 	mtype := method.Type
 	mname := method.Name
+	inNum := mtype.NumIn()
+	outNum := mtype.NumOut()
 
 	// Method must be exported.
 	if method.PkgPath != "" {
 		return nil
 	}
 
-	var replyType, argType, ctxType reflect.Type
-	switch mtype.NumIn() {
-	case 3:
-		argType = mtype.In(1)
-		replyType = mtype.In(2)
-	case 4:
-		ctxType = mtype.In(1)
-		argType = mtype.In(2)
-		replyType = mtype.In(3)
-	default:
-		log.Error("method %s of mtype %v has wrong number of in parameters %d; needs exactly 3/4",
-			mname, mtype, mtype.NumIn())
-		return nil
-	}
-	// First arg need not be a pointer.
-	if !isExportedOrBuiltinType(argType) {
-		log.Error("argument type of method %q is not exported %v", mname, argType)
+	var (
+		replyType, ctxType reflect.Type
+		argsType           []reflect.Type
+	)
+
+	if outNum != 1 && outNum != 2 {
+		log.Warn("method %s of mtype %v has wrong number of in out parameters %d; needs exactly 1/2",
+			mname, mtype.String(), outNum)
 		return nil
 	}
-	// Second arg must be a pointer.
-	if replyType.Kind() != reflect.Ptr {
-		log.Error("reply type of method %q is not a pointer %v", mname, replyType)
+
+	// The latest return type of the method must be error.
+	if returnType := mtype.Out(outNum - 1); returnType != typeOfError {
+		log.Warn("the latest return type %s of method %q is not error", returnType, mname)
 		return nil
 	}
-	// Reply type must be exported.
-	if !isExportedOrBuiltinType(replyType) {
-		log.Error("reply type of method %s not exported{%v}", mname, replyType)
-		return nil
+
+	// replyType
+	if outNum == 1 {
+		if mtype.In(inNum-1).Kind() != reflect.Ptr {
+			log.Error("reply type of method %q is not a pointer %v", mname, replyType)
+			return nil
+		}
+	} else {
+		replyType = mtype.Out(0)
+		if !isExportedOrBuiltinType(replyType) {
+			log.Error("reply type of method %s not exported{%v}", mname, replyType)
+			return nil
+		}
 	}
-	// Method needs one out.
-	if mtype.NumOut() != 1 {
-		log.Error("method %q has %d out parameters; needs exactly 1", mname, mtype.NumOut())
-		return nil
+
+	index := 1
+
+	// ctxType
+	if mtype.In(1).String() == "context.Context" {
+		ctxType = mtype.In(1)
+		index = 2
 	}
-	// The return type of the method must be error.
-	if returnType := mtype.Out(0); returnType != typeOfError {
-		log.Error("return type %s of method %q is not error", returnType, mname)
-		return nil
+
+	for ; index < inNum; index++ {
+		argsType = append(argsType, mtype.In(index))
+		// need not be a pointer.
+		if !isExportedOrBuiltinType(mtype.In(index)) {
+			log.Error("argument type of method %q is not exported %v", mname, mtype.In(index))
+			return nil
+		}
 	}
 
-	return &MethodType{method: method, argType: argType, replyType: replyType, ctxType: ctxType}
+	return &MethodType{method: method, argsType: argsType, replyType: replyType, ctxType: ctxType}
 }
diff --git a/common/rpc_service_test.go b/common/rpc_service_test.go
index 5d5c7283b..41476149c 100644
--- a/common/rpc_service_test.go
+++ b/common/rpc_service_test.go
@@ -30,9 +30,8 @@ type TestService struct {
 func (s *TestService) MethodOne(ctx context.Context, args []interface{}, rsp *struct{}) error {
 	return nil
 }
-func (s *TestService) MethodTwo(args []interface{}, rsp *struct{}) error {
-	return nil
-
+func (s *TestService) MethodTwo(args []interface{}) (struct{}, error) {
+	return struct{}{}, nil
 }
 func (s *TestService) Service() string {
 	return "com.test.Path"
@@ -50,8 +49,8 @@ func (s *testService) Method1(ctx context.Context, args testService, rsp *struct
 func (s *testService) Method2(ctx context.Context, args []interface{}, rsp struct{}) error {
 	return nil
 }
-func (s *testService) Method3(ctx context.Context, args []interface{}, rsp *testService) error {
-	return nil
+func (s *testService) Method3(ctx context.Context, args []interface{}) (testService, error) {
+	return testService{}, nil
 }
 func (s *testService) Method4(ctx context.Context, args []interface{}, rsp *struct{}) {
 }
@@ -131,33 +130,33 @@ func TestMethodType_SuiteContext(t *testing.T) {
 }
 
 func TestSuiteMethod(t *testing.T) {
-	// 4
+
 	s := &TestService{}
 	method, ok := reflect.TypeOf(s).MethodByName("MethodOne")
 	assert.True(t, ok)
 	methodType := suiteMethod(method)
 	method = methodType.Method()
 	assert.Equal(t, "func(*common.TestService, context.Context, []interface {}, *struct {}) error", method.Type.String())
-	at := methodType.ArgType()
-	assert.Equal(t, "[]interface {}", at.String())
+	at := methodType.ArgsType()
+	assert.Equal(t, "[]interface {}", at[0].String())
+	assert.Equal(t, "*struct {}", at[1].String())
 	ct := methodType.CtxType()
 	assert.Equal(t, "context.Context", ct.String())
 	rt := methodType.ReplyType()
-	assert.Equal(t, "*struct {}", rt.String())
+	assert.Nil(t, rt)
 
-	// 3
 	method, ok = reflect.TypeOf(s).MethodByName("MethodTwo")
 	assert.True(t, ok)
 	methodType = suiteMethod(method)
 	method = methodType.Method()
-	assert.Equal(t, "func(*common.TestService, []interface {}, *struct {}) error", method.Type.String())
-	at = methodType.ArgType()
-	assert.Equal(t, "[]interface {}", at.String())
+	assert.Equal(t, "func(*common.TestService, []interface {}) (struct {}, error)", method.Type.String())
+	at = methodType.ArgsType()
+	assert.Equal(t, "[]interface {}", at[0].String())
 	assert.Nil(t, methodType.CtxType())
 	rt = methodType.ReplyType()
-	assert.Equal(t, "*struct {}", rt.String())
+	assert.Equal(t, "struct {}", rt.String())
 
-	// wrong number of in parameters
+	// wrong number of in return
 	s1 := &testService{}
 	method, ok = reflect.TypeOf(s1).MethodByName("Version")
 	assert.True(t, ok)
diff --git a/examples/dubbo/go-client/app/client.go b/examples/dubbo/go-client/app/client.go
index 89c35a6c6..62ae4a105 100644
--- a/examples/dubbo/go-client/app/client.go
+++ b/examples/dubbo/go-client/app/client.go
@@ -83,7 +83,7 @@ func main() {
 	println("response result: %v", user)
 
 	println("\n\n\nstart to test dubbo - GetUser0")
-	ret, err := conMap["com.ikurento.user.UserProvider"].GetRPCService().(*UserProvider).GetUser0(context.TODO(), "A003")
+	ret, err := conMap["com.ikurento.user.UserProvider"].GetRPCService().(*UserProvider).GetUser0("A003", "Moorse")
 	if err != nil {
 		panic(err)
 	}
diff --git a/examples/dubbo/go-client/app/user.go b/examples/dubbo/go-client/app/user.go
index c6dfc9ebd..4ec6c5af3 100644
--- a/examples/dubbo/go-client/app/user.go
+++ b/examples/dubbo/go-client/app/user.go
@@ -94,7 +94,7 @@ func (User) JavaClassName() string {
 
 type UserProvider struct {
 	GetUser  func(ctx context.Context, req []interface{}, rsp *User) error
-	GetUser0 func(ctx context.Context, req interface{}) (User, error) `dubbo:"GetUser"`
+	GetUser0 func(id string, name string) (User, error)
 	GetUser1 func(ctx context.Context, req []interface{}, rsp *User) error
 	GetUser2 func(ctx context.Context, req []interface{}, rsp *User) error   `dubbo:"getUser"`
 	Echo     func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used
diff --git a/examples/dubbo/go-server/app/user.go b/examples/dubbo/go-server/app/user.go
index 1e31338e3..02aa25413 100644
--- a/examples/dubbo/go-server/app/user.go
+++ b/examples/dubbo/go-server/app/user.go
@@ -23,6 +23,7 @@ import (
 
 import (
 	"github.com/dubbogo/hessian2"
+	perrors "github.com/pkg/errors"
 )
 
 import (
@@ -137,15 +138,24 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User
 	if err == nil {
 		*rsp = *user
 		println("rsp:%#v", rsp)
-		// s, _ := json.Marshal(rsp)
-		// fmt.Println("hello0:", string(s))
-
-		// s, _ = json.Marshal(*rsp)
-		// fmt.Println("hello1:", string(s))
 	}
 	return err
 }
 
+func (u *UserProvider) GetUser0(id string, name string) (User, error) {
+	var err error
+
+	println("id:%s, name:%s", id, name)
+	user, err := u.getUser(id)
+	if err != nil {
+		return User{}, err
+	}
+	if user.Name != name {
+		return User{}, perrors.New("name is not " + user.Name)
+	}
+	return *user, err
+}
+
 func (u *UserProvider) Service() string {
 	return "com.ikurento.user.UserProvider"
 }
diff --git a/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java b/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java
index c04acefbe..69229943f 100644
--- a/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java
+++ b/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java
@@ -47,6 +47,10 @@ public class Consumer {
             System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " +
                     " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString()
                     + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString());
+            User user2 = userProvider.GetUser0("A003","Moorse");
+            System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " +
+                     " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString()
+                     + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString());
         } catch (Exception e) {
             e.printStackTrace();
         }
diff --git a/examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java b/examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java
index add09807e..d5bce8105 100644
--- a/examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java
+++ b/examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 1999-2011 Alibaba Group.
- *  
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- *  
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- *  
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,4 +22,5 @@ public interface UserProvider {
 	User GetUser(String userId);
 
 	List<User> GetUsers(List<String> userIdList);
+	User GetUser0(String userId, String name);
 }
diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java
index 55ec64c24..b75740bbc 100644
--- a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java
+++ b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java
@@ -12,6 +12,8 @@ public interface UserProvider {
 
     List<User> GetUsers(List<String> userIdList);
 
+    User GetUser0(String userId, String name);
+
     Map<String, User> GetUserMap(List<String> userIdList);
 
     User getUser(int usercode);
diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java
index ff051a97e..f0d7faf3d 100644
--- a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java
+++ b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java
@@ -32,6 +32,10 @@ public class UserProviderAnotherImpl implements UserProvider {
         return new User(userId, "Joe", 48);
     }
 
+    public User GetUser0(String userId, String name) {
+                return new User(userId, name, 48);
+    }
+
     public List<User> GetUsers(ArrayList<String> userIdList) {
         Iterator it = userIdList.iterator();
         List<User> userList = new ArrayList<User>();
diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java
index 2464ca1c2..1311bd807 100644
--- a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java
+++ b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java
@@ -32,6 +32,9 @@ public class UserProviderImpl implements UserProvider {
     public User GetUser(String userId) {
         return new User(userId, "zhangsan", 18);
     }
+    public User GetUser0(String userId, String name) {
+            return new User(userId, name, 18);
+    }
 
     public List<User> GetUsers(List<String> userIdList) {
         Iterator it = userIdList.iterator();
diff --git a/examples/jsonrpc/go-client/app/client.go b/examples/jsonrpc/go-client/app/client.go
index 304165ca9..4dd53dff3 100644
--- a/examples/jsonrpc/go-client/app/client.go
+++ b/examples/jsonrpc/go-client/app/client.go
@@ -79,7 +79,7 @@ func main() {
 	println("response result: %v", user)
 
 	println("\n\n\nstart to test dubbo - GetUser0")
-	ret, err := conMap["com.ikurento.user.UserProvider"].GetRPCService().(*UserProvider).GetUser0(context.TODO(), "A003")
+	ret, err := conMap["com.ikurento.user.UserProvider"].GetRPCService().(*UserProvider).GetUser0("A003", "Moorse")
 	if err != nil {
 		panic(err)
 	}
diff --git a/examples/jsonrpc/go-client/app/user.go b/examples/jsonrpc/go-client/app/user.go
index 8d9f7fa5b..8cfc84bca 100644
--- a/examples/jsonrpc/go-client/app/user.go
+++ b/examples/jsonrpc/go-client/app/user.go
@@ -45,7 +45,7 @@ func (u JsonRPCUser) String() string {
 
 type UserProvider struct {
 	GetUser  func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error
-	GetUser0 func(ctx context.Context, req interface{}) (*JsonRPCUser, error) `dubbo:"GetUser"`
+	GetUser0 func(id string, name string) (JsonRPCUser, error)
 	GetUser1 func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error
 	GetUser2 func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error `dubbo:"getUser"`
 	Echo     func(ctx context.Context, req interface{}) (interface{}, error)      // Echo represent EchoFilter will be used
diff --git a/examples/jsonrpc/go-server/app/user.go b/examples/jsonrpc/go-server/app/user.go
index 4f65f4282..cdf95ba07 100644
--- a/examples/jsonrpc/go-server/app/user.go
+++ b/examples/jsonrpc/go-server/app/user.go
@@ -20,6 +20,10 @@ import (
 	"time"
 )
 
+import (
+	perrors "github.com/pkg/errors"
+)
+
 import (
 	"github.com/dubbo/go-for-apache-dubbo/config"
 )
@@ -106,6 +110,20 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User
 	return err
 }
 
+func (u *UserProvider) GetUser0(id string, name string) (User, error) {
+	var err error
+
+	println("id:%s, name:%s", id, name)
+	user, err := u.getUser(id)
+	if err != nil {
+		return User{}, err
+	}
+	if user.Name != name {
+		return User{}, perrors.New("name is not " + user.Name)
+	}
+	return *user, err
+}
+
 func (u *UserProvider) Service() string {
 	return "com.ikurento.user.UserProvider"
 }
diff --git a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java b/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java
index fec159724..832f78e85 100644
--- a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java
+++ b/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java
@@ -51,6 +51,10 @@ public class Consumer {
             System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " +
                     " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString()
                     + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString());
+            User user2 = userProvider.GetUser0("A003","Moorse");
+            System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " +
+                     " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString()
+                     + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString());
         } catch (Exception e) {
             e.printStackTrace();
         }
diff --git a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java b/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java
index add09807e..d5bce8105 100644
--- a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java
+++ b/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 1999-2011 Alibaba Group.
- *  
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- *  
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- *  
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,4 +22,5 @@ public interface UserProvider {
 	User GetUser(String userId);
 
 	List<User> GetUsers(List<String> userIdList);
+	User GetUser0(String userId, String name);
 }
diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java
index 55ec64c24..b75740bbc 100644
--- a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java
+++ b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java
@@ -12,6 +12,8 @@ public interface UserProvider {
 
     List<User> GetUsers(List<String> userIdList);
 
+    User GetUser0(String userId, String name);
+
     Map<String, User> GetUserMap(List<String> userIdList);
 
     User getUser(int usercode);
diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java
index ff051a97e..157253575 100644
--- a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java
+++ b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java
@@ -32,6 +32,10 @@ public class UserProviderAnotherImpl implements UserProvider {
         return new User(userId, "Joe", 48);
     }
 
+     public User GetUser0(String userId, String name) {
+         return new User(userId, name, 48);
+     }
+
     public List<User> GetUsers(ArrayList<String> userIdList) {
         Iterator it = userIdList.iterator();
         List<User> userList = new ArrayList<User>();
diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java
index 2464ca1c2..25e97dd1c 100644
--- a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java
+++ b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java
@@ -33,6 +33,10 @@ public class UserProviderImpl implements UserProvider {
         return new User(userId, "zhangsan", 18);
     }
 
+    public User GetUser0(String userId, String name) {
+        return new User(userId, name, 18);
+    }
+
     public List<User> GetUsers(List<String> userIdList) {
         Iterator it = userIdList.iterator();
         List<User> userList = new ArrayList<User>();
diff --git a/protocol/dubbo/client_test.go b/protocol/dubbo/client_test.go
index 5631d9747..2938f569d 100644
--- a/protocol/dubbo/client_test.go
+++ b/protocol/dubbo/client_test.go
@@ -183,10 +183,8 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User
 	return nil
 }
 
-func (u *UserProvider) GetUser0(req []interface{}, rsp *User) error {
-	rsp.Id = req[0].(string)
-	rsp.Name = req[1].(string)
-	return nil
+func (u *UserProvider) GetUser0(id string, name string) (User, error) {
+	return User{Id: id, Name: name}, nil
 }
 
 func (u *UserProvider) GetUser1(ctx context.Context, req []interface{}, rsp *User) error {
diff --git a/protocol/dubbo/listener.go b/protocol/dubbo/listener.go
index a1268497e..5817e3e22 100644
--- a/protocol/dubbo/listener.go
+++ b/protocol/dubbo/listener.go
@@ -291,24 +291,38 @@ func (h *RpcServerHandler) callService(req *DubboPackage, ctx context.Context) {
 		return
 	}
 
-	// prepare argv
-	argv := req.Body.(map[string]interface{})["args"] // type is []interface
+	in := []reflect.Value{svc.Rcvr()}
+	if method.CtxType() != nil {
+		in = append(in, method.SuiteContext(ctx))
+	}
 
-	// prepare replyv
-	replyv := reflect.New(method.ReplyType().Elem())
-	var returnValues []reflect.Value
-	if method.CtxType() == nil {
-		returnValues = method.Method().Func.Call([]reflect.Value{svc.Rcvr(), reflect.ValueOf(argv), reflect.ValueOf(replyv.Interface())})
+	// prepare argv
+	argv := req.Body.(map[string]interface{})["args"]
+	if (len(method.ArgsType()) == 1 || len(method.ArgsType()) == 2 && method.ReplyType() == nil) && method.ArgsType()[0].String() == "[]interface {}" {
+		in = append(in, reflect.ValueOf(argv))
 	} else {
-		if contextv := reflect.ValueOf(ctx); contextv.IsValid() {
-			returnValues = method.Method().Func.Call([]reflect.Value{svc.Rcvr(), contextv, reflect.ValueOf(argv), reflect.ValueOf(replyv.Interface())})
-		} else {
-			returnValues = method.Method().Func.Call([]reflect.Value{svc.Rcvr(), reflect.Zero(method.CtxType()), reflect.ValueOf(argv), reflect.ValueOf(replyv.Interface())})
+		for i := 0; i < len(argv.([]interface{})); i++ {
+			in = append(in, reflect.ValueOf(argv.([]interface{})[i]))
 		}
 	}
 
-	// The return value for the method is an error.
-	if retErr := returnValues[0].Interface(); retErr != nil {
+	// prepare replyv
+	var replyv reflect.Value
+	if method.ReplyType() == nil {
+		replyv = reflect.New(method.ArgsType()[len(method.ArgsType())-1].Elem())
+		in = append(in, replyv)
+	}
+
+	returnValues := method.Method().Func.Call(in)
+
+	var retErr interface{}
+	if len(returnValues) == 1 {
+		retErr = returnValues[0].Interface()
+	} else {
+		replyv = returnValues[0]
+		retErr = returnValues[1].Interface()
+	}
+	if retErr != nil {
 		req.Header.ResponseStatus = hessian.Response_SERVER_ERROR
 		req.Body = retErr.(error)
 	} else {
diff --git a/protocol/jsonrpc/http_test.go b/protocol/jsonrpc/http_test.go
index 11db1f9cd..e70d5b83f 100644
--- a/protocol/jsonrpc/http_test.go
+++ b/protocol/jsonrpc/http_test.go
@@ -111,10 +111,8 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User
 	return nil
 }
 
-func (u *UserProvider) GetUser0(req []interface{}, rsp *User) error {
-	rsp.Id = req[0].(string)
-	rsp.Name = req[1].(string)
-	return nil
+func (u *UserProvider) GetUser0(id string, name string) (User, error) {
+	return User{Id: id, Name: name}, nil
 }
 
 func (u *UserProvider) GetUser1(ctx context.Context, req []interface{}, rsp *User) error {
diff --git a/protocol/jsonrpc/server.go b/protocol/jsonrpc/server.go
index c514bfcdc..a54dcb9d0 100644
--- a/protocol/jsonrpc/server.go
+++ b/protocol/jsonrpc/server.go
@@ -354,34 +354,45 @@ func serveRequest(ctx context.Context,
 	if svc == nil {
 		return perrors.New("cannot find svc " + serviceName)
 	}
-	mtype := svc.Method()[methodName]
-	if mtype == nil {
+	method := svc.Method()[methodName]
+	if method == nil {
 		return perrors.New("cannot find method " + methodName + " of svc " + serviceName)
 	}
 
-	replyv := reflect.New(mtype.ReplyType().Elem())
+	in := []reflect.Value{svc.Rcvr()}
+	if method.CtxType() != nil {
+		in = append(in, method.SuiteContext(ctx))
+	}
+
+	// prepare argv
+	if (len(method.ArgsType()) == 1 || len(method.ArgsType()) == 2 && method.ReplyType() == nil) && method.ArgsType()[0].String() == "[]interface {}" {
+		in = append(in, reflect.ValueOf(args))
+	} else {
+		for i := 0; i < len(args.([]interface{})); i++ {
+			in = append(in, reflect.ValueOf(args.([]interface{})[i]))
+		}
+	}
+
+	// prepare replyv
+	var replyv reflect.Value
+	if method.ReplyType() == nil {
+		replyv = reflect.New(method.ArgsType()[len(method.ArgsType())-1].Elem())
+		in = append(in, replyv)
+	}
+
+	returnValues := method.Method().Func.Call(in)
 
-	//  call service.method(args)
 	var (
-		errMsg       string
-		returnValues []reflect.Value
+		retErr interface{}
+		errMsg string
 	)
-	if mtype.CtxType() == nil {
-		returnValues = mtype.Method().Func.Call([]reflect.Value{
-			svc.Rcvr(),
-			reflect.ValueOf(args),
-			reflect.ValueOf(replyv.Interface()),
-		})
+	if len(returnValues) == 1 {
+		retErr = returnValues[0].Interface()
 	} else {
-		returnValues = mtype.Method().Func.Call([]reflect.Value{
-			svc.Rcvr(),
-			mtype.SuiteContext(ctx),
-			reflect.ValueOf(args),
-			reflect.ValueOf(replyv.Interface()),
-		})
+		replyv = returnValues[0]
+		retErr = returnValues[1].Interface()
 	}
-	// The return value for the method is an error.
-	if retErr := returnValues[0].Interface(); retErr != nil {
+	if retErr != nil {
 		errMsg = retErr.(error).Error()
 	}
 
-- 
GitLab