-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Description
Summary
Since release 1.70.0, you cannot have a streaming gRPC method named Notify
because the generated code creates a notify()
method which tries to override the final Object.notify()
.
What version of gRPC-Java are you using?
1.69.1 and misc earlier - example works
1.70.0, 1.75.0 (likely all between those) - example fails to compile
What is your environment?
Linux. Corretto 17.
What did you expect to see?
With this diff to add a streaming Notify
method in the example:
% cat <<EOF > notify-bug
--- a/examples/src/main/proto/hello_streaming.proto
+++ b/examples/src/main/proto/hello_streaming.proto
@@ -24,6 +24,8 @@ package manualflowcontrol;
service StreamingGreeter {
// Streams a many greetings
rpc SayHelloStreaming (stream HelloRequest) returns (stream HelloReply) {}
+
+ rpc Notify(stream HelloRequest) returns (stream HelloReply) {}
}
// The request message containing the user's name.
EOF
Running ./gradlew installdist
should succeed.
What did you see instead?
Versions 1.70.0 and later fail because they're conflicting with Object.notify.
% ./gradlew installDist
> Task :compileJava FAILED
.../grpc-java/examples/build/generated/sources/proto/main/grpc/io/grpc/examples/manualflowcontrol/StreamingGreeterGrpc.java:252: error: notify() in StreamingGreeterBlockingV2Stub cannot override notify() in Object
notify() {
^
overridden method is final
Note: .../grpc-java/examples/src/main/java/io/grpc/examples/customloadbalance/CustomLoadBalanceClient.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.
The generated code (build/generated/sources/proto/main/grpc/io/grpc/examples/manualflowcontrol/StreamingGreeterGrpc.java
) looks like:
public static final class StreamingGreeterBlockingV2Stub
extends io.grpc.stub.AbstractBlockingStub<StreamingGreeterBlockingV2Stub> {
// ...
@io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918")
public io.grpc.stub.BlockingClientCall<io.grpc.examples.manualflowcontrol.HelloRequest, io.grpc.examples.manualflowcontrol.HelloReply>
notify() {
return io.grpc.stub.ClientCalls.blockingBidiStreamingCall(
getChannel(), getNotifyMethod(), getCallOptions());
}
}
Version 1.69.1 and misc earlier versions that I checked succeeded because this V2 stub was introduced in 1.70.0.
Version 1.69.1 works because while it is named notify
, it's not creating a zero arg notify()
:
% rg -A1 "notify" build
build/generated/source/proto/main/grpc/io/grpc/examples/manualflowcontrol/StreamingGreeterGrpc.java
146: default io.grpc.stub.StreamObserver<io.grpc.examples.manualflowcontrol.HelloRequest> notify(
147- io.grpc.stub.StreamObserver<io.grpc.examples.manualflowcontrol.HelloReply> responseObserver) {
--
198: public io.grpc.stub.StreamObserver<io.grpc.examples.manualflowcontrol.HelloRequest> notify(
199- io.grpc.stub.StreamObserver<io.grpc.examples.manualflowcontrol.HelloReply> responseObserver) {
--
279: return (io.grpc.stub.StreamObserver<Req>) serviceImpl.notify(
280- (io.grpc.stub.StreamObserver<io.grpc.examples.manualflowcontrol.HelloReply>) responseObserver);
Steps to reproduce the bug
Using examples from the latest release:
% git clone https://github.com/grpc/grpc-java.git
% cd grpc-java
% git checkout -b test-1-75-0 v1.75.0
% cd examples
Try it without changes as a baseline:
% ./gradlew installDist
% ./gradlew clean
Apply the change that shows the bug:
% cat <<EOF > notify-bug
--- a/examples/src/main/proto/hello_streaming.proto
+++ b/examples/src/main/proto/hello_streaming.proto
@@ -24,6 +24,8 @@ package manualflowcontrol;
service StreamingGreeter {
// Streams a many greetings
rpc SayHelloStreaming (stream HelloRequest) returns (stream HelloReply) {}
+
+ rpc Notify(stream HelloRequest) returns (stream HelloReply) {}
}
// The request message containing the user's name.
EOF
% patch -p2 < notify-bug
Re-run with the proto change and it fails
% ./gradlew installDist
> Task :compileJava FAILED
.../grpc-java/examples/build/generated/sources/proto/main/grpc/io/grpc/examples/manualflowcontrol/StreamingGreeterGrpc.java:252: error: notify() in StreamingGreeterBlockingV2Stub cannot override notify() in Object
notify() {
^
overridden method is final
1 error
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.
* Try:
> Run with --info option to get more log output.
> Run with --scan to get full insights.
BUILD FAILED in 871ms
% ./gradlew clean
It fails in 1.70.0 too:
% git stash
% git checkout -b test-1-70-0 v1.70.0
# Builds normally
% ./gradlew installDist
% ./gradlew clean
# Fails with this change
% git stash pop
% git diff
% ./gradlew installDist
% ./gradlew clean
However, with the last release before 1.70.0 (1.69.1) it works:
% git stash
% git checkout -b test-1-69-1 v1.69.1
# Try without changes
% ./gradlew installDist
% ./gradlew clean
# Try with changes to show it still succeeds
% git stash pop
% git diff
% ./gradlew installDist
If you redo the above but name the gRPC method Notify2
so it doesn't conflict with Object.notify
, all three grpc-java releases work.
Suspected commit
I suspect it is due to this commit in 1.70.0:
stub: Introduce new API: BlockingStubV2 which supports Bidi streaming, Client streaming, a cleaner Server streaming and Unary RPCs (#10318) (ea8c31c)
It looks like it is lower casing the name without mangling it in case of conflicts like notify
. e.g. it creates java methods sayHelloStreaming()
and notify()
when the gRPC service methods are named SayHelloStreaming
and Notify
.