Hennadii Bulakh
Hennadii Bulakh

Reputation: 21

Proto gRPC Java stub fail while parsing map type

I am building the server-based application based on protobuf with gRPC interface. Server part - golang Client part - Java

The proto file has an object (map as type):

message SomeResponse {
  map<string, Entity> entity_by_id = 1;
}

message Entity {
  uint32 id = 1;
  string name = 2;
}

Based on this file generated the Java gRPC stub to make a request to server. Once I do request to server - client thrown the error: CANCELLED: Failed to read message.

Client code:

EntityRequest request = EntityRequest.newBuilder().addExtIds("abc").build();
        EntityResponse response;
        EntityServiceGrpc.EntityServiceBlockingStub client = EntityServiceGrpc.newBlockingStub(
                ManagedChannelFactory.get(
                        InfrastructureProperties.GRPC_HOST,
                        InfrastructureProperties.GRPC_PORT
                )
        );
        try {
            response = client.getEntityByExtIds(request);
        }
        catch (StatusRuntimeException e) {
            // failing here with CANCELLED: Failed to read message.
}

The server part works 100% - I confirmed it with goLang gRPC client and another...

The request from the client (java stub) reaches out to the server, and the server return response, Java stub is not able to parse it... If I change the object type - works fine. Problem with map.

Can you give me the direction where the problem could be?

Golang protoc version: v4.22.2 Java protoc version to generate stub: 3.23.3 Java client io.grpc version: 1.56.0

I confirmed the specific problem with parsing map value in response by Java stub

The stack trace (I have try to remove useless lines):

Status{code=CANCELLED, description=Failed to read message., cause=java.lang.NoClassDefFoundError: Could not initialize class com.sixt.service.bbb_bbb_extension.api.GuestOuterClass
    at com.sixt.service.bbb_extension.api.GuestByExtIdsResponse$GuestByExtIdDefaultEntryHolder.<clinit>(GuestByExtIdsResponse.java:56)
    at com.sixt.service.bbb_extension.api.GuestByExtIdsResponse$Builder.mergeFrom(GuestByExtIdsResponse.java:471)
    at com.sixt.service.bbb_extension.api.GuestByExtIdsResponse$1.parsePartialFrom(GuestByExtIdsResponse.java:656)
    at com.sixt.service.bbb_extension.api.GuestByExtIdsResponse$1.parsePartialFrom(GuestByExtIdsResponse.java:648)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:86)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:48)
    at io.grpc.protobuf.lite.ProtoLiteUtils$MessageMarshaller.parseFrom(ProtoLiteUtils.java:242)
    at io.grpc.protobuf.lite.ProtoLiteUtils$MessageMarshaller.parse(ProtoLiteUtils.java:234)
    at io.grpc.protobuf.lite.ProtoLiteUtils$MessageMarshaller.parse(ProtoLiteUtils.java:131)
    at io.grpc.MethodDescriptor.parseResponse(MethodDescriptor.java:284)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInternal(ClientCallImpl.java:660)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInContext(ClientCallImpl.java:647)
    at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
    at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
    at io.grpc.stub.ClientCalls$ThreadlessExecutor.runQuietly(ClientCalls.java:777)
    at io.grpc.stub.ClientCalls$ThreadlessExecutor.waitAndDrain(ClientCalls.java:760)
    at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:161)
    at com.sixt.service.ride_user_extension.api.GuestServiceGrpc$GuestServiceBlockingStub.getGuestByExtIds(GuestServiceGrpc.java:397)
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.NoSuchMethodError: 'boolean com.google.protobuf.DescriptorProtos$FieldDescriptorProto.getProto3Optional()' [in thread "Test worker"]
    at com.google.protobuf.Descriptors$FieldDescriptor.<init>(Descriptors.java:1519)
    at com.google.protobuf.Descriptors$FieldDescriptor.<init>(Descriptors.java:1066)
    at com.google.protobuf.Descriptors$Descriptor.<init>(Descriptors.java:944)
    at com.google.protobuf.Descriptors$Descriptor.<init>(Descriptors.java:657)
    at com.google.protobuf.Descriptors$FileDescriptor.<init>(Descriptors.java:561)
    at com.google.protobuf.Descriptors$FileDescriptor.buildFrom(Descriptors.java:333)
    at com.google.protobuf.Descriptors$FileDescriptor.internalBuildGeneratedFileFrom(Descriptors.java:440)
    at com.google.api.HttpProto.<clinit>(HttpProto.java:57)
    at com.google.api.AnnotationsProto.<clinit>(AnnotationsProto.java:54)
    at com.sixt.service.ride_user_extension.api.GuestOuterClass.<clinit>(GuestOuterClass.java:183)
    at com.sixt.service.ride_user_extension.api.GuestByExtIdsRequest.internalGetFieldAccessorTable(GuestByExtIdsRequest.java:38)
    at com.google.protobuf.GeneratedMessageV3.getDescriptorForType(GeneratedMessageV3.java:139)
    at com.google.protobuf.TextFormat$Printer.print(TextFormat.java:363)
    at com.google.protobuf.TextFormat$Printer.print(TextFormat.java:353)
    at com.google.protobuf.TextFormat$Printer.printToString(TextFormat.java:615)
    at com.google.protobuf.AbstractMessage.toString(AbstractMessage.java:110)
    at net.thucydides.core.steps.StepArgumentWriter.readableFormOf(StepArgumentWriter.java:14)
    at net.thucydides.core.steps.StepNamer.testNameWithArguments(StepNamer.java:42)
    at net.thucydides.core.steps.StepNamer.nameFor(StepNamer.java:19)
    at net.thucydides.core.steps.StepInterceptor.getTestNameFrom(StepInterceptor.java:534)
    at net.thucydides.core.steps.StepInterceptor.notifyStepStarted(StepInterceptor.java:568)
    at net.thucydides.core.steps.StepInterceptor.runOrSkipMethod(StepInterceptor.java:208)
    ... 49 more
}

Upvotes: 2

Views: 426

Answers (1)

Dmitry Chornyi
Dmitry Chornyi

Reputation: 1871

Exception java.lang.NoSuchMethodError: 'boolean com.google.protobuf.DescriptorProtos$FieldDescriptorProto.getProto3Optional()'

This means that you generated DescriptorProtos.java from a version of descriptor.proto that doesn't contain proto3_optional field. However your version of Descriptors.java (part of protobuf-java) expects this field to be present.

The solution is to update descriptor.proto (or remove it from the import path and use the one bundled with protoc).

Upvotes: 1

Related Questions