Pre-check
- [x] I am sure that all the content I provide is in English.
Search before asking
- [x] I had searched in the issues and found no similar issues.
Apache Dubbo Component
Java SDK (apache/dubbo)
Dubbo Version
Dubbo 3.3.4、 jdk 17
Steps to reproduce this issue
- use dubbo-sample-master use dubbo-samples-triple-grpc, the old protobuf file is follow:
syntax = "proto3";
option java_multiple_files = true;
package org.apache.dubbo.samples.tri.grpc;
message GreeterRequest {
string name = 1;
}
message GreeterReply {
string message = 1;
}
service Greeter{
// key, the first letter is lowercase
rpc greet(GreeterRequest) returns (GreeterReply);
rpc biStream(stream GreeterRequest) returns (stream GreeterReply);
rpc serverStream(GreeterRequest) returns (stream GreeterReply);
}
- update protobuf file
syntax = "proto3";
option java_multiple_files = true;
package org.apache.dubbo.samples.tri.grpc;
message GreeterRequest {
string name = 1;
}
message GreeterReply {
string message = 1;
}
service Greeter{
// key, Convert the first letter to uppercase
rpc Greet(GreeterRequest) returns (GreeterReply);
rpc biStream(stream GreeterRequest) returns (stream GreeterReply);
rpc serverStream(GreeterRequest) returns (stream GreeterReply);
}
-
compile and run
-
Requests starting with uppercase or lowercase letters, call on http The first http request detail (rpc method name is uppercase):
POST localhost:50053/org.apache.dubbo.samples.tri.grpc.Greeter/greet
Content-Type: application/json
{
"name": "John"
}
Error details:
21:11:04.136 |-INFO [NettyServerWorker-5-1] ing.transport.netty4.NettyChannelHandler:56 -| [DUBBO] The connection [id: 0xade552f6, L:/127.0.0.1:50053 - R:/127.0.0.1:65057] of 127.0.0.1:65057 -> 127.0.0.1:50053 is established., dubbo version: 3.3.4, current host: 172.16.210.28
21:11:04.165 |-INFO [NettyServerWorker-5-1] .tri.h12.AbstractServerTransportListener:252 -| [DUBBO] An error occurred while processing the http request with DefaultHttp11ServerTransportListener, Http1Request{method='POST', path='/org.apache.dubbo.samples.tri.grpc.Greeter/greet', contentType='application/json'}, dubbo version: 3.3.4, current host: 172.16.210.28
org.apache.dubbo.remoting.http12.exception.HttpStatusException: Invoker not found
at org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener.doRoute(AbstractServerTransportListener.java:124) ~[dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener.onBeforeMetadata(AbstractServerTransportListener.java:118) [dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener.onMetadata(AbstractServerTransportListener.java:85) [dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener.onMetadata(AbstractServerTransportListener.java:54) [dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1ConnectionHandler.channelRead0(NettyHttp1ConnectionHandler.java:56) [dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1ConnectionHandler.channelRead0(NettyHttp1ConnectionHandler.java:29) [dubbo-3.3.4.jar:3.3.4]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1Codec.channelRead(NettyHttp1Codec.java:55) [dubbo-3.3.4.jar:3.3.4]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:107) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:107) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.handlerRemoved(ByteToMessageDecoder.java:266) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:537) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:796) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:732) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:658) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998) [netty-common-4.1.118.Final.jar:4.1.118.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.118.Final.jar:4.1.118.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-common-4.1.118.Final.jar:4.1.118.Final]
at java.lang.Thread.run(Thread.java:840) [?:?]
The second http request detail (rpc method name first letter is uppercase):
# change service method name 'greet' to 'Greet'
POST localhost:50053/org.apache.dubbo.samples.tri.grpc.Greeter/Greet
Content-Type: application/json
{
"name": "John"
}
Error detials:
21:16:20.396 |-INFO [NettyServerWorker-5-2] ing.transport.netty4.NettyChannelHandler:56 -| [DUBBO] The connection [id: 0x5bbfa53a, L:/127.0.0.1:50053 - R:/127.0.0.1:52065] of 127.0.0.1:52065 -> 127.0.0.1:50053 is established., dubbo version: 3.3.4, current host: 172.16.210.28
21:16:20.398 |-INFO [NettyServerWorker-5-2] .tri.h12.AbstractServerTransportListener:252 -| [DUBBO] An error occurred while processing the http request with DefaultHttp11ServerTransportListener, Http1Request{method='POST', path='/org.apache.dubbo.samples.tri.grpc.Greeter/Greet', contentType='application/json'}, dubbo version: 3.3.4, current host: 172.16.210.28
org.apache.dubbo.remoting.http12.exception.HttpStatusException: Invoker not found
at org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener.doRoute(AbstractServerTransportListener.java:124) ~[dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener.onBeforeMetadata(AbstractServerTransportListener.java:118) [dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener.onMetadata(AbstractServerTransportListener.java:85) [dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener.onMetadata(AbstractServerTransportListener.java:54) [dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1ConnectionHandler.channelRead0(NettyHttp1ConnectionHandler.java:56) [dubbo-3.3.4.jar:3.3.4]
at org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1ConnectionHandler.channelRead0(NettyHttp1ConnectionHandler.java:29) [dubbo-3.3.4.jar:3.3.4]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1Codec.channelRead(NettyHttp1Codec.java:55) [dubbo-3.3.4.jar:3.3.4]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:107) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:107) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.handlerRemoved(ByteToMessageDecoder.java:266) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:537) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290) [netty-codec-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:796) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:732) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:658) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) [netty-transport-4.1.118.Final.jar:4.1.118.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998) [netty-common-4.1.118.Final.jar:4.1.118.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.118.Final.jar:4.1.118.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-common-4.1.118.Final.jar:4.1.118.Final]
at java.lang.Thread.run(Thread.java:840) [?:?]
What you expected to happen
Call 'localhost: 50053/org.apache.dubbo.samples.tri.grpc.Greeter/Greet' Or 'localhost: 50053/org.apache.dubbo.samples.tri.grpc.Greeter/greet' via HTTP succeeded, do not all fail
Anything else
General proto file specifications, The first character of the RPC method name is capitalized, and we have a large number of proto files with history that use RPC method names starting with uppercase characters
Are you willing to submit a pull request to fix on your own?
- [x] Yes I am willing to submit a pull request on my own!
Code of Conduct
- [x] I agree to follow this project's Code of Conduct
Comment From: zrlw
service Greeter{
// key, Convert the first letter to uppercase
rpc Greet(GreeterRequest) returns (GreeterReply);
rpc biStream(stream GreeterRequest) returns (stream GreeterReply);
rpc serverStream(GreeterRequest) returns (stream GreeterReply);
}
methods name biStream
and serverStream
do not comply with protobuf regulation: service names and method names should use TitleCase. see details at https://protobuf.dev/programming-guides/style
Comment From: zrlw
you might refer to this proto: https://github.com/apache/dubbo/blob/3.3/dubbo-rpc/dubbo-rpc-triple/src/main/proto/health.proto
service Health {
...
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
...
rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
Comment From: zrlw
i tested on current dubbo 3.3 branch and didn't find the issue. here is my operations: 1. modify pom.xml of dubbo-demo-spring-boot-idl, (1) add dependencies
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.25.6</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-api</artifactId>
<version>1.63.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.63.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.63.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.83</version>
</dependency>
(2) add plugins, set os.detected.classifier to windows-x86_64 since i test it on windows.
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.25.6:exe:windows-x86_64
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.63.0:exe:windows-x86_64
</pluginArtifact>
<protocPlugins>
<protocPlugin>
<id>dubbo</id>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-compiler</artifactId>
<version>${project.version}</version>
<mainClass>org.apache.dubbo.gen.tri.Dubbo3TripleGenerator</mainClass>
</protocPlugin>
</protocPlugins>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
<goal>compile-custom</goal>
<goal>test-compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
- modify service methods name of dubbo-demo-spring-boot-idl-provider#helloworld.proto
service GreeterService {
// Sends a greeting.
rpc SayHello(HelloRequest) returns (HelloReply);
rpc biStream(stream HelloRequest) returns (stream HelloReply);
rpc serverStream(HelloRequest) returns (stream HelloReply);
}
- modify application.yml of dubbo-demo-spring-boot-idl-provider (1) change tri port from -1 to 50053,
protocol:
name: tri
port: 50053
(2) add management and server port configurations,
management:
endpoints:
web:
exposure:
include: mappings
server:
port: 8081
- run
mvn compile
of dubbo-demo-spring-boot-idl-provider - add missing implements to dubbo-demo-spring-boot-idl-provider#GreeterServiceImpl
@Override
public void serverStream(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
// do nothing just for test.
}
@Override
public StreamObserver<HelloRequest> biStream(StreamObserver<HelloReply> responseObserver) {
// for test.
return null;
}
- start dubbo-demo-spring-boot-idl-provider#ProviderApplication
- test http post request by postman
Comment From: lqscript
@zrlw I also encountered this issue.
I found that this problem does not occur if the service class directly implements the service interface (e.g., implements GreeterService
) in dubbo-demo.
However, if the service extends the stub base class (e.g., DubboGreeterServiceTriple.GreeterServiceImplBase
), which is the method described in the official documentation for Dubbo Triple services, it returns a 404 error whenever a lowerCamelCase method or an UpperCamelCase method is called.
After debugging the source code, I found that the root cause is related to how Dubbo registers HTTP routes for Triple services.
When a service extends the generated base class, Dubbo uses a StubServiceDescriptor
.
org/apache/dubbo/config/ServiceConfig.java:565
This descriptor stores method names using the original names from the .proto file, which are typically UpperCamelCase (e.g., SayHello
).
However, the actual method generated in the Java base class follows Java conventions and is lowerCamelCase (e.g., sayHello
).
When DefaultRequestMappingRegistry
attempts to create HTTP mappings, it reflects on the service implementation and uses the method name (lowerCamelCase) to look up its corresponding ServiceDescriptor
.
This lookup fails because the registry is searching for a descriptor by its lowerCamelCase name, but the descriptor is keyed by the UpperCamelCase name.
As a result, no HTTP mapping is registered for the method, causing all HTTP-based invocations to fail with a 404 error.
Comment From: zrlw
This descriptor stores method names using the original names from the .proto file, which are typically UpperCamelCase (e.g., SayHello).
pls submit a new issue and pr?
Comment From: lqscript
I create a new issue #15484
Comment From: oxsean
@paxxie2 Already working on it.
Comment From: fantiq
HI @paxxie2 @oxsean i noticed this issue hasn't been update in a while, is it still in progress? or would some help be needed?
Comment From: zrlw
@paxxie2 Already working on it.
Since @paxxie2 has not responded for a while, anybody willing to continue fixing this issue based on https://github.com/oxsean/dubbo/commit/da8fd19c2c041326f9d35c47b2448e37b35ca716 is appreciated.
Comment From: fantiq
Hi @zrlw . I'd like to continue developing this issue, can u assign it to me?
Comment From: fantiq
Cause
When dubbo-compiler
generate java files from a proto file, it uses the two variables originMethodName
and methodName
.
The value of the variable originMethodName
is the name of the rpc method, the value of the variable methodName
will lowercase the first letter of the rpc method name.
methodName
is used to fill in the method name of the generated interface class.
originMethodName
is used to fill the value of the methodName
parameter when instantiating the StubMethodDescriptor object in the generated code.
when the triple protocol registers the rest router, it will traverse the interface method and find the StubMethodDescriptor object by the method name.
if the first letter of the RPC method name is capitalized, the StubMethodDescriptor object will not be found here, causing the routing registration to fail.
e.g.
service GreeterService {
rpc SayHello(HelloRequest) returns (HelloReply);
}
as defined above, when generate the code, the value of variable originMethodName
whill be SayHello
,
the value of variable methodName
whill be sayHello
.
Solution
1. introduce the option in proto
we can define an option like this:
extend google.protobuf.MethodOptions {
string java_method_name = 1001;
}
use like this:
import "org/apache/dubbo/compiler/options.proto";
service GreeterService {
rpc SayHello(HelloRequest) returns (HelloReply) {
option (java_method_name) = "sayHello";
}
}
If the developer uses java_method_name
to specify the method name, the values of the template variables originMethodName
and methodName
when generating code will use the same values specified by java_method_name
.
2. associate the value of the methodName
variable with the StubMethodDescriptor object
When i learned about oxsean's work on da8fd19, perhaps we can consider storing the value of the variable methodName
in the ConcurrentMap<String, Object> attributeMap
property of StubMethodDescriptor
in the generated code.
e.g.
if the rpc defined like this:
service GreeterService {
rpc SayHello(HelloRequest) returns (HelloReply);
}
The code generated by dubbo-compiler
is as follows:
private static final StubMethodDescriptor sayHelloMethod = new StubMethodDescriptor("SayHello",
org.apache.dubbo.demo.hello.HelloRequest.class, org.apache.dubbo.demo.hello.HelloReply.class, MethodDescriptor.RpcType.UNARY,
obj -> ((Message) obj).toByteArray(), obj -> ((Message) obj).toByteArray(), org.apache.dubbo.demo.hello.HelloRequest::parseFrom,
org.apache.dubbo.demo.hello.HelloReply::parseFrom);
static {
sayHelloMethod.addAttribute("methodName", "sayHello");
serviceDescriptor.addMethod(sayHelloMethod);
}
When calling the addMethod(MethodDescriptor)
method, prioritize the method name on the attributeMap
. and it will continue based on da8fd19 .
Trade off
solution 1 only requires modifying the dubbo-compiler
, but requires manual settings by the developer.
solution 2 involves more changes, but users are unaware of them.
any suggestions? @oxsean @paxxie2 @zrlw