grpc / grpc-kotlin

Kotlin gRPC implementation. HTTP/2 based RPC
https://grpc.io/docs/languages/kotlin
Apache License 2.0
1.2k stars 165 forks source link

Generate Kotlin builders for external types #373

Open JavierSegoviaCordoba opened 1 year ago

JavierSegoviaCordoba commented 1 year ago

I am using date.proto from Google types but I need to use Date.newBuilder().... Is it possible to generate a date { } builder?

jamesward commented 1 year ago

I believe that you can have dependencies on libraries that contain protos and the wrappers (Kotlin Protos for example) will be created around them. So I think this should work. Maybe I can build a little sample for this if I get the chance.

JavierSegoviaCordoba commented 1 year ago

Yeah, a sample should be great 😄 Thank you @jamesward!

jamesward commented 1 year ago

Here is the sample: https://github.com/jamesward/grpc-kotlin-sample-deps

Date Kotlin Builders part: https://github.com/jamesward/grpc-kotlin-sample-deps/blob/main/src/main/kotlin/io/grpc/examples/helloworld/HelloWorldServer.kt#L55-L60

The trick is to add a dep to the protobuf configuration, like:

protobuf("com.google.api.grpc:proto-google-common-protos:2.11.0")

That causes the protobuf Gradle plugin to treat it as a proto dependency and generate the sources for protos in the jar. Details: https://github.com/google/protobuf-gradle-plugin#protos-in-dependencies

There is probably another way you could configure the Gradle plugin to only generate the Kotlin wrappers for that dependency (and not re-generate the Java wrappers that are already in the jar).

Hopefully that helps!

JavierSegoviaCordoba commented 1 year ago

@jamesward I think I have the problem in that I have an intermediate protos module

// protos/build.gradle.kts
// it is using google protos
plugins {
    `java-library`
}

java {
    sourceSets.getByName("main").resources.srcDir("src/main/proto")
}

And in the server

// server/build.gradle.kts
dependencies {
    protobuf(project(projects.protos.dependencyProject.path))
}

protos module is going to be consumed from clients and servers, so it shouldn't generate anything. How would you setup this?

jamesward commented 1 year ago

Check out how we do this in the grpc-kotlin examples: https://github.com/grpc/grpc-kotlin/tree/master/examples

protos module: https://github.com/grpc/grpc-kotlin/blob/master/examples/protos/build.gradle.kts

primary stub module: https://github.com/grpc/grpc-kotlin/blob/master/examples/stub/build.gradle.kts

Let me know if that helps.

JavierSegoviaCordoba commented 1 year ago

Indeed I copied that setup, I will review it again to check if I am missing anything 🤔.

jamesward commented 1 year ago

The structure overview is something like:

jamesward commented 1 year ago

The one part that might be hard to setup is a dependency in protos on the other library since that project doesn't have the protobuf configuration. Probably a way to make that work but a bit tricky.

JavierSegoviaCordoba commented 1 year ago

@jamesward but stub generates client + server code? Or only the code related to proto messages?

jamesward commented 1 year ago

I have it setup so that stub generates the proto messages and the gRPC wrappers. But you could definitely split that out into two separate modules. I don't think there is a way to split out the client & server gRPC parts though (that I know of).