Okay, let's craft a complete working example of a Gradle-based archetype for a Kotlin gRPC "Hello World" project, including the proto files.
1. Archetype Project Structure
kotlin-grpc-hello-world-archetype/
├── build.gradle.kts
└── src
└── main
└── resources
└── archetype-resources
├── build.gradle.kts
├── src
│ ├── main
│ │ ├── kotlin
│ │ │ └── com
│ │ │ └── example
│ │ │ ├── GreeterClient.kt
│ │ │ └── GreeterServer.kt
│ │ └── proto
│ │ └── helloworld.proto
2. Files Content
build.gradle.kts (in the root of the archetype project)
Kotlin
plugins {
`java-gradle-plugin`
}
group = "com.example"
version = "1.0-SNAPSHOT"
archetype-resources/build.gradle.kts
Kotlin
plugins {
id("org.jetbrains.kotlin.jvm") version "1.8.22"
id("com.google.protobuf") version "0.9.4"
application
}
group = "com.example"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
implementation(platform("io.grpc:grpc-bom:1.57.2"))
implementation("io.grpc:grpc-protobuf")
implementation("io.grpc:grpc-kotlin-stub")
implementation("io.grpc:grpc-netty-shaded")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("io.grpc:grpc-testing")
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.24.4"
}
plugins {
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:1.5.0:jdk8@jar"
}
}
generateProtoTasks {
ofSourceSet("main").forEach {
it.plugins {
id("grpc")
}
}
}
}
application {
mainClass.set("com.example.GreeterServerKt")
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
}
}
sourceSets {
main {
java {
srcDirs("build/generated/source/proto/main/grpc")
srcDirs("build/generated/source/proto/main/java")
}
}
}
archetype-resources/src/main/proto/helloworld.proto
Protocol Buffers
syntax = "proto3";
option java_multiple_files = true;
package com.example;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
archetype-resources/src/main/kotlin/com/example/GreeterServer.kt
Kotlin
package com.example
import io.grpc.Server
import io.grpc.ServerBuilder
import io.grpc.kotlin.AbstractCoroutineServerImpl
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class GreeterService : GreeterGrpcKt.GreeterCoroutineImplBase() {
override suspend fun sayHello(request: HelloRequest): HelloReply = HelloReply
.newBuilder()
.setMessage("Hello, ${request.name}")
.build()
}
fun main() {
val port = 50051
val server = ServerBuilder
.forPort(port)
.addService(GreeterService())
.build()
.start()
println("Server started, listening on $port")
Runtime.getRuntime().addShutdownHook(
Thread {
println("*** shutting down gRPC server since JVM is shutting down")
server.shutdown()
println("*** server shut down")
}
)
server.awaitTermination()
}
archetype-resources/src/main/kotlin/com/example/GreeterClient.kt
Kotlin
package com.example
import io.grpc.ManagedChannelBuilder
import kotlinx.coroutines.runBlocking
fun main() {
val channel = ManagedChannelBuilder.forAddress("localhost", 50051)
.usePlaintext()
.build()
val stub = GreeterGrpcKt.GreeterCoroutineStub(channel)
runBlocking {
val request = HelloRequest.newBuilder()
.setName("world")
.build()
val response = stub.sayHello(request)
println("Received: ${response.message}")
}
channel.shutdown()
}
3. Install and Use
Install: ./gradlew install from the root of the archetype project
Generate a project:
Bash
gradle init --type kotlin-application
Follow the prompts, providing the necessary details for your project.
This complete example should allow you to generate a functional Kotlin gRPC "Hello World" project using your Gradle-based archetype.
Remember: You can further customize this archetype by adding more proto files, modifying the Kotlin code, or adjusting the Gradle build configuration to fit your specific needs!