Alanxtl commented on code in PR #3154:
URL: https://github.com/apache/dubbo-go/pull/3154#discussion_r2688745078


##########
protocol/triple/triple.go:
##########
@@ -141,6 +149,18 @@ func (tp *TripleProtocol) Destroy() {
        tp.BaseProtocol.Destroy()
 }
 
+// isGenericCall checks if the generic parameter indicates a generic call
+func isGenericCall(generic string) bool {
+       if generic == "" {
+               return false
+       }
+       lowerGeneric := strings.ToLower(generic)
+       return lowerGeneric == constant.GenericSerializationDefault ||
+               lowerGeneric == constant.GenericSerializationGson ||
+               lowerGeneric == constant.GenericSerializationProtobuf ||
+               lowerGeneric == constant.GenericSerializationProtobufJson
+}

Review Comment:
   use `strings.EqualFold` instead, no need to `toLower` and `==`



##########
server/server.go:
##########
@@ -176,6 +179,61 @@ func (s *Server) genSvcOpts(handler any, info 
*common.ServiceInfo, opts ...Servi
        return newSvcOpts, nil
 }
 
+// isNillable checks if a reflect.Value's kind supports nil checking.
+func isNillable(v reflect.Value) bool {
+       switch v.Kind() {
+       case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, 
reflect.Pointer, reflect.Slice:
+               return true
+       default:
+               return false
+       }
+}
+
+// isReflectNil safely checks if a reflect.Value is nil.
+func isReflectNil(v reflect.Value) bool {
+       return isNillable(v) && v.IsNil()
+}
+
+// CallMethodByReflection invokes the given method via reflection and 
processes its return values.
+// This is a shared helper function used by both server/server.go and 
protocol/triple/server.go.
+func CallMethodByReflection(ctx context.Context, method reflect.Method, 
handler any, args []any) (any, error) {
+       in := []reflect.Value{reflect.ValueOf(handler)}
+       in = append(in, reflect.ValueOf(ctx))
+       for _, arg := range args {
+               in = append(in, reflect.ValueOf(arg))
+       }
+       returnValues := method.Func.Call(in)
+
+       // Process return values
+       if len(returnValues) == 1 {
+               if isReflectNil(returnValues[0]) {
+                       return nil, nil
+               }
+               if err, ok := returnValues[0].Interface().(error); ok {
+                       return nil, err
+               }
+               return nil, nil
+       }
+       var result any
+       var err error
+       if !isReflectNil(returnValues[0]) {
+               result = returnValues[0].Interface()
+       }
+       if len(returnValues) > 1 && !isReflectNil(returnValues[1]) {
+               if e, ok := returnValues[1].Interface().(error); ok {
+                       err = e
+               }
+       }
+       return result, err
+}
+
+// createReflectionMethodFunc creates a MethodFunc that calls the given method 
via reflection.
+func createReflectionMethodFunc(method reflect.Method) func(ctx 
context.Context, args []any, handler any) (any, error) {
+       return func(ctx context.Context, args []any, handler any) (any, error) {
+               return CallMethodByReflection(ctx, method, handler, args)
+       }
+}
+
 // Add a method with a name of a different first-letter case
 // to achieve interoperability with java
 // TODO: The method name case sensitivity in Dubbo-java should be addressed.

Review Comment:
   I'm wondering is this todo solved?



##########
protocol/triple/server.go:
##########
@@ -503,51 +503,101 @@ func createServiceInfoWithReflection(svc 
common.RPCService) *common.ServiceInfo
                if methodType.Name == "Reference" {
                        continue
                }
-               paramsNum := methodType.Type.NumIn()
-               // the first param is receiver itself, the second param is ctx
-               // just ignore them
-               if paramsNum < 2 {
-                       logger.Fatalf("TRIPLE does not support %s method that 
does not have any parameter", methodType.Name)
-                       continue
-               }
-               paramsTypes := make([]reflect.Type, paramsNum-2)
-               for j := 2; j < paramsNum; j++ {
-                       paramsTypes[j-2] = methodType.Type.In(j)
-               }
-               methodInfo := common.MethodInfo{
-                       Name: methodType.Name,
-                       // only support Unary invocation now
-                       Type: constant.CallUnary,
-                       ReqInitFunc: func() any {
-                               params := make([]any, len(paramsTypes))
-                               for k, paramType := range paramsTypes {
-                                       params[k] = 
reflect.New(paramType).Interface()
-                               }
-                               return params
-                       },
+               methodInfo := buildMethodInfoWithReflection(methodType)
+               if methodInfo != nil {
+                       methodInfos = append(methodInfos, *methodInfo)
                }
-               methodInfos = append(methodInfos, methodInfo)
        }
 
-       // only support no-idl mod call unary
-       genericMethodInfo := common.MethodInfo{
-               Name: "$invoke",
-               Type: constant.CallUnary,
+       // Add $invoke method for generic call support
+       methodInfos = append(methodInfos, buildGenericMethodInfo())

Review Comment:
   this `methodInfos` is appended inside the loop in line 508 and appended 
outside the loop in line 513, is it correct?



##########
protocol/triple/triple_protocol/codec.go:
##########
@@ -227,29 +322,51 @@ func (c *protoWrapperCodec) Marshal(message any) ([]byte, 
error) {
        return proto.Marshal(wrapperReq)
 }
 
+// Unmarshal handles both TripleResponseWrapper (for responses) and 
TripleRequestWrapper (for requests).
+// It determines the format by checking if message is a slice (request) or not 
(response).
 func (c *protoWrapperCodec) Unmarshal(binary []byte, message any) error {
-       var params []any
-       var ok bool
-       params, ok = message.([]any)
-       if !ok {
-               params = []any{message}
-       }
+       // Check if message is a slice - if so, it's a request with multiple 
args
+       params, isSlice := message.([]any)
+       if isSlice {

Review Comment:
   ditto



##########
server/server.go:
##########
@@ -176,6 +179,61 @@ func (s *Server) genSvcOpts(handler any, info 
*common.ServiceInfo, opts ...Servi
        return newSvcOpts, nil
 }
 
+// isNillable checks if a reflect.Value's kind supports nil checking.
+func isNillable(v reflect.Value) bool {
+       switch v.Kind() {
+       case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, 
reflect.Pointer, reflect.Slice:
+               return true
+       default:
+               return false
+       }
+}
+
+// isReflectNil safely checks if a reflect.Value is nil.
+func isReflectNil(v reflect.Value) bool {
+       return isNillable(v) && v.IsNil()
+}

Review Comment:
   is this method redefined in the protocol/triple/server.go:594?



##########
protocol/triple/triple_protocol/codec.go:
##########
@@ -114,11 +118,62 @@ func (c *protoBinaryCodec) Marshal(message any) ([]byte, 
error) {
 func (c *protoBinaryCodec) Unmarshal(data []byte, message any) error {
        protoMessage, ok := message.(proto.Message)
        if !ok {
-               return errNotProto(message)
+               // Non-proto types indicate a generic call - try to unwrap from 
wrapper format.
+               // This is used by the server when receiving Java/Go generic 
calls.
+               return c.unmarshalWrappedMessage(data, message)
        }
        return proto.Unmarshal(data, protoMessage)
 }
 
+// unmarshalWrappedMessage handles both TripleResponseWrapper and 
TripleRequestWrapper formats.
+// It determines the format by checking if message is a slice (request) or not 
(response).
+func (c *protoBinaryCodec) unmarshalWrappedMessage(data []byte, message any) 
error {
+       hessianCodec := &hessian2Codec{}
+
+       // Check if message is a slice - if so, it's a request with multiple 
args
+       params, isSlice := message.([]any)
+       if isSlice {

Review Comment:
   ```suggestion
        if params, isSlice := message.([]any); isSlice {
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to