Search code examples
javagradleprotocol-buffersgrpc-javaprotoc

Problem when auto generating gRPC stub files using Gradle


I've been asked to implement some gRPC classes for a college course, and have run into some problems when generating the java classes from one source proto file.

Some background first: it's a fairly basic service, with a simple method that receives an id and returns a phone and an email. This is the proto file (BuscarData means FetchData, sorry for the leftover non translation!):

syntax = 'proto3';
option java_multiple_files=true;
option java_generic_services= true;
package  uy.edu.um.sd20;

message DataRequest {
  int32 id = 1;
}

message DataResponse {
  string phone = 1;
  string email = 2;
}

service DataRepo {
  rpc BuscarData (DataRequest) returns (DataResponse);
}

The idea I had was to generate the classes with gradle plugins. My build.gradle:

plugins {
    id 'java'
    id "com.google.protobuf" version '0.8.8'
}
apply plugin: 'java'

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.11.4'
    implementation 'io.grpc:grpc-netty-shaded:1.29.0'
    implementation 'io.grpc:grpc-protobuf:1.29.0'
    implementation 'io.grpc:grpc-stub:1.29.0'

}

sourceSets {
    main {
        proto {
            srcDir 'src/main/proto'
        }
        java {
            srcDirs 'src/main/java', 'generated-sources/main/java'
        }
    }
}

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.11.0'
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.29.0'
        }
    }
    generateProtoTasks.generatedFilesBaseDir = 'generated-sources'

    generateProtoTasks {
        all().each { task ->
            // Here you can configure the task
        }
        ofSourceSet('main')

    }
}

From what I understood, everything's there: the grpc and protoc dependencies, and the plugin which enables protoc to compile grpc (protoc-gen-grpc), and where to deposit the generated files. However, there are two problems:

  1. the generated-sources are not marked as source or anything like that, meaning they cannot be imported from other classes
  2. if I'm not mistaken, the generated-sources should generate a skeleton of DataRepoImpl so that I can add the code needed for BuscarData. However, it didn't. Or maybe I should create it, extending from DataRepo.java, but I couldn't test it, due to problem n°1.

I've added a screenshot of the project file structure: img

As you can see, quite a lot (if not all) of the gradle settings are copy-pasted and scavenged from many different web-sites. I hope I was careful enough not to repeat any imports. There are similar questions, and I tried the solutions there, but no luck there. One example, with which I knew I had to include the gen grpc plugin: another SO question

Any tip regarding anything else is welcome! I'm new to stackoverflow question-asking, so I may have made mistakes regarding the question specificity or aim of the question.

Thanks!

Franri.


Solution

  • For 1), the plugin should put the generated files are the input for java compile tasks even if you do not explicitly add 'generated-sources/main/java' in the sourceSets configuration. Version 0.8.8 has been a while, you can try with newer versions. There might have been some minor fixes for things you may hit.

    For 2), you did not add grpc plugin to each generateProto task. It should be

    generateProtoTasks {
        all().each { task ->
            task.plugins { grpc{} }
        }
        ofSourceSet('main')
    
    }