├── .gitignore ├── kotlin-grpc-keyvalue-service ├── src │ └── main │ │ ├── java │ │ └── grpc │ │ │ └── service │ │ │ └── kv │ │ │ ├── GrpcServer.kt │ │ │ └── KeyValueService.kt │ │ └── proto │ │ └── kv.proto └── pom.xml ├── kotlin-grpc-user-service ├── src │ └── main │ │ ├── proto │ │ └── user.proto │ │ └── java │ │ └── grpc │ │ └── service │ │ └── user │ │ ├── GrpcServer.kt │ │ └── UserService.kt └── pom.xml ├── README.md ├── kotlin-grpc-client ├── src │ └── main │ │ └── java │ │ └── grpc │ │ └── client │ │ └── GrpcClient.kt └── pom.xml └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | target 4 | -------------------------------------------------------------------------------- /kotlin-grpc-keyvalue-service/src/main/java/grpc/service/kv/GrpcServer.kt: -------------------------------------------------------------------------------- 1 | package grpc.service.kv 2 | 3 | fun main(args: Array) { 4 | 5 | val server = io.grpc.ServerBuilder.forPort(15000).addService(KeyValueService()).build() 6 | server.start() 7 | 8 | println("Key value service started") 9 | 10 | Runtime.getRuntime().addShutdownHook(Thread { println("Ups, JVM shutdown") }) 11 | server.awaitTermination() 12 | 13 | println("Key value service stopped") 14 | } 15 | -------------------------------------------------------------------------------- /kotlin-grpc-user-service/src/main/proto/user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package services; 4 | 5 | option java_multiple_files = true; 6 | option java_package = "services"; 7 | option java_outer_classname = "UserServiceProtos"; 8 | 9 | service UserService { 10 | rpc getUser(UserRequest) returns (UserResponse) {} 11 | } 12 | 13 | // The request message containing the user's name. 14 | message UserRequest { 15 | string name = 1; 16 | } 17 | 18 | // The response message containing the greetings 19 | message UserResponse { 20 | string name = 1; 21 | string emailAddress = 2; 22 | bool active = 3; 23 | string country = 4; 24 | } 25 | -------------------------------------------------------------------------------- /kotlin-grpc-keyvalue-service/src/main/proto/kv.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package services; 4 | 5 | option java_multiple_files = true; 6 | option java_package = "services"; 7 | option java_outer_classname = "KeyValueServiceProtos"; 8 | 9 | service KeyValueService { 10 | rpc put(PutRequest) returns (PutResponse) {} 11 | rpc get(GetRequest) returns (GetResponse) {} 12 | } 13 | 14 | message PutRequest { 15 | string key = 1; 16 | string value = 2; 17 | } 18 | 19 | message PutResponse { 20 | } 21 | 22 | message GetRequest { 23 | string key = 1; 24 | } 25 | 26 | message GetResponse { 27 | string key = 1; 28 | string value = 2; 29 | } 30 | -------------------------------------------------------------------------------- /kotlin-grpc-user-service/src/main/java/grpc/service/user/GrpcServer.kt: -------------------------------------------------------------------------------- 1 | package grpc.service.user 2 | 3 | import io.grpc.ManagedChannelBuilder 4 | import io.grpc.ServerBuilder 5 | import services.KeyValueServiceGrpcKt 6 | 7 | fun main(args: Array) { 8 | 9 | val channel = ManagedChannelBuilder.forAddress("localhost", 15000).usePlaintext().build() 10 | val kvsClient = KeyValueServiceGrpcKt.newStub(channel) 11 | 12 | val server = ServerBuilder.forPort(15001).addService(UserService(kvsClient)).build() 13 | server.start() 14 | 15 | println("User service started") 16 | 17 | Runtime.getRuntime().addShutdownHook(Thread { println("Ups, JVM shutdown") }) 18 | server.awaitTermination() 19 | 20 | println("User service stopped") 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple Sample Kotlin gRPC service 2 | 3 | Very simple Java8 sample of a gRPC Kotlin service. 4 | Check Java9 branch to check Java9 sample. 5 | 6 | This samples is composed by two gRPC services (user and key value) and one client. 7 | The user service must get data from the key value service to provide all information about the user to a client. 8 | 9 | 10 | 11 | ### Pre requirements 12 | * Java 8 13 | * Maven 14 | 15 | ### About gRPC 16 | ... 17 | 18 | ### About Kotlin 19 | ... 20 | 21 | ## Try it 22 | 23 | 24 | **Build** 25 | ``` 26 | mvn clean install 27 | ``` 28 | ### Run key value service 29 | ``` 30 | mvn -pl kotlin-grpc-keyvalue-service exec:java 31 | ``` 32 | ### Run user service 33 | ``` 34 | mvn -pl kotlin-grpc-user-service exec:java 35 | ``` 36 | ### Run the client 37 | ``` 38 | mvn -pl kotlin-grpc-client exec:java 39 | ``` 40 | -------------------------------------------------------------------------------- /kotlin-grpc-client/src/main/java/grpc/client/GrpcClient.kt: -------------------------------------------------------------------------------- 1 | package grpc.client 2 | 3 | import com.google.common.collect.Iterators 4 | import io.grpc.ManagedChannelBuilder 5 | import services.UserRequest 6 | import services.UserServiceGrpc 7 | import java.util.concurrent.TimeUnit 8 | 9 | fun main(args: Array) { 10 | 11 | val channel = ManagedChannelBuilder.forAddress("localhost", 15001).usePlaintext().build() 12 | val blockingStub = UserServiceGrpc.newBlockingStub(channel) 13 | 14 | try { 15 | val users = Iterators.cycle("radha", "kanti", "chanda", "kali") 16 | var i = 0 17 | while (users.hasNext() && i < 100) { 18 | 19 | val request = UserRequest.newBuilder().setName(users.next()).build() 20 | 21 | println("Response from server:\n${blockingStub.getUser(request)}") 22 | i++ 23 | } 24 | 25 | } finally { 26 | channel.shutdown().awaitTermination(5, TimeUnit.SECONDS) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kotlin-grpc-user-service/src/main/java/grpc/service/user/UserService.kt: -------------------------------------------------------------------------------- 1 | package grpc.service.user 2 | 3 | import kotlinx.coroutines.async 4 | import services.GetRequest 5 | import services.KeyValueServiceGrpcKt.KeyValueServiceKtStub 6 | import services.UserRequest 7 | import services.UserResponse 8 | import services.UserServiceGrpcKt.UserServiceImplBase 9 | 10 | class UserService(private val keyValue: KeyValueServiceKtStub) : UserServiceImplBase() { 11 | 12 | override suspend fun getUser(request: UserRequest): UserResponse { 13 | suspend fun getValue(key: String) = keyValue.get( 14 | GetRequest 15 | .newBuilder() 16 | .setKey(request.name + key) 17 | .build() ?: throw IllegalArgumentException("key not found") 18 | ) 19 | 20 | val email = async { getValue(".email") } 21 | val country = async { getValue(".country") } 22 | val active = async { getValue(".active") } 23 | 24 | return UserResponse 25 | .newBuilder() 26 | .setName(request.name ?: throw IllegalArgumentException("name can not be null")) 27 | .setEmailAddress(email.await().value) 28 | .setCountry(country.await().value) 29 | .setActive(active.await().value?.toBoolean() ?: false) 30 | .build() 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /kotlin-grpc-keyvalue-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | kotlin-grpc-sample 7 | flaviof.samples.kotlin 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | kotlin-grpc-keyvalue-service 13 | 14 | 15 | 16 | io.grpc 17 | grpc-all 18 | 19 | 20 | 21 | 22 | 23 | 24 | org.codehaus.mojo 25 | exec-maven-plugin 26 | 1.2.1 27 | 28 | 29 | 30 | java 31 | 32 | 33 | 34 | 35 | grpc.service.kv.GrpcServerKt 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /kotlin-grpc-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | kotlin-grpc-sample 7 | flaviof.samples.kotlin 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | kotlin-grpc-client 13 | 14 | 15 | 16 | flaviof.samples.kotlin 17 | kotlin-grpc-user-service 18 | 1.0-SNAPSHOT 19 | 20 | 21 | 22 | io.grpc 23 | grpc-all 24 | 25 | 26 | 27 | 28 | 29 | 30 | org.codehaus.mojo 31 | exec-maven-plugin 32 | 1.2.1 33 | 34 | 35 | 36 | java 37 | 38 | 39 | 40 | 41 | grpc.client.GrpcClientKt 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /kotlin-grpc-user-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | kotlin-grpc-sample 7 | flaviof.samples.kotlin 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | kotlin-grpc-user-service 13 | 14 | 15 | 16 | flaviof.samples.kotlin 17 | kotlin-grpc-keyvalue-service 18 | 1.0-SNAPSHOT 19 | 20 | 21 | 22 | io.grpc 23 | grpc-all 24 | 25 | 26 | 27 | 28 | 29 | 30 | org.codehaus.mojo 31 | exec-maven-plugin 32 | 1.2.1 33 | 34 | 35 | 36 | java 37 | 38 | 39 | 40 | 41 | grpc.service.user.GrpcServerKt 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /kotlin-grpc-keyvalue-service/src/main/java/grpc/service/kv/KeyValueService.kt: -------------------------------------------------------------------------------- 1 | package grpc.service.kv 2 | 3 | import services.GetRequest 4 | import services.GetResponse 5 | import services.KeyValueServiceGrpcKt.KeyValueServiceImplBase 6 | import services.PutRequest 7 | import services.PutResponse 8 | 9 | class KeyValueService : KeyValueServiceImplBase() { 10 | 11 | val names = listOf("radha", "kanti", "chanda", "kali") 12 | 13 | internal var store: MutableMap = hashMapOf( 14 | "${names[0]}.email" to "${names[0]}@gmail.com", 15 | "${names[0]}.country" to "Portugal", 16 | "${names[0]}.active" to "true", 17 | "${names[1]}.email" to "${names[1]}@gmail.com", 18 | "${names[1]}.country" to "France", 19 | "${names[1]}.active" to "true", 20 | "${names[2]}.email" to "${names[2]}@gmail.com", 21 | "${names[2]}.country" to "Spain", 22 | "${names[2]}.active" to "true", 23 | "${names[3]}.email" to "${names[3]}@gmail.com", 24 | "${names[3]}.country" to "UK", 25 | "${names[3]}.active" to "false" 26 | ) 27 | 28 | override suspend fun put(request: PutRequest): PutResponse { 29 | store.put(request.key ?: throw IllegalArgumentException("key can not be null"), 30 | request.value ?: throw IllegalArgumentException("value can not be null") 31 | ) 32 | 33 | return PutResponse.getDefaultInstance() 34 | } 35 | 36 | override suspend fun get(request: GetRequest): GetResponse { 37 | return GetResponse 38 | .newBuilder() 39 | .setValue( 40 | store[request.key ?: throw IllegalArgumentException("key can not be null")] 41 | ?: throw IllegalArgumentException("${request.key} key not found") 42 | ).build() 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | flaviof.samples.kotlin 8 | kotlin-grpc-sample 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | 13 | kotlin-grpc-user-service 14 | kotlin-grpc-keyvalue-service 15 | kotlin-grpc-client 16 | 17 | 18 | 19 | 1.3.0 20 | 21 | 1.16.1 22 | 3.5.1-1 23 | 24 | 25 | 26 | 27 | 28 | io.grpc 29 | grpc-all 30 | ${grpc.version} 31 | 32 | 33 | 34 | org.jetbrains.kotlin 35 | kotlin-stdlib 36 | ${kotlin.version} 37 | 38 | 39 | org.jetbrains.kotlinx 40 | kotlinx-coroutines-core 41 | 1.0.0 42 | 43 | 44 | org.jetbrains.kotlin 45 | kotlin-test-junit 46 | ${kotlin.version} 47 | 48 | 49 | 50 | 51 | 52 | 53 | org.jetbrains.kotlin 54 | kotlin-stdlib 55 | 56 | 57 | 58 | org.jetbrains.kotlinx 59 | kotlinx-coroutines-core 60 | 61 | 62 | org.jetbrains.kotlin 63 | kotlin-test-junit 64 | test 65 | 66 | 67 | 68 | 69 | 70 | 71 | kr.motd.maven 72 | os-maven-plugin 73 | 1.4.1.Final 74 | 75 | 76 | 77 | 78 | maven-compiler-plugin 79 | 80 | 1.8 81 | 1.8 82 | 83 | 84 | 85 | org.jetbrains.kotlin 86 | kotlin-maven-plugin 87 | ${kotlin.version} 88 | 89 | 90 | compile 91 | compile 92 | 93 | compile 94 | 95 | 96 | 97 | test-compile 98 | test-compile 99 | 100 | test-compile 101 | 102 | 103 | 104 | 105 | 106 | org.xolstice.maven.plugins 107 | protobuf-maven-plugin 108 | 0.5.0 109 | 110 | com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier} 111 | grpc-java 112 | io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} 113 | 114 | 115 | GrpcKotlinGenerator 116 | io.rouz 117 | grpc-kotlin-gen 118 | 0.0.6 119 | io.rouz.grpc.kotlin.GrpcKotlinGenerator 120 | 121 | 122 | 123 | 124 | 125 | 126 | compile 127 | compile-custom 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | --------------------------------------------------------------------------------