The Wire compiler will generate interfaces for your service RPCs defined in your protobuf schema; under the condition that the target is set to Kotlin.
You can configure how your services are generated via the Gradle plugin:
wire {
// Kotlin target will generate code for services.
kotlin {
// `client` to generate interfaces best suited to sending outbound calls.
// `server` to generate interfaces best suited to receiving inbound calls.
rpcRole = 'server'
// Server only
// `suspending` to generate coroutines APIs that require a Kotlin coroutines context.
// `blocking` to generate blocking APIs callable by Java and Kotlin.
rpcCallStyle = 'suspending'
// Server only
// True for emitted services to generate one interface per RPC.
singleMethodServices = false
}
}
The generated code varies depending on your RPC role, namely client or server.
We'll use the following schema to demonstrate how they differ:
syntax = "proto2";
package routeguide;
service RouteGuide {
// A simple RPC.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
For the schema RouteGuide
, when rpcRole
is client
, the Wire compiler will generate the
following interface:
interface RouteGuideClient : Service {
fun GetFeature(): GrpcCall<Point, Feature>
fun ListFeatures(): GrpcStreamingCall<Rectangle, Feature>
fun RecordRoute(): GrpcStreamingCall<Point, RouteSummary>
fun RouteChat(): GrpcStreamingCall<RouteNote, RouteNote>
}
For streaming APIs, we return a GrpcStreamingCall, and a GrpcCall otherwise. With these objects, the caller can communicate with the server. Both blocking and suspending APIs are provided.
To help you instantiate your service, we provide a small runtime, namely GrpcClient:
val grpcClient = GrpcClient.Builder()
.client(OkHttpClient.Builder().protocols(listOf(Protocol.H2_PRIOR_KNOWLEDGE)).build())
.baseUrl(serverUrl)
.build()
val routeGuideClient = grpcClient.create(RouteGuideClient::class)
Following this configuration:
wire {
kotlin {
rpcRole = 'server'
rpcCallStyle = 'blocking'
}
}
the Wire compiler will generate the following interface for the server to implement:
interface RouteGuideBlockingServer : Service {
fun GetFeature(request: Point): Feature
fun ListFeatures(request: Rectangle, response: MessageSink<Feature>)
fun RecordRoute(request: MessageSource<Point>): RouteSummary
fun RouteChat(request: MessageSource<RouteNote>, response: MessageSink<RouteNote>)
}
For streaming connections, the server can use Wire's blocking APIs: MessageSource and MessageSink.
Following this configuration:
wire {
kotlin {
rpcRole = 'server'
rpcCallStyle = 'suspending'
}
}
the Wire compiler will generate the following interface for the server to implement:
interface RouteGuideServer : Service {
suspend fun GetFeature(request: Point): Feature
fun ListFeatures(request: Rectangle, response: SendChannel<Feature>)
fun RecordRoute(request: ReceiveChannel<Point>): RouteSummary
fun RouteChat(request: ReceiveChannel<RouteNote>, response: SendChannel<RouteNote>)
}
The server can use Kotlin coroutines' suspend and Channels mechanisms to execute suspending network calls.
Check out our sample project demonstrating bidirectional communication between an Android application and a server.
Use Wire runtime Gradle coordinates:
implementation("com.squareup.wire:wire-runtime:LATEST_VERSION")
In addition, to use Wire gRPC for clients, use these new Gradle coordinates:
implementation("com.squareup.wire:wire-grpc-client:LATEST_VERSION")