0

We have a Scala application using Scalatra (http://scalatra.org/) as our web framework. I'm wondering if there are any good (or just any) resources out there on how to implement a GraphQL endpoint using Sangria (http://sangria-graphql.org/) and Scalatra?

I'm new to Scala and would appreciate any help to get started on this.

1 Answer 1

1

There aren't any that I know of but since Scalatra uses json4s you would use sangria's json4s marshaller .

Otherwise, if sangria could be clearer to you, here's a scala worksheet with a very simplistic example based off play + sangria - in this case you would just need to swap the json library.

The db is mocked (perhaps you use Slick?) and the http server as well but it's a simple case of swapping in the function definitions.

import sangria.ast.Document import sangria.execution.{ErrorWithResolver, Executor, QueryAnalysisError} import sangria.macros.derive.{ObjectTypeDescription, ObjectTypeName, deriveObjectType} import sangria.parser.{QueryParser, SyntaxError} import sangria.renderer.SchemaRenderer import sangria.schema.{Argument, Field, IntType, ListType, ObjectType, OptionInputType, Schema, fields} import scala.concurrent.Await import scala.concurrent.duration._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.{Failure, Success} // replace with another json lib // eg https://github.com/sangria-graphql/sangria-json4s-jackson import play.api.libs.json._ import sangria.marshalling.playJson._ case class User(name: String, age: Int, phone: Option[String]) class FakeDb { class UsersTable { def getUsers(limit: Int): List[User] = { // this would come from the db List( User("john smith", 23, None), User("Anne Schwazenbach", 45, Some("2134556")) ) } } val usersRepo = new UsersTable } object MySchema { val limitArg: Argument[Int] = Argument("first", OptionInputType(IntType), description = s"Returns the first n elements from the list.", defaultValue = 10) implicit val UsersType: ObjectType[FakeDb, User] = { deriveObjectType[FakeDb, User]( ObjectTypeName("Users"), ObjectTypeDescription("Users in the system") ) } private val Query: ObjectType[FakeDb, Unit] = ObjectType[FakeDb, Unit]( "Query", fields[FakeDb, Unit]( Field("users", ListType(UsersType), arguments = limitArg :: Nil, resolve = c => c.ctx.usersRepo.getUsers(c.arg(limitArg)) ) )) val theSchema: Schema[FakeDb, Unit] = Schema(Query) } object HttpServer { def get(): String = { // Http GET SchemaRenderer.renderSchema(MySchema.theSchema) } def post(query: String): Future[JsValue] = { // Http POST val variables = None val operation = None QueryParser.parse(query) match { case Success(q) => executeQuery(q, variables, operation) case Failure(error: SyntaxError) => Future.successful(Json.obj("error" -> error.getMessage)) case Failure(error: Throwable) => Future.successful(Json.obj("error" -> error.getMessage)) } } private def executeQuery(queryAst: Document, vars: Option[JsValue], operation: Option[String]): Future[JsValue] = { val schema: Schema[FakeDb, Unit] = MySchema.theSchema Executor.execute[FakeDb, Unit, JsValue](schema, queryAst, new FakeDb, operationName = operation, variables=vars.getOrElse(Json.obj())) .map((d: JsValue) => d) .recover { case error: QueryAnalysisError ⇒ Json.obj("error" -> error.getMessage) case error: ErrorWithResolver ⇒ Json.obj("error" -> error.getMessage) } } } HttpServer.get() val myquery = """ { users { name } } """ val res: JsValue = Await.result(HttpServer.post(myquery), 10.seconds) 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.