├── .gitignore ├── examples └── src │ └── main │ ├── protobuf │ └── hello_world.proto │ └── scala │ └── HelloWorld.scala ├── library └── src │ └── main │ └── scala │ ├── Channel.scala │ ├── Server.scala │ └── package.scala └── project ├── GrpcBuild.scala └── plugins.sbt /.gitignore: -------------------------------------------------------------------------------- 1 | project/target 2 | target 3 | dist 4 | -------------------------------------------------------------------------------- /examples/src/main/protobuf/hello_world.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | syntax = "proto3"; 31 | 32 | package helloworld; 33 | 34 | option java_multiple_files = true; 35 | option java_package = "io.grpc.examples.helloworld"; 36 | option java_outer_classname = "HelloWorldProto"; 37 | 38 | // The greeting service definition. 39 | service Greeter { 40 | // Sends a greeting 41 | rpc SayHello (HelloRequest) returns (HelloResponse) {} 42 | } 43 | 44 | // The request message containing the user's name. 45 | message HelloRequest { 46 | string name = 1; 47 | } 48 | 49 | // The response message containing the greetings 50 | message HelloResponse { 51 | string message = 1; 52 | } 53 | -------------------------------------------------------------------------------- /examples/src/main/scala/HelloWorld.scala: -------------------------------------------------------------------------------- 1 | package io.grpc.scala 2 | package examples 3 | 4 | import scala.concurrent.ExecutionContext.Implicits.global 5 | import io.grpc.stub.StreamObserver 6 | 7 | import io.grpc.examples.helloworld.{GreeterGrpc, HelloRequest, HelloResponse} 8 | 9 | object HelloWorldClient { 10 | def main(args: Array[String]) { 11 | val channel = Channel("localhost", 50051) 12 | val stub = GreeterGrpc.newFutureStub(channel) 13 | val request = HelloRequest.newBuilder().setName(args.headOption.getOrElse("Giskard")).build() 14 | 15 | stub.sayHello(request).asFuture.map { response => 16 | println(response.getMessage) 17 | }.onComplete { _ => 18 | channel.shutdown()//.awaitTerminated(5, TimeUnit.SECONDS) 19 | } 20 | } 21 | } 22 | 23 | object HelloWorldServer { 24 | object Greeter extends GreeterGrpc.Greeter { 25 | override def sayHello(request: HelloRequest, observer: StreamObserver[HelloResponse]) { 26 | val response = HelloResponse.newBuilder().setMessage(s"Hello ${request.getName}").build() 27 | observer.onValue(response) 28 | observer.onCompleted 29 | } 30 | } 31 | 32 | def main(args: Array[String]) { 33 | val server = Server(50051, List(GreeterGrpc.bindService(Greeter))) 34 | server.start 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /library/src/main/scala/Channel.scala: -------------------------------------------------------------------------------- 1 | package io.grpc 2 | package scala 3 | 4 | import io.grpc.transport.netty.{NegotiationType, NettyChannelBuilder} 5 | 6 | object Channel { 7 | def apply(host: String, port: Int): ChannelImpl = 8 | NettyChannelBuilder 9 | .forAddress(host, port) 10 | .negotiationType(NegotiationType.PLAINTEXT) 11 | .build() 12 | } 13 | -------------------------------------------------------------------------------- /library/src/main/scala/Server.scala: -------------------------------------------------------------------------------- 1 | package io.grpc 2 | package scala 3 | 4 | import io.grpc.transport.netty.{NettyServerBuilder} 5 | 6 | object Server { 7 | def apply(port: Int, services: List[ServerServiceDefinition]): ServerImpl = 8 | services.foldLeft(NettyServerBuilder.forPort(port))(_.addService(_)).build() 9 | } 10 | 11 | -------------------------------------------------------------------------------- /library/src/main/scala/package.scala: -------------------------------------------------------------------------------- 1 | package io.grpc 2 | 3 | import _root_.scala.concurrent.{Future, Promise} 4 | import com.google.common.util.concurrent.{Futures, FutureCallback, ListenableFuture} 5 | 6 | package object scala { 7 | implicit class RichListenableFuture[A](self: ListenableFuture[A]) { 8 | def asFuture: Future[A] = { 9 | val p = Promise[A]() 10 | Futures.addCallback(self, new FutureCallback[A] { 11 | def onFailure(t: Throwable): Unit = p.failure(t) 12 | def onSuccess(result: A): Unit = p.success(result) 13 | }) 14 | p.future 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /project/GrpcBuild.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | import Keys._ 3 | 4 | import sbtprotobuf.ProtobufPlugin._ 5 | 6 | object ProjectBuild extends Build { 7 | 8 | val grpcVersion = "0.7.1" 9 | 10 | def mkProject(module: String, name: String) = 11 | Project(name, file(module), settings = Seq( 12 | organization := "io.grpc", 13 | // TODO Enable after first stable release 14 | // version := (s"git describe --long --tags --match v${grpcVersion}" !!).trim.drop(1), 15 | version := (s"git describe --long --tags --match v0.0" !!).trim.drop(1), 16 | scalaVersion := "2.11.6", 17 | scalacOptions ++= Seq("-feature","-deprecation", "-Xlint") 18 | )) 19 | 20 | lazy val root = Project("root", file(".")) 21 | .aggregate(library, examples) 22 | 23 | lazy val library = mkProject("library", "grpc-scala") 24 | .settings(libraryDependencies += "io.grpc" % "grpc-all" % grpcVersion) 25 | 26 | lazy val examples = mkProject("examples", "grpc-scala-examples").dependsOn(library) 27 | .settings(protobufSettings:_*) 28 | .settings( 29 | version in protobufConfig := "3.0.0-alpha-3.1", 30 | protocOptions in protobufConfig ++= Seq( 31 | "--plugin=protoc-gen-java_rpc=/usr/local/bin/protoc-gen-grpc-java", 32 | "--java_rpc_out=examples/target/scala-2.11/src_managed/main/compiled_protobuf" 33 | ) 34 | ) 35 | } 36 | 37 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.github.gseitz" % "sbt-protobuf" % "0.4.0") 2 | --------------------------------------------------------------------------------