How do I combine proto buf definitions from separate name spaces in a single proto buf file?

23 views
Skip to first unread message

John Buczkowski

unread,
May 5, 2021, 11:34:04 AMMay 5
to grpc.io
I'm building out a series of ProtoBuf definitions for a .NetCore gRPC application.
I'm using the Orchestrator pattern as I will be creating a series of microservices.

I am running into issues with my proto definitions throwing compiler errors as being "undefined."
The definitions are in several different files (with different C# namespaces).
What follows is a simplified version of my definitions.

Consider the following protobuf files:

**service.proto**

    syntax = "proto3";
    option csharp_namespace = "RequestHandlerService";
    package test;
    
    service Handler
    {
      rpc AddItem1(G_RequestType1) returns (G_RequestResponse) { }
      rpc AddItem2(G_RequestType2) returns (G_RequestResponse) { }
    }
    
    message G_RequestType1{
      string originId = 1;
      string request = 2;
    }
    
    message G_RequestType2{
      string originId = 1;
      string request = 2;
    }
    
    message G_RequestResponse{
      string response = 1;
    }


**windowsservice.proto:**

    syntax = "proto3";
    import "google/protobuf/timestamp.proto";
    option csharp_namespace = "Windows.RequestHandler.Service";
    package windows.requesthandler.service;
    
    service WindowsHandler
    {
        rpc Action1(G_Action1Request) returns (G_Action1Response) { }
        rpc Action2(G_Action2Request) returns (G_Action2Reponse) { }
    }
    
    message G_Action1Request{
        string transactionId = 1;
        google.protobuf.Timestamp DateTimeStamp = 2;
        string filePath = 3;
    }
    
    message G_Action2Request{
        string transactionId = 1;
        google.protobuf.Timestamp DateTimeStamp = 2;
        string textToInsert = 3;
    }
    
    message G_Action1Response {
        google.protobuf.Timestamp DateTimeStamp = 1;
        string fileSecurityStatusMessage = 2;
        G_Action1Request action1Request = 3;
    }
    
    message G_Action2Response {
        google.protobuf.Timestamp DateTimeStamp = 1;
        string fileModifierStatusMessage = 2;
    G_Action2Request action2Request = 3;
    }
    
    
    message G_WindowsRequest {
        int32 requestId = 1;
        oneof RequestType{
            G_Action1Request action1Request = 2;
            G_Action2Request action2Requestion = 3;
        }
    }
    
    message G_WindowsRequestResponse {
        bool wasSuccessful = 1;
        string response = 2;
        oneof ResponseType{
            G_Action1Response action1Response = 3;
            G_Action2Response action2Respone = 4;
        }
    }


**orchestrator.proto**

    syntax = "proto3";
    option csharp_namespace = "OrchestratorService";
    package test;
    
    import "service.proto";
    import "windowsservice.proto";
    
    service Orchestrator
    {
      rpc RegisterClient(G_RegisterClientRequest) returns (stream G_Response) { }
      rpc EnqueueRequest(G_OrchestrationRequest) returns (G_Response) { }
    }
    
    message G_OrchestrationRequest{
      string originId = 1;
      oneof RequestType{
        G_RequestType1 requestType1 = 2;
        G_RequestType2 requestType2 = 3;
        G_Response response = 4;
        G_WindowsRequest windowsRequest = 5;
        G_WindowsRequestResponse windowsRequestResponse = 6;
      }
    }
    
    message G_RegisterClientRequest{
      string clientId = 1;
    }
    
    message G_Response{
      bool wasSuccessful = 1;
      string response = 2;
    }

Here is the <ItemGroup> definition from the csproj file for my Orchestrator project:

     <ItemGroup>
    <Protobuf Include="../Protos/orchestrator.proto" GrpcServices="Server" ProtoRoot="../Protos/">
    <Link>Protos/orchestrator.proto</Link>
    </Protobuf>
    <Protobuf Include="../Protos/service.proto" GrpcServices="Client" ProtoRoot="../Protos/">
    <Link>Protos/service.proto</Link>
    </Protobuf>
    <Protobuf Include="../Protos/windowsservice.proto" GrpcServices="Client" ProtoRoot="../Protos/">
      <Link>Protos/windowservice.proto</Link>
    </Protobuf>
    </ItemGroup>

Both **G_WindowsRequest** and **G_WindowsRequestResponse** are throwing a compiler error saying they are undefined. Is this an issue with **csharp_namespace** and/or **package** resolution?

Is there a way to enforce separate package/csharp_namespace definitions within the separate proto definitions, but reference those definitions within the rolled up "orchestrator" proto file definition?


**Here is a snippet of the compiler errors I am seeing:**

> 2>  orchestrator.proto(22,5): error : "G_WindowsRequest" is not
> defined. 2>  orchestrator.proto(23,5): error :
> "G_WindowsRequestResponse" is not defined. 2>Done building target
> "_Protobuf_CoreCompile" in project "Protos.csproj" -- FAILED. 2>
> 2>Done building project "Protos.csproj" -- FAILED. 2> 2>Build FAILED.
> 2> 2>orchestrator.proto(22,5): error : "G_WindowsRequest" is not
> defined. 2>orchestrator.proto(23,5): error :
> "G_WindowsRequestResponse" is not defined. 2>    0 Warning(s) 2>    2
> Error(s)

Jan Tattermusch

unread,
May 7, 2021, 5:22:10 AMMay 7
to grpc.io
G_WindowsRequest is declared in package "windows.requesthandler.service", but in orchestrator.proto (which itself is under package "test"), you're only referring to it as "G_WindowsRequest", without specifying the package name. The protobuf compiler has no way of knowing which "G_WindowsRequest" you want (FWIW there could be 50 other definitions of that name under different packages).
I think you need to use the fully qualified name windows.requesthandler.service.G_WindowsRequest, since G_WindowsRequest is from a different namespace than you're currently in. That should fix the issue you're seeing.
Reply all
Reply to author
Forward
0 new messages