Skip to content

Instantly share code, notes, and snippets.

@anotherhale
Last active September 22, 2018 05:38
Show Gist options
  • Save anotherhale/e02da8e48b2827b5139d5bacbfc2ab53 to your computer and use it in GitHub Desktop.
Save anotherhale/e02da8e48b2827b5139d5bacbfc2ab53 to your computer and use it in GitHub Desktop.
Attempt to create Sangria API without derived types to experiment with interfacing with POJOs instead of Scala case classes.
// Author.java
class Author {
private String name;
private int publishedBooks;
Author(String _name , int _publishedBooks) {
name = _name
publishedBooks = _publishedBooks
}
String getName() {return name;}
void setName(String _name){ this.name = _name; }
int getPublishedBooks() {return publishedBooks;}
void setPublishedBooks(int _publishedBooks) {this.publishedBooks = _publishedBooks;}
}
// Book.java
class Book {
private String title;
private java.util.List<Author> authors;
Book(String _title , java.util.List<Author> _authors) {
title = _title
authors = _authors
}
String getTitle() {return title;}
void setTitle(String _title){ this.title = _title; }
java.util.List<Author> getAuthors() {return authors;}
void setAuthors(java.util.List<Author> _authors) {this.authors = _authors;}
}
// Schema.scala
import sangria.schema._
import sangria.execution._
import sangria.macros._
import sangria.macros.derive._
import sangria.marshalling.circe._
import enumeratum._
import io.circe.generic.auto._
import io.circe.Json
import io.circe.syntax._
import scala.collection.JavaConverters
import scala.concurrent.ExecutionContext.Implicits.global
object SchemaDefinition {
class Repo {
private var storedBook: Option[Book] = None
def saveBook(book: Book): Unit = {
storedBook = Some(book)
}
def loadBook(): Option[Book] = storedBook
}
implicit val decodeAuthor: Decoder[Author] = new Decoder[Author] {
final def apply(c: HCursor): Decoder.Result[Author] =
for {
name <- c.downField("name").as[String]
publishedBooks <- c.downField("publishedBooks").as[Int]
} yield {
new Author(name, publishedBooks)
}
}
implicit val encodeBook: Encoder[Book] = new Encoder[Book] {
final def apply(b: Book): Json = Json.obj(
("title", Json.fromString(b.getTitle)),
("authors", Json.fromValues(JavaConverters.asScalaIteratorConverter(b.getAuthors.iterator()).asScala.toSeq.map(a=>encodeAuthor(a))))
)
}
implicit val decodeBook: Decoder[Book] = new Decoder[Book] {
final def apply(c: HCursor): Decoder.Result[Book] =
for {
title <- c.downField("title").as[String]
authors <- c.downField("authors").as[Seq[Author]]
} yield {
new Book(title, JavaConverters.seqAsJavaList(authors))
}
}
implicit val AuthorInputType = InputObjectType[Author]("AuthorInput", List(
InputField("name", StringType),
InputField("publishedBooks", IntType, defaultValue = 0)))
implicit lazy val BookInputType = InputObjectType[Book]("BookInput", List(
InputField("title", StringType),
InputField("authors", ListInputType(AuthorInputType))
))
// Output objects
implicit lazy val BookType = ObjectType("Book", fields[Repo, Book](
Field("title", StringType,
resolve = _.value.getTitle),
Field("authors", ListType(AuthorType),
resolve = book => JavaConverters.asScalaIteratorConverter(book.value.getAuthors.iterator()).asScala.toSeq
)))
implicit val AuthorType = ObjectType("Author", fields[Repo, Author](
Field("name", StringType,
resolve = _.value.getName),
Field("publishedBooks", IntType,
resolve = _.value.getPublishedBooks)
))
// Schema definition
val BookArg = Argument("book", BookInputType)
val QueryType = ObjectType("Query", fields[Repo, Unit](
Field("book", OptionType(BookType), resolve = _.ctx.loadBook())))
val MutationType = ObjectType("Mutation", fields[Repo, Unit](
Field("saveBook", OptionType(BookType),
arguments = BookArg :: Nil,
resolve = c {
val book = c arg BookArg
c.ctx.saveBook(book)
book
})))
val schema = Schema(QueryType, Some(MutationType))
// Test query
val query =
gql"""
mutation {
saveBook(book: {title: "Sapiens", authors: [{name: "Yuval Noah Harari", publishedBooks: 6}]}) {
title
authors {
name
publishedBooks
}
}
}
"""
val context = new Repo
val result = Executor.execute(schema, query, context)
result.foreach(res println(res.spaces2))
// [info] Compiling 4 Scala sources and 2 Java sources to target\scala-2.12\classes ...
// [error] src\main\scala\SchemaDefinition.scala:32:34: type mismatch;
// [error] found : sangria.schema.InputObjectType[Author]
// [error] required: sangria.schema.OutputType[?]
// [error] Note: implicit lazy value BookInputType is not applicable here because it comes after the application point and it lacks an explicit result type
// [error] InputField("authors", ListType(AuthorInputType))))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment