diff --git a/common/proxy/proxy.go b/common/proxy/proxy.go index 044f6018ad49ff43a5d3e881dbc48fffb3649698..a7c0ab8bed7abeebad824824b402285279d66367 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 82745527672f24c3da10c1d1a4c513c0c112a0c9..60679e00dbff0b15d3242858cd5b2533eec2fa11 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 5d5c7283b32dfa55e8a39072ce8a0e126842e9fc..41476149c09d0d44140717076c7fc8c13152b348 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 89c35a6c69866965007711ac4ecc8b4165d18382..62ae4a1056de5368dfc168cab465ee6fc2f6a3d6 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 c6dfc9ebdf1d32db0fe514a6a40086317b82ae92..4ec6c5af35013e1c9707ca50b5329494f5ee5a90 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 1e31338e3ddafe53b3228dd98cdd0d9167def36f..02aa25413237be3e90cce936234fe13e074e076b 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 c04acefbe25fc1f1110de9c27d0ef0fb36721d74..69229943fcda3aae24970fb5ad7f05736696790a 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 add09807e7673805bf18553a74941466b3138203..d5bce8105673a24d78ddd3a636788d1ccf8e57a6 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 55ec64c24ff0e0b79894a4f67fb85fb489d38b77..b75740bbcd26a6438d22f7d3bf08fa5e316f7aa7 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 ff051a97e5c50e760cc9e29aca79276295caff2f..f0d7faf3df40c3d422407ddf4d2f2c501e1efdf7 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 2464ca1c2c5dbb3b615315ba91decae2cd6d7166..1311bd807d59d8336f4ada1296d3a05abd31a548 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 304165ca96958bf149ba42155874db8b89d31346..4dd53dff36fcef36277a0eaa84c0830cc5ccbfb7 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 8d9f7fa5bc2c512bfd0d0d393178fb95e7143cbf..8cfc84bca8c02851a85d8416ab280bd7aee92a79 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 4f65f428295666bf5da9fd0db31e9c77352d91d8..cdf95ba07c54067c06872597693152b94010f307 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 fec1597240ee351e6b53a3cb6a43a18ca33eef6e..832f78e8553c5c55ea7f7d15566ddee7ac1268de 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 add09807e7673805bf18553a74941466b3138203..d5bce8105673a24d78ddd3a636788d1ccf8e57a6 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 55ec64c24ff0e0b79894a4f67fb85fb489d38b77..b75740bbcd26a6438d22f7d3bf08fa5e316f7aa7 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 ff051a97e5c50e760cc9e29aca79276295caff2f..157253575b9e5e75dadaaeaffa1e256374fefa5d 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 2464ca1c2c5dbb3b615315ba91decae2cd6d7166..25e97dd1c4482f2ff6ae7acb1ecb01a5ed66b328 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 5631d9747a61e0af469f9480eb0a443a9bc4e438..2938f569d59ae2b85035170183d672fa0854bd39 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 a1268497e1e07174d4af7100e43e5c1ebbc44a32..5817e3e2270a47dc4fb37ea86533f0673c3d8c8f 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 11db1f9cd9380d1e86398b9b3021371bd9ab1199..e70d5b83fdfa72be519dd61df5e4b358452bb40f 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 c514bfcdc11809004cf5ae0054acc2bbf6680df4..a54dcb9d0f0bf97751b85c3c8ea5975fb761e03f 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() }