Skip to content

Commit

Permalink
add graalvm example - fixes #152 (#187)
Browse files Browse the repository at this point in the history
* add graalvm example - fixes #152

* try to make tests not flaky

* adds env var for PORT to graal client

Co-authored-by: Brent Shaffer <betterbrent@google.com>
  • Loading branch information
jamesward and bshaffer authored Oct 13, 2020
1 parent bc0882f commit 6c6078c
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 19 deletions.
17 changes: 16 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ Sub-Project Layout:
- `protos` : Only protobufs
- `stub` : Creates regular Java & Kotlin stub artifacts from the `protos` sub-project
- `stub-lite` : Creates lite Java & Kotlin stub artifacts from the `protos` sub-project
- `stub-android` : Creates Android-compatible Java & Kotlin stub artifacts from the `protos` sub-project
- `server` : Kotlin servers based on regular `stub` artifacts
- `client` : Kotlin clients based on regular `stub` artifacts
- `android` : Kotlin Android app based on `stub-lite` artifacts and the `server`
- `native-client` : GraalVM Native Image clients based on `stub-lite` artifacts
- `android` : Kotlin Android app based on `stub-android` artifacts

## Hello, World Client & Server Example

Expand Down Expand Up @@ -46,6 +48,19 @@ In another console, run the client against the "dog", "pig", and "sheep" service
./gradlew :client:AnimalsClient --args=sheep
```

## GraalVM Native Image Example

Start the server:
```sh
./gradlew :server:HelloWorldServer
```

In another console, create the native image client and run it:
```sh
./gradlew :native-client:nativeImage
native-client/build/graal/hello-world
```

## Android Example

Start the server:
Expand Down
2 changes: 1 addition & 1 deletion examples/android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ dependencies {
implementation(kotlin("stdlib"))
implementation("androidx.appcompat:appcompat:1.2.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8")
implementation(project(":stub-lite"))
implementation(project(":stub-android"))
runtimeOnly("io.grpc:grpc-okhttp:${rootProject.ext["grpcVersion"]}")
}

Expand Down
37 changes: 37 additions & 0 deletions examples/native-client/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
plugins {
application
kotlin("jvm")
id("com.palantir.graal") version "0.7.1"
}

dependencies {
implementation(kotlin("stdlib-jdk8"))
implementation(project(":stub-lite"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8")

runtimeOnly("io.grpc:grpc-okhttp:${rootProject.ext["grpcVersion"]}")
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
}

application {
mainClass.set("io.grpc.examples.helloworld.HelloWorldClientKt")
}

// todo: add graalvm-config-create task
// JAVA_HOME=~/.gradle/caches/com.palantir.graal/20.2.0/8/graalvm-ce-java8-20.2.0 JAVA_OPTS=-agentlib:native-image-agent=config-output-dir=native-client/src/graal native-client/build/install/native-client/bin/native-client

graal {
graalVersion("20.2.0")
mainClass(application.mainClassName)
outputName("hello-world")
option("--verbose")
option("--no-server")
option("--no-fallback")
option("-H:+ReportExceptionStackTraces")
option("-H:+TraceClassInitialization")
option("-H:+PrintClassInitialization")
option("-H:ReflectionConfigurationFiles=src/graal/reflect-config.json")
}
84 changes: 84 additions & 0 deletions examples/native-client/src/graal/reflect-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
[
{
"name":"com.sun.jndi.dns.DnsContextFactory"
},
{
"name":"io.grpc.examples.helloworld.HelloReply",
"fields":[{"name":"message_", "allowUnsafeAccess":true}]
},
{
"name":"io.grpc.examples.helloworld.HelloRequest",
"fields":[{"name":"name_", "allowUnsafeAccess":true}]
},
{
"name":"io.grpc.internal.DnsNameResolverProvider"
},
{
"name":"io.grpc.internal.JndiResourceResolverFactory",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.grpc.internal.PickFirstLoadBalancerProvider"
},
{
"name":"io.grpc.util.SecretRoundRobinLoadBalancerProvider$Provider"
},
{
"name":"java.net.InetSocketAddress",
"methods":[{"name":"getHostString","parameterTypes":[] }]
},
{
"name":"java.nio.Buffer",
"fields":[{"name":"address", "allowUnsafeAccess":true}]
},
{
"name":"java.util.concurrent.ScheduledThreadPoolExecutor",
"methods":[{"name":"setRemoveOnCancelPolicy","parameterTypes":["boolean"] }]
},
{
"name":"java.util.concurrent.atomic.LongAdder",
"allPublicConstructors":true,
"methods":[
{"name":"add","parameterTypes":["long"] },
{"name":"sum","parameterTypes":[] }
]
},
{
"name":"javax.naming.directory.InitialDirContext"
},
{
"name":"kotlin.internal.jdk8.JDK8PlatformImplementations",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.misc.Unsafe",
"allDeclaredFields":true,
"methods":[
{"name":"arrayBaseOffset","parameterTypes":["java.lang.Class"] },
{"name":"arrayIndexScale","parameterTypes":["java.lang.Class"] },
{"name":"copyMemory","parameterTypes":["long","long","long"] },
{"name":"copyMemory","parameterTypes":["java.lang.Object","long","java.lang.Object","long","long"] },
{"name":"getBoolean","parameterTypes":["java.lang.Object","long"] },
{"name":"getByte","parameterTypes":["long"] },
{"name":"getByte","parameterTypes":["java.lang.Object","long"] },
{"name":"getDouble","parameterTypes":["java.lang.Object","long"] },
{"name":"getFloat","parameterTypes":["java.lang.Object","long"] },
{"name":"getInt","parameterTypes":["long"] },
{"name":"getInt","parameterTypes":["java.lang.Object","long"] },
{"name":"getLong","parameterTypes":["long"] },
{"name":"getLong","parameterTypes":["java.lang.Object","long"] },
{"name":"getObject","parameterTypes":["java.lang.Object","long"] },
{"name":"objectFieldOffset","parameterTypes":["java.lang.reflect.Field"] },
{"name":"putBoolean","parameterTypes":["java.lang.Object","long","boolean"] },
{"name":"putByte","parameterTypes":["long","byte"] },
{"name":"putByte","parameterTypes":["java.lang.Object","long","byte"] },
{"name":"putDouble","parameterTypes":["java.lang.Object","long","double"] },
{"name":"putFloat","parameterTypes":["java.lang.Object","long","float"] },
{"name":"putInt","parameterTypes":["long","int"] },
{"name":"putInt","parameterTypes":["java.lang.Object","long","int"] },
{"name":"putLong","parameterTypes":["long","long"] },
{"name":"putLong","parameterTypes":["java.lang.Object","long","long"] },
{"name":"putObject","parameterTypes":["java.lang.Object","long","java.lang.Object"] }
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_binary")

licenses(["notice"])

package(default_visibility = ["//examples/src:__subpackages__"])

kt_jvm_binary(
name = "hello_world_client",
srcs = ["HelloWorldClient.kt"],
main_class = "io.grpc.examples.helloworld.HelloWorldClientKt",
deps = [
"//examples/protos/src/main/proto/io/grpc/examples/helloworld:hello_world_kt_grpc",
"@io_grpc_grpc_java//netty",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.grpc.examples.helloworld

import io.grpc.ManagedChannel
import io.grpc.ManagedChannelBuilder
import io.grpc.examples.helloworld.GreeterGrpcKt.GreeterCoroutineStub
import java.io.Closeable
import java.util.concurrent.TimeUnit

class HelloWorldClient(private val channel: ManagedChannel) : Closeable {
private val stub: GreeterCoroutineStub = GreeterCoroutineStub(channel)

suspend fun greet(name: String) {
val request = HelloRequest.newBuilder().setName(name).build()
val response = stub.sayHello(request)
println("Received: ${response.message}")
}

override fun close() {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS)
}
}

/**
* Greeter, uses first argument as name to greet if present;
* greets "world" otherwise.
*/
suspend fun main(args: Array<String>) {
val port = System.getenv("PORT")?.toInt() ?: 50051

val channel = ManagedChannelBuilder.forAddress("localhost", port).usePlaintext().build()

val client = HelloWorldClient(channel)

val user = args.singleOrNull() ?: "world"
client.greet(user)
}
6 changes: 3 additions & 3 deletions examples/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
rootProject.name = "grpc-kotlin-examples"

// when running the assemble task, ignore the android subproject
// when running the assemble task, ignore the android & graalvm related subprojects
if (startParameter.taskRequests.find { it.args.contains("assemble") } == null) {
include("protos", "stub", "client", "server", "stub-lite", "android")
include("protos", "stub", "stub-lite", "client", "native-client", "server", "stub-android", "android")
} else {
include("protos", "stub", "client", "server")
include("protos", "stub", "server")
}

pluginManagement {
Expand Down
68 changes: 68 additions & 0 deletions examples/stub-android/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import com.google.protobuf.gradle.generateProtoTasks
import com.google.protobuf.gradle.id
import com.google.protobuf.gradle.plugins
import com.google.protobuf.gradle.protobuf
import com.google.protobuf.gradle.protoc

plugins {
id("com.android.library")
kotlin("android")
id("com.google.protobuf")
}

dependencies {
protobuf(project(":protos"))

implementation(kotlin("stdlib"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8")
implementation("javax.annotation:javax.annotation-api:1.3.2")

api("com.google.protobuf:protobuf-javalite:${rootProject.ext["protobufVersion"]}")
api("io.grpc:grpc-protobuf-lite:${rootProject.ext["grpcVersion"]}")

// todo: I think we should be able to just include this:
// api("io.grpc:grpc-kotlin-stub-lite:${rootProject.ext["grpcKotlinVersion"]}")
// but it doesn't pull transitives correctly

api("io.grpc:grpc-stub:${rootProject.ext["grpcVersion"]}")
api("io.grpc:grpc-kotlin-stub:${rootProject.ext["grpcKotlinVersion"]}") {
exclude("io.grpc", "grpc-protobuf")
}
}

android {
compileSdkVersion(30)
buildToolsVersion = "30.0.2"
}

protobuf {
protoc {
artifact = "com.google.protobuf:protoc:${rootProject.ext["protobufVersion"]}"
}
plugins {
id("java") {
artifact = "io.grpc:protoc-gen-grpc-java:${rootProject.ext["grpcVersion"]}"
}
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:${rootProject.ext["grpcVersion"]}"
}
id("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:${rootProject.ext["grpcKotlinVersion"]}:jdk7@jar"
}
}
generateProtoTasks {
all().forEach {
it.plugins {
id("java") {
option("lite")
}
id("grpc") {
option("lite")
}
id("grpckt") {
option("lite")
}
}
}
}
}
19 changes: 8 additions & 11 deletions examples/stub-lite/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import com.google.protobuf.gradle.protobuf
import com.google.protobuf.gradle.protoc

plugins {
id("com.android.library")
kotlin("android")
kotlin("jvm")
id("com.google.protobuf")
}

dependencies {
protobuf(project(":protos"))

implementation(kotlin("stdlib"))
implementation(kotlin("stdlib-jdk8"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8")
implementation("javax.annotation:javax.annotation-api:1.3.2")

Expand All @@ -30,19 +29,15 @@ dependencies {
}
}

android {
compileSdkVersion(30)
buildToolsVersion = "30.0.2"
java {
sourceCompatibility = JavaVersion.VERSION_1_8
}

protobuf {
protoc {
artifact = "com.google.protobuf:protoc:${rootProject.ext["protobufVersion"]}"
}
plugins {
id("java") {
artifact = "io.grpc:protoc-gen-grpc-java:${rootProject.ext["grpcVersion"]}"
}
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:${rootProject.ext["grpcVersion"]}"
}
Expand All @@ -52,10 +47,12 @@ protobuf {
}
generateProtoTasks {
all().forEach {
it.plugins {
id("java") {
it.builtins {
named("java") {
option("lite")
}
}
it.plugins {
id("grpc") {
option("lite")
}
Expand Down
3 changes: 1 addition & 2 deletions examples/stub/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import com.google.protobuf.gradle.generateProtoTasks
import com.google.protobuf.gradle.id
import com.google.protobuf.gradle.ofSourceSet
import com.google.protobuf.gradle.plugins
import com.google.protobuf.gradle.protobuf
import com.google.protobuf.gradle.protoc
Expand Down Expand Up @@ -40,7 +39,7 @@ protobuf {
}
}
generateProtoTasks {
ofSourceSet("main").forEach {
all().forEach {
it.plugins {
id("grpc")
id("grpckt")
Expand Down
Loading

0 comments on commit 6c6078c

Please sign in to comment.