All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sttp.tapir.grpc.examples.PekkoGrpcSimpleBooksExample.scala Maven / Gradle / Ivy

The newest version!
package sttp.tapir.grpc.examples

import org.apache.pekko.actor.ActorSystem
import org.apache.pekko.grpc.GrpcClientSettings
import org.apache.pekko.http.scaladsl.Http
import cats.implicits._
import com.typesafe.config.ConfigFactory
import org.slf4j.{Logger, LoggerFactory}
import sttp.tapir._
import sttp.tapir.grpc.protobuf._
import sttp.tapir.grpc.protobuf.pbdirect._
import sttp.tapir.server.ServerEndpoint
import sttp.tapir.server.pekkogrpc.PekkoGrpcServerInterpreter
import sttp.tapir.generic.auto._
import sttp.tapir.grpc.examples.grpc_simple_books_example.gen.{
  Library => GenLibrary,
  LibraryClient => GenLibraryClient,
  AddBookMsg => GenAddBookMsg
}

import java.util.concurrent.atomic.AtomicLong
import scala.concurrent.{Await, ExecutionContext, Future}

trait Logging {
  protected val logger: Logger = LoggerFactory.getLogger(getClass.getName)
}

case class SimpleBook(id: Long, title: String, description: String)
case class AddBookMsg(title: String, description: String)

/** Descriptions of endpoints used in the example.
  */
object Endpoints {
  val addBook = endpoint
    .in("Library" / "AddBook")
    .in(grpcBody[AddBookMsg])
    .out(grpcBody[SimpleBook])

  val endpoints = List(addBook)
}

object SimpleBooksExampleServer extends Logging {

  import Endpoints._

  private val counter = new AtomicLong(0)

  def booksServerEndpoints: List[ServerEndpoint[Any, Future]] =
    List(
      addBook.serverLogic { book =>
        logger.info(s"Adding a new book [$book]")
        Future.successful(SimpleBook(counter.getAndIncrement(), book.title, book.description).asRight[Unit])
      }
    )

  def main(args: Array[String]): Unit = {
    val conf = ConfigFactory
      .parseString("pekko.http.server.preview.enable-http2 = on")
      .withFallback(ConfigFactory.defaultApplication())
    val system = ActorSystem("HelloWorld", conf)

    new ExampleGrpcServer(system).run()
  }
}

class ExampleGrpcServer(system: ActorSystem) extends Logging {
  def run(): Future[Http.ServerBinding] = {
    // Pekko boot up code
    implicit val sys: ActorSystem = system
    implicit val ec: ExecutionContext = sys.dispatcher

    val route = PekkoGrpcServerInterpreter().toRoute(SimpleBooksExampleServer.booksServerEndpoints)

    val binding = Http().newServerAt("127.0.0.1", 8080).bind(route)

    // report successful binding
    binding.foreach { binding => logger.info(s"gRPC server bound to: ${binding.localAddress}") }

    binding
  }
}

object SimpleBookExampleProtoGenerator extends App {
  ProtoSchemaGenerator.renderToFile(
    path = "grpc/examples/src/main/protobuf/simple_books_example.proto",
    packageName = "sttp.tapir.grpc.examples.grpc_simple_books_example.gen",
    endpoints = Endpoints.endpoints
  )
}

object SimpleBookExampleClient extends App with Logging {

  import scala.concurrent.duration._

  implicit val sys = ActorSystem("HelloWorldClient")
  implicit val ec = sys.dispatcher

  val client = GenLibraryClient(GrpcClientSettings.connectToServiceAt("localhost", 8080).withTls(false))
  val result = Await.result(client.addBook(GenAddBookMsg("TEST_BOOK", "TEST")), 10.second)

  logger.info(s"Result: [$result]")
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy