Copilot commented on code in PR #1016:
URL: https://github.com/apache/dubbo-go-samples/pull/1016#discussion_r2680684072
##########
generic/README.md:
##########
@@ -1,88 +1,97 @@
-# Generic Call
+# Generic Sample (Triple Generic Call)
-Generic call is a mechanism that ensures information is correctly transmitted
when the client does not have interface information. It generalizes POJOs into
generic formats (such as dictionaries, strings), and is generally used in
scenarios like integration testing and gateways.
+[English](README.md) | [中文](README_zh.md)
-This example demonstrates generic calls between Dubbo-Go and Dubbo Java
services, showing how services can interoperate regardless of the language
they're implemented in.
+This sample demonstrates how to use generic invocation with the Triple
protocol for Go-Java interoperability. Generic invocation allows calling remote
services without generating stubs or having the service interface locally.
-## Directory Structure
+## Layout
-- go-server: Dubbo-Go server example
-- go-client: Dubbo-Go client example with generic calls
-- java-client: Dubbo Java client example
-- java-server: Dubbo Java server example
-- build: For integration test
-
-Dubbo Java examples can be used to test interoperability with Dubbo-Go. You
can start java server with go client, or go server with java client for testing.
+```
+generic/
+├── go-server/ # Go provider listening on :50052
+├── go-client/ # Go consumer with generic invocation
+├── java-server/ # Java provider listening on :50052
+└── java-client/ # Java consumer with generic invocation
+```
## Prerequisites
-- Docker and Docker Compose for running ZooKeeper registry
-- Go 1.23+ for Dubbo-Go examples
-- Java 8+ and Maven for Dubbo Java examples
+Start ZooKeeper:
-## Registry
+```bash
+docker run -d --name zookeeper -p 2181:2181 zookeeper:3.8
+```
Review Comment:
Both README files include instructions to start ZooKeeper in the
"Prerequisites" section using docker, but the PR description states that
ZooKeeper dependency was removed. The Prerequisites sections in both README.md
and README_zh.md should be updated to reflect the direct connection mode that
doesn't require ZooKeeper.
##########
generic/README_zh.md:
##########
@@ -1,88 +1,97 @@
-# 泛化调用
+# 泛化调用示例 (Triple 协议)
-泛化调用是在客户端没有接口信息时保证信息被正确传递的手段,即把 POJO 泛化为通用格式(如字典、字符串),一般被用于集成测试、网关等场景。
+[English](README.md) | [中文](README_zh.md)
-本示例演示了 Dubbo-Go 和 Dubbo Java 服务之间的泛化调用,展示了不同语言实现的服务如何互操作。
+本示例演示了如何使用 Triple 协议进行泛化调用,实现 Go 和 Java 服务之间的互操作。泛化调用允许在没有服务接口定义的情况下调用远程服务。
## 目录结构
-- go-server: Dubbo-Go 服务端示例
-- go-client: Dubbo-Go 客户端示例(泛化调用)
-- java-client: Dubbo Java 客户端示例
-- java-server: Dubbo Java 服务端示例
-- build: 集成测试需要的脚本
+```
+generic/
+├── go-server/ # Go 服务端,监听 :50052
+├── go-client/ # Go 客户端,泛化调用
+├── java-server/ # Java 服务端,监听 :50052
+└── java-client/ # Java 客户端,泛化调用
+```
-Dubbo Java 示例可以用来测试与 Dubbo-Go 的互操作性。您可以启动 java 服务端配合 go 客户端,或者启动 go 服务端配合 java
客户端进行测试。
+## 前置条件
-## 环境准备
+启动 ZooKeeper:
-- Docker 和 Docker Compose 用于运行 ZooKeeper 注册中心
-- Go 1.23+ 用于 Dubbo-Go 示例
-- Java 8+ 和 Maven 用于 Dubbo Java 示例
+```bash
+docker run -d --name zookeeper -p 2181:2181 zookeeper:3.8
+```
Review Comment:
The Chinese README also includes ZooKeeper setup instructions in the
Prerequisites section, which is inconsistent with the direct connection
approach described in the PR. This section should be updated to match the
removal of ZooKeeper dependency.
##########
go.mod:
##########
@@ -176,6 +176,7 @@ require (
)
replace (
+ dubbo.apache.org/dubbo-go/v3 => ../dubbo-go
Review Comment:
The local replace directive points to a relative path '../dubbo-go' which is
a temporary development dependency. This should be removed before merging to
production. The PR description mentions this depends on apache/dubbo-go#3154,
so this replace directive should only be present during development/testing and
removed once that PR is merged.
##########
generic/README.md:
##########
@@ -1,88 +1,97 @@
-# Generic Call
+# Generic Sample (Triple Generic Call)
-Generic call is a mechanism that ensures information is correctly transmitted
when the client does not have interface information. It generalizes POJOs into
generic formats (such as dictionaries, strings), and is generally used in
scenarios like integration testing and gateways.
+[English](README.md) | [中文](README_zh.md)
-This example demonstrates generic calls between Dubbo-Go and Dubbo Java
services, showing how services can interoperate regardless of the language
they're implemented in.
+This sample demonstrates how to use generic invocation with the Triple
protocol for Go-Java interoperability. Generic invocation allows calling remote
services without generating stubs or having the service interface locally.
-## Directory Structure
+## Layout
-- go-server: Dubbo-Go server example
-- go-client: Dubbo-Go client example with generic calls
-- java-client: Dubbo Java client example
-- java-server: Dubbo Java server example
-- build: For integration test
-
-Dubbo Java examples can be used to test interoperability with Dubbo-Go. You
can start java server with go client, or go server with java client for testing.
+```
+generic/
+├── go-server/ # Go provider listening on :50052
+├── go-client/ # Go consumer with generic invocation
+├── java-server/ # Java provider listening on :50052
+└── java-client/ # Java consumer with generic invocation
+```
## Prerequisites
-- Docker and Docker Compose for running ZooKeeper registry
-- Go 1.23+ for Dubbo-Go examples
-- Java 8+ and Maven for Dubbo Java examples
+Start ZooKeeper:
-## Registry
+```bash
+docker run -d --name zookeeper -p 2181:2181 zookeeper:3.8
+```
-This example uses ZooKeeper as the registry. The following command starts
ZooKeeper from docker, so you need to ensure that docker and docker-compose are
installed first.
+## Run the Go Server
-```shell
-# Start ZooKeeper registry
-docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14
+```bash
+cd generic/go-server/cmd
+go run .
```
-## Running the Examples
+The server listens on port `50052` and registers to ZooKeeper.
-### Dubbo-Go Server
+## Run the Go Client
-Using Dubbo-Go as provider, you can start it from command line tool:
-
-```shell
-cd go-server/cmd && go run server.go
+```bash
+cd generic/go-client/cmd
+go run .
```
-### Dubbo-Go Client (Generic Call)
+The client discovers the service via ZooKeeper and uses
`client.WithGenericType("true")` to perform generic calls.
Review Comment:
The README states the Go client "discovers the service via ZooKeeper and
uses `client.WithGenericType("true")`", but looking at the client.go
implementation, it uses direct URLs (DubboServerURL and TripleServerURL) via
client.WithURL(), not service discovery through ZooKeeper. The documentation
should be corrected to reflect the direct connection approach.
```suggestion
The client connects directly to the Dubbo and Triple servers using URLs via
`client.WithURL()` to perform generic calls.
```
##########
generic/go-server/cmd/server.go:
##########
@@ -17,117 +17,58 @@
package main
-import (
- "os"
- "os/signal"
- "syscall"
-)
-
import (
"dubbo.apache.org/dubbo-go/v3"
- "dubbo.apache.org/dubbo-go/v3/common"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
_ "dubbo.apache.org/dubbo-go/v3/imports"
"dubbo.apache.org/dubbo-go/v3/protocol"
"dubbo.apache.org/dubbo-go/v3/registry"
"dubbo.apache.org/dubbo-go/v3/server"
hessian "github.com/apache/dubbo-go-hessian2"
- "github.com/dubbogo/gost/log/logger"
-)
+ "github.com/apache/dubbo-go-samples/generic/go-server/pkg"
-import (
- pkg2 "github.com/apache/dubbo-go-samples/generic/go-server/pkg"
-)
-
-const (
- RegistryAddress = "127.0.0.1:2181"
- ServerName = "generic-server"
- DubboServerPort = 20004
+ "github.com/dubbogo/gost/log/logger"
)
func main() {
- hessian.RegisterPOJO(&pkg2.User{})
-
- ins := createDubboInstance()
-
- srv, err := ins.NewServer()
- if err != nil {
- logger.Fatalf("Failed to create server: %v", err)
- }
+ hessian.RegisterPOJO(&pkg.User{})
- registerService(srv, &pkg2.UserProvider{})
-
- go func() {
- logger.Info("Starting Dubbo Protocol Server...")
- if err := srv.Serve(); err != nil {
- logger.Errorf("Dubbo server failed: %v", err)
- }
- }()
-
- waitForShutdown()
-}
-
-func createDubboInstance() *dubbo.Instance {
ins, err := dubbo.NewInstance(
- dubbo.WithName(ServerName),
+ dubbo.WithName("generic-go-server"),
dubbo.WithRegistry(
registry.WithZookeeper(),
- registry.WithAddress(RegistryAddress),
+ registry.WithAddress("127.0.0.1:2181"),
),
Review Comment:
The Go server uses ZooKeeper registry (registry.WithZookeeper() and address
"127.0.0.1:2181"), but the PR description states that ZooKeeper dependency was
removed in favor of direct connection mode. The Java server in ApiProvider.java
correctly uses direct export with registry address "N/A". The Go server should
be updated to match this approach for consistency.
##########
generic/java-client/src/main/resources/dubbo.properties:
##########
@@ -0,0 +1,4 @@
+dubbo.application.name=generic-java-client
+dubbo.registry.address=zookeeper://127.0.0.1:2181
Review Comment:
The Java client's dubbo.properties file specifies a ZooKeeper registry
address, and the ApiTripleConsumer.java uses registry-based connection.
However, the PR description states ZooKeeper dependency was removed. For
consistency with the stated goals, the Java client should also be updated to
use direct connection mode like the Go client does.
```suggestion
dubbo.registry.address=N/A
```
##########
generic/README_zh.md:
##########
@@ -1,88 +1,97 @@
-# 泛化调用
+# 泛化调用示例 (Triple 协议)
-泛化调用是在客户端没有接口信息时保证信息被正确传递的手段,即把 POJO 泛化为通用格式(如字典、字符串),一般被用于集成测试、网关等场景。
+[English](README.md) | [中文](README_zh.md)
-本示例演示了 Dubbo-Go 和 Dubbo Java 服务之间的泛化调用,展示了不同语言实现的服务如何互操作。
+本示例演示了如何使用 Triple 协议进行泛化调用,实现 Go 和 Java 服务之间的互操作。泛化调用允许在没有服务接口定义的情况下调用远程服务。
## 目录结构
-- go-server: Dubbo-Go 服务端示例
-- go-client: Dubbo-Go 客户端示例(泛化调用)
-- java-client: Dubbo Java 客户端示例
-- java-server: Dubbo Java 服务端示例
-- build: 集成测试需要的脚本
+```
+generic/
+├── go-server/ # Go 服务端,监听 :50052
+├── go-client/ # Go 客户端,泛化调用
+├── java-server/ # Java 服务端,监听 :50052
+└── java-client/ # Java 客户端,泛化调用
+```
-Dubbo Java 示例可以用来测试与 Dubbo-Go 的互操作性。您可以启动 java 服务端配合 go 客户端,或者启动 go 服务端配合 java
客户端进行测试。
+## 前置条件
-## 环境准备
+启动 ZooKeeper:
-- Docker 和 Docker Compose 用于运行 ZooKeeper 注册中心
-- Go 1.23+ 用于 Dubbo-Go 示例
-- Java 8+ 和 Maven 用于 Dubbo Java 示例
+```bash
+docker run -d --name zookeeper -p 2181:2181 zookeeper:3.8
+```
-## 注册中心
+## 启动 Go 服务端
-本示例使用 ZooKeeper 作为注册中心。以下命令通过 docker 启动 ZooKeeper,因此需要确保已安装 docker 和
docker-compose。
+```bash
+cd generic/go-server/cmd
+go run .
+```
-```shell
-# 启动 ZooKeeper 注册中心
-docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14
+服务端监听 `50052` 端口,并注册到 ZooKeeper。
+
+## 启动 Go 客户端
+
+```bash
+cd generic/go-client/cmd
+go run .
```
-## 运行示例
+客户端通过 ZooKeeper 发现服务,使用 `client.WithGenericType("true")` 进行泛化调用。
-### Dubbo-Go 服务端
+## 启动 Java 服务端
-使用 Dubbo-Go 作为服务提供者,可以通过命令行工具启动:
+在 java-server 目录下构建并运行:
-```shell
-cd go-server/cmd && go run server.go
+```bash
+cd generic/java-server
+mvn clean compile exec:java
-Dexec.mainClass="org.apache.dubbo.samples.ApiProvider"
```
-### Dubbo-Go 客户端(泛化调用)
-
-使用 Dubbo-Go 作为服务消费者进行泛化调用:
+## 启动 Java 客户端
-```shell
-cd go-client/cmd && go run client.go
+```bash
+cd generic/java-client
+mvn clean compile exec:java
-Dexec.mainClass="org.apache.dubbo.samples.ApiTripleConsumer"
```
-### Dubbo Java 服务端
+客户端使用 `reference.setGeneric("true")` 进行泛化调用。
-使用 Dubbo Java 作为服务提供者:
+## 测试方法
-```shell
-cd java-server/java-server
-mvn clean package
-sh run.sh
-```
+| 方法 | 参数 | 返回值 |
+|------|------|--------|
+| GetUser1 | String | User |
+| GetUser2 | String, String | User |
+| GetUser3 | int | User |
+| GetUser4 | int, String | User |
+| GetOneUser | - | User |
+| GetUsers | String[] | User[] |
+| GetUsersMap | String[] | Map<String, User> |
+| QueryUser | User | User |
+| QueryUsers | User[] | User[] |
+| QueryAll | - | Map<String, User> |
-### Dubbo Java 客户端
+## 预期输出
-使用 Dubbo Java 作为服务消费者:
+服务端日志:
-```shell
-cd java-client/java-client
-mvn clean package
-sh run.sh
```
+Generic Go/Java server started on port 50052
+Registry: zookeeper://127.0.0.1:2181
+```
+
+客户端日志:
+
+```
+[PASS] GetUser1(String): {id=A003, name=Joe, age=48, ...}
+[PASS] GetUser2(String, String): {id=A003, name=lily, age=48, ...}
+...
+[OK] All tests passed!
+```
+
+## 注意事项
-## 测试互操作性
-
-本示例旨在测试 Dubbo-Go 和 Dubbo Java 之间的互操作性:
-
-1. 启动 ZooKeeper 注册中心
-2. 启动 go-server 或 java-server 之一
-3. 运行 go-client 或 java-client 之一来测试泛化调用
-
-客户端将向服务端发起多种泛化调用,包括:
-- GetUser1(String userId)
-- GetUser2(String userId, String name)
-- GetUser3(int userCode)
-- GetUser4(int userCode, String name)
-- GetOneUser()
-- GetUsers(String[] userIdList)
-- GetUsersMap(String[] userIdList)
-- QueryUser(User user)
-- QueryUsers(List<User> userObjectList)
-- QueryAll()
\ No newline at end of file
+- 不要同时启动 Go 服务端和 Java 服务端,它们都监听 50052 端口。
+- 启动服务端或客户端之前,请确保 ZooKeeper 正在运行。
Review Comment:
The Chinese documentation has the same issue as the English version - it
states "启动服务端或客户端之前,请确保 ZooKeeper 正在运行" (Make sure ZooKeeper is running before
starting the server or client), but this is inconsistent with the removal of
ZooKeeper dependency mentioned in the PR description. The documentation should
be updated to reflect the direct connection approach.
##########
generic/README.md:
##########
@@ -1,88 +1,97 @@
-# Generic Call
+# Generic Sample (Triple Generic Call)
-Generic call is a mechanism that ensures information is correctly transmitted
when the client does not have interface information. It generalizes POJOs into
generic formats (such as dictionaries, strings), and is generally used in
scenarios like integration testing and gateways.
+[English](README.md) | [中文](README_zh.md)
-This example demonstrates generic calls between Dubbo-Go and Dubbo Java
services, showing how services can interoperate regardless of the language
they're implemented in.
+This sample demonstrates how to use generic invocation with the Triple
protocol for Go-Java interoperability. Generic invocation allows calling remote
services without generating stubs or having the service interface locally.
-## Directory Structure
+## Layout
-- go-server: Dubbo-Go server example
-- go-client: Dubbo-Go client example with generic calls
-- java-client: Dubbo Java client example
-- java-server: Dubbo Java server example
-- build: For integration test
-
-Dubbo Java examples can be used to test interoperability with Dubbo-Go. You
can start java server with go client, or go server with java client for testing.
+```
+generic/
+├── go-server/ # Go provider listening on :50052
+├── go-client/ # Go consumer with generic invocation
+├── java-server/ # Java provider listening on :50052
+└── java-client/ # Java consumer with generic invocation
+```
## Prerequisites
-- Docker and Docker Compose for running ZooKeeper registry
-- Go 1.23+ for Dubbo-Go examples
-- Java 8+ and Maven for Dubbo Java examples
+Start ZooKeeper:
-## Registry
+```bash
+docker run -d --name zookeeper -p 2181:2181 zookeeper:3.8
+```
-This example uses ZooKeeper as the registry. The following command starts
ZooKeeper from docker, so you need to ensure that docker and docker-compose are
installed first.
+## Run the Go Server
-```shell
-# Start ZooKeeper registry
-docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14
+```bash
+cd generic/go-server/cmd
+go run .
```
-## Running the Examples
+The server listens on port `50052` and registers to ZooKeeper.
Review Comment:
The README states "The server listens on port `50052` and registers to
ZooKeeper", but this is inconsistent with the PR's goal of removing ZooKeeper
dependency. While the current Go server implementation does use ZooKeeper, the
documentation should clarify the intended architecture or be updated once the
ZooKeeper dependency is fully removed.
##########
generic/go-server/pkg/user_provider.go:
##########
@@ -116,3 +116,37 @@ func (u *UserProvider) Reference() string {
func (u *UserProvider) MethodMapper(_ context.Context) map[string]string {
return map[string]string{}
}
+
+// Invoke handles generic call via $invoke method
+// Parameters: methodName (string), types ([]string), args ([]interface{})
+func (u *UserProvider) Invoke(ctx context.Context, methodName string, types
[]string, args []interface{}) (interface{}, error) {
+ logger.Infof("Generic invoke: method=%s, types=%v, args=%v",
methodName, types, args)
+
+ switch methodName {
+ case "GetUser1":
+ return u.GetUser1(ctx, args[0].(string))
+ case "GetUser2":
+ return u.GetUser2(ctx, args[0].(string), args[1].(string))
+ case "GetUser3":
+ return u.GetUser3(ctx, args[0].(int32))
+ case "GetUser4":
+ return u.GetUser4(ctx, args[0].(int32), args[1].(string))
+ case "GetOneUser":
+ return u.GetOneUser(ctx)
+ case "GetUsers":
+ return u.GetUsers(ctx, args[0].([]string))
+ case "GetUsersMap":
+ return u.GetUsersMap(ctx, args[0].([]string))
+ case "QueryUser":
+ user := args[0].(*User)
+ return u.QueryUser(ctx, user)
+ case "QueryUsers":
+ users := args[0].([]*User)
+ return u.QueryUsers(ctx, users)
+ case "QueryAll":
+ return u.QueryAll(ctx)
+ default:
+ logger.Errorf("Unknown method: %s", methodName)
+ return nil, nil
Review Comment:
The Invoke method returns nil for unknown methods without returning an
error. This makes it difficult to debug issues when calling non-existent
methods. Consider returning an error like `fmt.Errorf("unknown method: %s",
methodName)` instead of returning (nil, nil).
##########
generic/java-server/src/main/resources/dubbo.properties:
##########
@@ -0,0 +1,7 @@
+dubbo.application.name=generic-java-server
+dubbo.registry.address=zookeeper://127.0.0.1:2181
Review Comment:
The dubbo.properties file references a ZooKeeper registry address, but
according to the PR description, ZooKeeper dependency was removed in favor of
direct connection mode. This configuration file appears to be inconsistent with
the new direct connection approach used in ApiProvider.java which sets registry
address to "N/A".
##########
generic/README_zh.md:
##########
@@ -1,88 +1,97 @@
-# 泛化调用
+# 泛化调用示例 (Triple 协议)
-泛化调用是在客户端没有接口信息时保证信息被正确传递的手段,即把 POJO 泛化为通用格式(如字典、字符串),一般被用于集成测试、网关等场景。
+[English](README.md) | [中文](README_zh.md)
-本示例演示了 Dubbo-Go 和 Dubbo Java 服务之间的泛化调用,展示了不同语言实现的服务如何互操作。
+本示例演示了如何使用 Triple 协议进行泛化调用,实现 Go 和 Java 服务之间的互操作。泛化调用允许在没有服务接口定义的情况下调用远程服务。
## 目录结构
-- go-server: Dubbo-Go 服务端示例
-- go-client: Dubbo-Go 客户端示例(泛化调用)
-- java-client: Dubbo Java 客户端示例
-- java-server: Dubbo Java 服务端示例
-- build: 集成测试需要的脚本
+```
+generic/
+├── go-server/ # Go 服务端,监听 :50052
+├── go-client/ # Go 客户端,泛化调用
+├── java-server/ # Java 服务端,监听 :50052
+└── java-client/ # Java 客户端,泛化调用
+```
-Dubbo Java 示例可以用来测试与 Dubbo-Go 的互操作性。您可以启动 java 服务端配合 go 客户端,或者启动 go 服务端配合 java
客户端进行测试。
+## 前置条件
-## 环境准备
+启动 ZooKeeper:
-- Docker 和 Docker Compose 用于运行 ZooKeeper 注册中心
-- Go 1.23+ 用于 Dubbo-Go 示例
-- Java 8+ 和 Maven 用于 Dubbo Java 示例
+```bash
+docker run -d --name zookeeper -p 2181:2181 zookeeper:3.8
+```
-## 注册中心
+## 启动 Go 服务端
-本示例使用 ZooKeeper 作为注册中心。以下命令通过 docker 启动 ZooKeeper,因此需要确保已安装 docker 和
docker-compose。
+```bash
+cd generic/go-server/cmd
+go run .
+```
-```shell
-# 启动 ZooKeeper 注册中心
-docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14
+服务端监听 `50052` 端口,并注册到 ZooKeeper。
+
+## 启动 Go 客户端
+
+```bash
+cd generic/go-client/cmd
+go run .
```
-## 运行示例
+客户端通过 ZooKeeper 发现服务,使用 `client.WithGenericType("true")` 进行泛化调用。
Review Comment:
The Chinese README states "客户端通过 ZooKeeper 发现服务" (client discovers service
through ZooKeeper), but the client.go implementation uses direct URLs via
client.WithURL() rather than ZooKeeper-based service discovery. The
documentation should be updated to reflect the actual implementation.
```suggestion
客户端通过直连服务地址(例如使用 `client.WithURL("tri://127.0.0.1:50052")`)调用服务,并使用
`client.WithGenericType("true")` 进行泛化调用。
```
##########
generic/go-client/cmd/client_test.go:
##########
@@ -0,0 +1,591 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+ "context"
+ "testing"
+ "time"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3"
+ "dubbo.apache.org/dubbo-go/v3/client"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/config/generic"
+ _ "dubbo.apache.org/dubbo-go/v3/imports"
+
+ hessian "github.com/apache/dubbo-go-hessian2"
+
+ "github.com/apache/dubbo-go-samples/generic/go-client/pkg"
+)
+
+func init() {
+ hessian.RegisterPOJO(&pkg.User{})
+}
+
+// setupDubboGenericService creates a GenericService using Dubbo protocol
+func setupDubboGenericService(t *testing.T) *generic.GenericService {
+ ins, err := dubbo.NewInstance(
+ dubbo.WithName("generic-test-dubbo"),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create dubbo instance: %v", err)
+ }
+
+ cli, err := ins.NewClient(
+ client.WithClientProtocolDubbo(),
+ client.WithClientSerialization(constant.Hessian2Serialization),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create client: %v", err)
+ }
+
+ svc, err := cli.NewGenericService(
+ "org.apache.dubbo.samples.UserProvider",
+ client.WithURL("dubbo://127.0.0.1:20000"),
+ client.WithVersion("1.0.0"),
+ client.WithGroup("dubbo"),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create generic service: %v", err)
+ }
+
+ return svc
+}
+
+// setupTripleGenericService creates a GenericService using Triple protocol
+func setupTripleGenericService(t *testing.T) *generic.GenericService {
+ ins, err := dubbo.NewInstance(
+ dubbo.WithName("generic-test-triple"),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create dubbo instance: %v", err)
+ }
+
+ cli, err := ins.NewClient(
+ client.WithClientProtocolTriple(),
+ client.WithClientSerialization(constant.Hessian2Serialization),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create client: %v", err)
+ }
+
+ svc, err := cli.NewGenericService(
+ "org.apache.dubbo.samples.UserProvider",
+ client.WithURL("tri://127.0.0.1:50052"),
+ client.WithVersion("1.0.0"),
+ client.WithGroup("triple"),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create generic service: %v", err)
+ }
+
+ return svc
+}
+
+//
=============================================================================
+// Dubbo Protocol Tests
+//
=============================================================================
+
+func TestDubbo_GenericCall_StringArg(t *testing.T) {
Review Comment:
Test function name uses underscore separator
"TestDubbo_GenericCall_StringArg" instead of the more common Go convention of
using camel case like "TestDubboGenericCallStringArg". While this still works,
it's inconsistent with typical Go naming conventions. Consider using camel case
for consistency with Go best practices.
```suggestion
func TestDubboGenericCallStringArg(t *testing.T) {
```
##########
generic/go-client/cmd/client_test.go:
##########
@@ -0,0 +1,591 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+ "context"
+ "testing"
+ "time"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3"
+ "dubbo.apache.org/dubbo-go/v3/client"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/config/generic"
+ _ "dubbo.apache.org/dubbo-go/v3/imports"
+
+ hessian "github.com/apache/dubbo-go-hessian2"
+
+ "github.com/apache/dubbo-go-samples/generic/go-client/pkg"
+)
+
+func init() {
+ hessian.RegisterPOJO(&pkg.User{})
+}
+
+// setupDubboGenericService creates a GenericService using Dubbo protocol
+func setupDubboGenericService(t *testing.T) *generic.GenericService {
+ ins, err := dubbo.NewInstance(
+ dubbo.WithName("generic-test-dubbo"),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create dubbo instance: %v", err)
+ }
+
+ cli, err := ins.NewClient(
+ client.WithClientProtocolDubbo(),
+ client.WithClientSerialization(constant.Hessian2Serialization),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create client: %v", err)
+ }
+
+ svc, err := cli.NewGenericService(
+ "org.apache.dubbo.samples.UserProvider",
+ client.WithURL("dubbo://127.0.0.1:20000"),
+ client.WithVersion("1.0.0"),
+ client.WithGroup("dubbo"),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create generic service: %v", err)
+ }
+
+ return svc
+}
+
+// setupTripleGenericService creates a GenericService using Triple protocol
+func setupTripleGenericService(t *testing.T) *generic.GenericService {
+ ins, err := dubbo.NewInstance(
+ dubbo.WithName("generic-test-triple"),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create dubbo instance: %v", err)
+ }
+
+ cli, err := ins.NewClient(
+ client.WithClientProtocolTriple(),
+ client.WithClientSerialization(constant.Hessian2Serialization),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create client: %v", err)
+ }
+
+ svc, err := cli.NewGenericService(
+ "org.apache.dubbo.samples.UserProvider",
+ client.WithURL("tri://127.0.0.1:50052"),
+ client.WithVersion("1.0.0"),
+ client.WithGroup("triple"),
+ )
+ if err != nil {
+ t.Fatalf("Failed to create generic service: %v", err)
+ }
+
+ return svc
+}
+
+//
=============================================================================
+// Dubbo Protocol Tests
+//
=============================================================================
+
+func TestDubbo_GenericCall_StringArg(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupDubboGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetUser1",
[]string{"java.lang.String"}, []hessian.Object{"A001"})
+ if err != nil {
+ t.Fatalf("GetUser1 failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["id"] != "A001" {
+ t.Errorf("Expected id=A001, got %v", resultMap["id"])
+ }
+}
+
+func TestDubbo_GenericCall_MultipleArgs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupDubboGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetUser2",
[]string{"java.lang.String", "java.lang.String"}, []hessian.Object{"A002",
"CustomName"})
+ if err != nil {
+ t.Fatalf("GetUser2 failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["name"] != "CustomName" {
+ t.Errorf("Expected name=CustomName, got %v", resultMap["name"])
+ }
+}
+
+func TestDubbo_GenericCall_IntArg(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupDubboGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetUser3",
[]string{"int"}, []hessian.Object{int32(1)})
+ if err != nil {
+ t.Fatalf("GetUser3 failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["id"] != "1" {
+ t.Errorf("Expected id=1, got %v", resultMap["id"])
+ }
+}
+
+func TestDubbo_GenericCall_NoArgs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupDubboGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetOneUser",
[]string{}, []hessian.Object{})
+ if err != nil {
+ t.Fatalf("GetOneUser failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["id"] == nil {
+ t.Error("Expected non-nil id")
+ }
+}
+
+func TestDubbo_GenericCall_ArrayArg(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupDubboGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetUsers",
[]string{"[Ljava.lang.String;"}, []hessian.Object{[]string{"001", "002",
"003"}})
+ if err != nil {
+ t.Fatalf("GetUsers failed: %v", err)
+ }
+
+ resultList, ok := result.([]interface{})
+ if !ok {
+ t.Fatalf("Expected list result, got %T", result)
+ }
+
+ if len(resultList) != 3 {
+ t.Errorf("Expected 3 users, got %d", len(resultList))
+ }
+}
+
+func TestDubbo_GenericCall_POJOArg(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupDubboGenericService(t)
+
+ user := &pkg.User{
+ ID: "test001",
+ Name: "TestUser",
+ Age: 30,
+ Time: time.Now(),
+ }
+
+ result, err := svc.Invoke(context.Background(), "QueryUser",
[]string{"org.apache.dubbo.samples.User"}, []hessian.Object{user})
+ if err != nil {
+ t.Fatalf("QueryUser failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["name"] != "TestUser" {
+ t.Errorf("Expected name=TestUser, got %v", resultMap["name"])
+ }
+}
+
+//
=============================================================================
+// Triple Protocol Tests
+//
=============================================================================
+
+func TestTriple_GenericCall_StringArg(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupTripleGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetUser1",
[]string{"java.lang.String"}, []hessian.Object{"A001"})
+ if err != nil {
+ t.Fatalf("GetUser1 failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["id"] != "A001" {
+ t.Errorf("Expected id=A001, got %v", resultMap["id"])
+ }
+}
+
+func TestTriple_GenericCall_MultipleArgs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupTripleGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetUser2",
[]string{"java.lang.String", "java.lang.String"}, []hessian.Object{"A002",
"CustomName"})
+ if err != nil {
+ t.Fatalf("GetUser2 failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["name"] != "CustomName" {
+ t.Errorf("Expected name=CustomName, got %v", resultMap["name"])
+ }
+}
+
+func TestTriple_GenericCall_IntArg(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupTripleGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetUser3",
[]string{"int"}, []hessian.Object{int32(1)})
+ if err != nil {
+ t.Fatalf("GetUser3 failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["id"] != "1" {
+ t.Errorf("Expected id=1, got %v", resultMap["id"])
+ }
+}
+
+func TestTriple_GenericCall_NoArgs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupTripleGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetOneUser",
[]string{}, []hessian.Object{})
+ if err != nil {
+ t.Fatalf("GetOneUser failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["id"] == nil {
+ t.Error("Expected non-nil id")
+ }
+}
+
+func TestTriple_GenericCall_ArrayArg(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupTripleGenericService(t)
+
+ result, err := svc.Invoke(context.Background(), "GetUsers",
[]string{"[Ljava.lang.String;"}, []hessian.Object{[]string{"001", "002",
"003"}})
+ if err != nil {
+ t.Fatalf("GetUsers failed: %v", err)
+ }
+
+ resultList, ok := result.([]interface{})
+ if !ok {
+ t.Fatalf("Expected list result, got %T", result)
+ }
+
+ if len(resultList) != 3 {
+ t.Errorf("Expected 3 users, got %d", len(resultList))
+ }
+}
+
+func TestTriple_GenericCall_POJOArg(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupTripleGenericService(t)
+
+ user := &pkg.User{
+ ID: "test001",
+ Name: "TestUser",
+ Age: 30,
+ Time: time.Now(),
+ }
+
+ result, err := svc.Invoke(context.Background(), "QueryUser",
[]string{"org.apache.dubbo.samples.User"}, []hessian.Object{user})
+ if err != nil {
+ t.Fatalf("QueryUser failed: %v", err)
+ }
+
+ resultMap, ok := result.(map[interface{}]interface{})
+ if !ok {
+ t.Fatalf("Expected map result, got %T", result)
+ }
+
+ if resultMap["name"] != "TestUser" {
+ t.Errorf("Expected name=TestUser, got %v", resultMap["name"])
+ }
+}
+
+func TestTriple_GenericCall_POJOArrayArg(t *testing.T) {
+ if testing.Short() {
+ t.Skip("Skipping integration test in short mode")
+ }
+
+ svc := setupTripleGenericService(t)
+
+ users := []hessian.Object{
+ &pkg.User{ID: "001", Name: "User1", Age: 20, Time: time.Now()},
+ &pkg.User{ID: "002", Name: "User2", Age: 25, Time: time.Now()},
+ &pkg.User{ID: "003", Name: "User3", Age: 30, Time: time.Now()},
+ }
+
+ result, err := svc.Invoke(context.Background(), "QueryUsers",
[]string{"java.util.List"}, []hessian.Object{users})
Review Comment:
The test uses "java.util.List" as the parameter type for QueryUsers, but the
actual Java method signature expects User[] (an array, not a List). This type
mismatch will likely cause the generic call to fail. The parameter type should
be "[Lorg.apache.dubbo.samples.User;" to match the array signature.
```suggestion
result, err := svc.Invoke(context.Background(), "QueryUsers",
[]string{"[Lorg.apache.dubbo.samples.User;"}, []hessian.Object{users})
```
##########
generic/README_zh.md:
##########
@@ -1,88 +1,97 @@
-# 泛化调用
+# 泛化调用示例 (Triple 协议)
-泛化调用是在客户端没有接口信息时保证信息被正确传递的手段,即把 POJO 泛化为通用格式(如字典、字符串),一般被用于集成测试、网关等场景。
+[English](README.md) | [中文](README_zh.md)
-本示例演示了 Dubbo-Go 和 Dubbo Java 服务之间的泛化调用,展示了不同语言实现的服务如何互操作。
+本示例演示了如何使用 Triple 协议进行泛化调用,实现 Go 和 Java 服务之间的互操作。泛化调用允许在没有服务接口定义的情况下调用远程服务。
## 目录结构
-- go-server: Dubbo-Go 服务端示例
-- go-client: Dubbo-Go 客户端示例(泛化调用)
-- java-client: Dubbo Java 客户端示例
-- java-server: Dubbo Java 服务端示例
-- build: 集成测试需要的脚本
+```
+generic/
+├── go-server/ # Go 服务端,监听 :50052
+├── go-client/ # Go 客户端,泛化调用
+├── java-server/ # Java 服务端,监听 :50052
+└── java-client/ # Java 客户端,泛化调用
+```
-Dubbo Java 示例可以用来测试与 Dubbo-Go 的互操作性。您可以启动 java 服务端配合 go 客户端,或者启动 go 服务端配合 java
客户端进行测试。
+## 前置条件
-## 环境准备
+启动 ZooKeeper:
-- Docker 和 Docker Compose 用于运行 ZooKeeper 注册中心
-- Go 1.23+ 用于 Dubbo-Go 示例
-- Java 8+ 和 Maven 用于 Dubbo Java 示例
+```bash
+docker run -d --name zookeeper -p 2181:2181 zookeeper:3.8
+```
-## 注册中心
+## 启动 Go 服务端
-本示例使用 ZooKeeper 作为注册中心。以下命令通过 docker 启动 ZooKeeper,因此需要确保已安装 docker 和
docker-compose。
+```bash
+cd generic/go-server/cmd
+go run .
+```
-```shell
-# 启动 ZooKeeper 注册中心
-docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14
+服务端监听 `50052` 端口,并注册到 ZooKeeper。
Review Comment:
The Chinese README states the Go server "并注册到 ZooKeeper" (registers to
ZooKeeper), but the PR description indicates ZooKeeper dependency was removed.
While the current Go server implementation does still use ZooKeeper, according
to the PR goals this should be changed to direct connection mode for
consistency.
##########
generic/README.md:
##########
@@ -1,88 +1,97 @@
-# Generic Call
+# Generic Sample (Triple Generic Call)
-Generic call is a mechanism that ensures information is correctly transmitted
when the client does not have interface information. It generalizes POJOs into
generic formats (such as dictionaries, strings), and is generally used in
scenarios like integration testing and gateways.
+[English](README.md) | [中文](README_zh.md)
-This example demonstrates generic calls between Dubbo-Go and Dubbo Java
services, showing how services can interoperate regardless of the language
they're implemented in.
+This sample demonstrates how to use generic invocation with the Triple
protocol for Go-Java interoperability. Generic invocation allows calling remote
services without generating stubs or having the service interface locally.
-## Directory Structure
+## Layout
-- go-server: Dubbo-Go server example
-- go-client: Dubbo-Go client example with generic calls
-- java-client: Dubbo Java client example
-- java-server: Dubbo Java server example
-- build: For integration test
-
-Dubbo Java examples can be used to test interoperability with Dubbo-Go. You
can start java server with go client, or go server with java client for testing.
+```
+generic/
+├── go-server/ # Go provider listening on :50052
+├── go-client/ # Go consumer with generic invocation
+├── java-server/ # Java provider listening on :50052
+└── java-client/ # Java consumer with generic invocation
+```
## Prerequisites
-- Docker and Docker Compose for running ZooKeeper registry
-- Go 1.23+ for Dubbo-Go examples
-- Java 8+ and Maven for Dubbo Java examples
+Start ZooKeeper:
-## Registry
+```bash
+docker run -d --name zookeeper -p 2181:2181 zookeeper:3.8
+```
-This example uses ZooKeeper as the registry. The following command starts
ZooKeeper from docker, so you need to ensure that docker and docker-compose are
installed first.
+## Run the Go Server
-```shell
-# Start ZooKeeper registry
-docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14
+```bash
+cd generic/go-server/cmd
+go run .
```
-## Running the Examples
+The server listens on port `50052` and registers to ZooKeeper.
-### Dubbo-Go Server
+## Run the Go Client
-Using Dubbo-Go as provider, you can start it from command line tool:
-
-```shell
-cd go-server/cmd && go run server.go
+```bash
+cd generic/go-client/cmd
+go run .
```
-### Dubbo-Go Client (Generic Call)
+The client discovers the service via ZooKeeper and uses
`client.WithGenericType("true")` to perform generic calls.
-Using Dubbo-Go as consumer with generic calls:
+## Run the Java Server
-```shell
-cd go-client/cmd && go run client.go
-```
+Build and run from the java-server directory:
-### Dubbo Java Server
+```bash
+cd generic/java-server
+mvn clean compile exec:java
-Dexec.mainClass="org.apache.dubbo.samples.ApiProvider"
+```
-Using Dubbo Java as provider:
+## Run the Java Client
-```shell
-cd java-server/java-server
-mvn clean package
-sh run.sh
+```bash
+cd generic/java-client
+mvn clean compile exec:java
-Dexec.mainClass="org.apache.dubbo.samples.ApiTripleConsumer"
```
-### Dubbo Java Client
+The client uses `reference.setGeneric("true")` to perform generic calls.
+
+## Tested Methods
-Using Dubbo Java as consumer:
+| Method | Parameters | Return |
+|--------|------------|--------|
+| GetUser1 | String | User |
+| GetUser2 | String, String | User |
+| GetUser3 | int | User |
+| GetUser4 | int, String | User |
+| GetOneUser | - | User |
+| GetUsers | String[] | User[] |
+| GetUsersMap | String[] | Map<String, User> |
+| QueryUser | User | User |
+| QueryUsers | User[] | User[] |
+| QueryAll | - | Map<String, User> |
+
+## Expected Output
+
+Server log:
+
+```
+Generic Go/Java server started on port 50052
+Registry: zookeeper://127.0.0.1:2181
+```
+
+Client log:
-```shell
-cd java-client/java-client
-mvn clean package
-sh run.sh
```
+[PASS] GetUser1(String): {id=A003, name=Joe, age=48, ...}
+[PASS] GetUser2(String, String): {id=A003, name=lily, age=48, ...}
+...
+[OK] All tests passed!
+```
+
+## Notes
-## Testing Interoperability
-
-This example is designed to test interoperability between Dubbo-Go and Dubbo
Java:
-
-1. Start the ZooKeeper registry
-2. Start either go-server or java-server
-3. Run either go-client or java-client to test the generic calls
-
-The client will make various generic calls to the server, including:
-- GetUser1(String userId)
-- GetUser2(String userId, String name)
-- GetUser3(int userCode)
-- GetUser4(int userCode, String name)
-- GetOneUser()
-- GetUsers(String[] userIdList)
-- GetUsersMap(String[] userIdList)
-- QueryUser(User user)
-- QueryUsers(List<User> userObjectList)
-- QueryAll()
\ No newline at end of file
+- Do NOT start Go Server and Java Server at the same time. Both listen on port
50052.
+- Make sure ZooKeeper is running before starting the server or client.
Review Comment:
The README.md states "Make sure ZooKeeper is running before starting the
server or client," but the PR description indicates ZooKeeper dependency was
removed in favor of direct connection mode. The updated Java server uses direct
export (registry address "N/A"). This documentation is inconsistent with the
implementation changes and should be updated.
##########
generic/README.md:
##########
@@ -1,88 +1,97 @@
-# Generic Call
+# Generic Sample (Triple Generic Call)
-Generic call is a mechanism that ensures information is correctly transmitted
when the client does not have interface information. It generalizes POJOs into
generic formats (such as dictionaries, strings), and is generally used in
scenarios like integration testing and gateways.
+[English](README.md) | [中文](README_zh.md)
-This example demonstrates generic calls between Dubbo-Go and Dubbo Java
services, showing how services can interoperate regardless of the language
they're implemented in.
+This sample demonstrates how to use generic invocation with the Triple
protocol for Go-Java interoperability. Generic invocation allows calling remote
services without generating stubs or having the service interface locally.
-## Directory Structure
+## Layout
-- go-server: Dubbo-Go server example
-- go-client: Dubbo-Go client example with generic calls
-- java-client: Dubbo Java client example
-- java-server: Dubbo Java server example
-- build: For integration test
-
-Dubbo Java examples can be used to test interoperability with Dubbo-Go. You
can start java server with go client, or go server with java client for testing.
+```
+generic/
+├── go-server/ # Go provider listening on :50052
+├── go-client/ # Go consumer with generic invocation
+├── java-server/ # Java provider listening on :50052
+└── java-client/ # Java consumer with generic invocation
+```
## Prerequisites
-- Docker and Docker Compose for running ZooKeeper registry
-- Go 1.23+ for Dubbo-Go examples
-- Java 8+ and Maven for Dubbo Java examples
+Start ZooKeeper:
-## Registry
+```bash
+docker run -d --name zookeeper -p 2181:2181 zookeeper:3.8
+```
-This example uses ZooKeeper as the registry. The following command starts
ZooKeeper from docker, so you need to ensure that docker and docker-compose are
installed first.
+## Run the Go Server
-```shell
-# Start ZooKeeper registry
-docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14
+```bash
+cd generic/go-server/cmd
+go run .
```
-## Running the Examples
+The server listens on port `50052` and registers to ZooKeeper.
-### Dubbo-Go Server
+## Run the Go Client
-Using Dubbo-Go as provider, you can start it from command line tool:
-
-```shell
-cd go-server/cmd && go run server.go
+```bash
+cd generic/go-client/cmd
+go run .
```
-### Dubbo-Go Client (Generic Call)
+The client discovers the service via ZooKeeper and uses
`client.WithGenericType("true")` to perform generic calls.
-Using Dubbo-Go as consumer with generic calls:
+## Run the Java Server
-```shell
-cd go-client/cmd && go run client.go
-```
+Build and run from the java-server directory:
-### Dubbo Java Server
+```bash
+cd generic/java-server
+mvn clean compile exec:java
-Dexec.mainClass="org.apache.dubbo.samples.ApiProvider"
+```
-Using Dubbo Java as provider:
+## Run the Java Client
-```shell
-cd java-server/java-server
-mvn clean package
-sh run.sh
+```bash
+cd generic/java-client
+mvn clean compile exec:java
-Dexec.mainClass="org.apache.dubbo.samples.ApiTripleConsumer"
```
-### Dubbo Java Client
+The client uses `reference.setGeneric("true")` to perform generic calls.
+
+## Tested Methods
-Using Dubbo Java as consumer:
+| Method | Parameters | Return |
+|--------|------------|--------|
+| GetUser1 | String | User |
+| GetUser2 | String, String | User |
+| GetUser3 | int | User |
+| GetUser4 | int, String | User |
+| GetOneUser | - | User |
+| GetUsers | String[] | User[] |
+| GetUsersMap | String[] | Map<String, User> |
+| QueryUser | User | User |
+| QueryUsers | User[] | User[] |
+| QueryAll | - | Map<String, User> |
+
+## Expected Output
+
+Server log:
+
+```
+Generic Go/Java server started on port 50052
+Registry: zookeeper://127.0.0.1:2181
+```
+
+Client log:
-```shell
-cd java-client/java-client
-mvn clean package
-sh run.sh
```
+[PASS] GetUser1(String): {id=A003, name=Joe, age=48, ...}
+[PASS] GetUser2(String, String): {id=A003, name=lily, age=48, ...}
+...
+[OK] All tests passed!
+```
+
+## Notes
-## Testing Interoperability
-
-This example is designed to test interoperability between Dubbo-Go and Dubbo
Java:
-
-1. Start the ZooKeeper registry
-2. Start either go-server or java-server
-3. Run either go-client or java-client to test the generic calls
-
-The client will make various generic calls to the server, including:
-- GetUser1(String userId)
-- GetUser2(String userId, String name)
-- GetUser3(int userCode)
-- GetUser4(int userCode, String name)
-- GetOneUser()
-- GetUsers(String[] userIdList)
-- GetUsersMap(String[] userIdList)
-- QueryUser(User user)
-- QueryUsers(List<User> userObjectList)
-- QueryAll()
\ No newline at end of file
+- Do NOT start Go Server and Java Server at the same time. Both listen on port
50052.
Review Comment:
The README states "Do NOT start Go Server and Java Server at the same time.
Both listen on port 50052." However, according to the ApiProvider.java code,
the Java server uses Dubbo protocol on port 20000 and Triple protocol on port
50052, while the Go server only uses port 50052. The documentation should
clarify that the conflict is specifically for the Triple protocol port.
```suggestion
- Do NOT start the Go Server and the Java Server's Triple protocol endpoint
on the same host at the same time, because both use port 50052 for Triple.
```
--
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]