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.
Summary
Since release 1.70.0, you cannot have a streaming gRPC method named
Notifybecause the generated code creates anotify()method which tries to override the finalObject.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
Notifymethod in the example:Running
./gradlew installdistshould succeed.What did you see instead?
Versions 1.70.0 and later fail because they're conflicting with Object.notify.
The generated code (
build/generated/sources/proto/main/grpc/io/grpc/examples/manualflowcontrol/StreamingGreeterGrpc.java) looks like: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 argnotify():Steps to reproduce the bug
Using examples from the latest release:
Try it without changes as a baseline:
Apply the change that shows the bug:
Re-run with the proto change and it fails
It fails in 1.70.0 too:
However, with the last release before 1.70.0 (1.69.1) it works:
If you redo the above but name the gRPC method
Notify2so it doesn't conflict withObject.notify, all three grpc-java releases work.Suspected commit
I suspect it is due to this commit in 1.70.0:
It looks like it is lower casing the name without mangling it in case of conflicts like
notify. e.g. it creates java methodssayHelloStreaming()andnotify()when the gRPC service methods are namedSayHelloStreamingandNotify.