Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Nick Hudkins
@nickhudkins
Yeah :( I was looking at it now, creating a bit of a test case
@dispalt the question I have is... can deriveInputObjectType, ensure that the proper (encoding / decoding) implicits are in scope along with the graphql type
Nick Hudkins
@nickhudkins
As time has gone on, I know many folks who maybe used to use Sangria, no longer do. I was curious if we could get a quick list of "Companies using Sangria at scale" If anyone here is using it in production at work (and you can share) I'd love to collect a list!
Yann Simon
@yanns
Hi, I gave a talk about GraphQL that you might find interesting: https://www.youtube.com/watch?v=Y4aP-ryulgQ&t=489s
Srepfler Srdan
@schrepfler
as any project, it would be good if there's a leadership with a clear roadmap ahead. What differentiates Sangria from the other implementations, what will keep it relevant in time etc.
Yann Simon
@yanns
@schrepfler I agree with you. As I wrote in https://github.com/sangria-graphql/sangria/issues/446#issuecomment-623075358, I'm not the one who can do it. I don't have enough time for this.
@nickhudkins invested a lot of time recently. Thanks to him! If you want to join, you are welcome.
Tim Rourke
@timrourke
is there a good way to deal with errors in sangria that doesn't involve throwing and catching exceptions? my server uses Either[SomeErrorType, SomeResourceType] to constrain the error channel and keep it typed, and there are some errors i would want to handily lazily instead of eagerly
(also totally unrelated to that, is there a sensible way to provide a query i am executing a database transaction? this would be especially important to me for mutation queries, because i need to treat writes as atomic and roll back a transaction if any one DB operation fails during a write. is this kind of use case even common in graphql-land?)
er, is the thing to do to provide a custom context of some kind?
Tim Rourke
@timrourke
ok, figured both of the above q's out
Tim Rourke
@timrourke
for anyone playing along at home, the solution is to define a custom context object containing whatever DAOs/repositories/thingies that get stuff from the DB. i feel a little icky sticking a live database transaction object into a case class as a field, but it works
and for serializing exceptions, you can implement a custom exception handler to extract relevant data for an exception thrown for a given field. would be nice to avoid throw but not a big deal at this external layer of the application
Nick Hudkins
@nickhudkins
Hey @timrourke you should checkout Alternative Execution Scheme https://sangria-graphql.github.io/learn/#alternative-execution-scheme
DeliveryScheme.Either will allow you to handle QUERY parsing as an Either as well. Hoping this helps point you into the "sangria" way to handle this
Nick Hudkins
@nickhudkins
as for your db question, the pattern I have used is to create an execution and mutation context that i put in... context. the context is created per HTTP request, providing a SHARED read connection for any DB executions and a unique transaction for any mutation. the connection itself is created per HTTP request as well, pulled from a pool. This lets me handle transaction rollback within a wcWrite function provided by a WithWriteConnection trait that wraps all of my DB operations and provides the transaction to be used, with any failures resulting in automatic rollback, or committing on success
Yann Simon
@yanns
Hi all. We will remove support for scala 2.11 and jvm < 1.8: https://github.com/sangria-graphql/sangria/issues/523#issuecomment-739152466
It's still time to react if you are impacted by this plan.
Binh Nguyen
@ngbinh
ok with it. There is not much excuse to not moving away from 2.11
Yann Simon
@yanns
Hi, if you want to help, you can open PR to use github actions instead of travis CI. We need that on all repositories.
I've migrated Sangria (sangria-graphql/sangria#547) and macro-visit (sangria-graphql/macro-visit#28 and https://github.com/sangria-graphql/macro-visit/pull/29)
Sagar Jadhav
@SagarJa07481451_twitter
Is there a way to not use case classes to model object types in sangria. Using Graphql-Java , we can externalize the schema and pass it at runtime. How can we achieve this in graphQL-scala?
Yann Simon
@yanns
It's possible to derive the GraphQL types from case classes, but it is also possible to write the GraphQL types per hand: https://sangria-graphql.github.io/learn/#schema-definition
Sagar Jadhav
@SagarJa07481451_twitter
@yanns I get "Schema was materialized and cannot be used for any queries except introspection queries." error when I parse it and try to execute.
Yann Simon
@yanns
Strange we are using this approach on production without any issues.
Sagar Jadhav
@SagarJa07481451_twitter
@yanns Can you please list down high level steps that you follow. Maybe I am missing some step.
Yann Simon
@yanns
@SagarJa07481451_twitter we are using the Executor.execute, like in https://github.com/sangria-graphql/sangria-akka-http-example/blob/master/src/main/scala/Server.scala#L33
Sagar Jadhav
@SagarJa07481451_twitter
@yanns This does not work for me. Are you also reading the schema from an external schema.graphql file ? In the above link, schema is not read from an external file. It is created through the code.
Dave Handy
@dave-handy
hi @yanns ! I see you are also working on migrating to github actions... have you tried publishing a new signed version yet? I'm having an issue with the action not seeing PGP_SECRET
Yann Simon
@yanns
@SagarJa07481451_twitter no I don't use an external schema file. Sorry I might have misunderstood you. I thought you want to avoid using the macro derivation to generate the GraphQL schema.
@dave-handy the publishing with github actions is disabled for now: sangria-graphql/macro-visit#29
This would requite much more work.
5 replies
Yann Simon
@yanns
https://github.com/sangria-graphql/sangria-slowlog is now using github actions & auto-formatting
Yann Simon
@yanns
same now for https://github.com/sangria-graphql/sangria-msgpack. If you want to help, you can have a look at the changed that were necessary, and apply them to other repositories.
Yann Simon
@yanns
Binh Nguyen
@ngbinh
:clap:
Philipp Zerelles
@pz_mxu_gitlab
Hello, Can someone maybe help me? I create a schema from AST and in the AST I use a custom scalar "DateTime". Now I also created a ScalarType for that type and use ScalarResolver to assign it to the scalar defined in the AST. But for outputs with the custom type, I get an exception that String cannot be cast to LocalDateTime and my custom "coerceOutput" is not called at all. What am I missing?
Yann Simon
@yanns
An example of a ScalarType we are using:
  implicit val DateTimeType = ScalarType[DateTime](
    "DateTime",
    description = Some(
      "DateTime is a scalar value that represents an [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) formatted date and time."),
    coerceOutput = (date, _) => ISODateTimeFormat.dateTime().print(date),
    coerceUserInput = {
      case s: String =>
        parseDateTime(s) match {
          case scala.util.Success(date) => Right(date)
          case scala.util.Failure(_) => Left(DateCoercionViolation)
        }
      case _ => Left(DateCoercionViolation)
    },
    coerceInput = {
      case ast.StringValue(s, _, _, _, _) =>
        parseDateTime(s) match {
          case scala.util.Success(date) => Right(date)
          case scala.util.Failure(_) => Left(DateCoercionViolation)
        }
      case _ => Left(DateCoercionViolation)
    }
  )
abhishekvaidprophecy
@abhishekvaidprophecy

I'm new to Sangria. I need to create an Argument which is of custom object type.

val authorizationContextArg: Argument[DefaultInput] = Argument(
    "authorizationContext",
    InputObjectType(
      "AuthorizationContext",
      "Define the Auhorization Context of the Search",
      fields = List(
        InputField("authEntityKind", StringType, description = "Auth Entity Kind"),
        InputField("authEntityId",   StringType, description = "Auth Entity Id")
      )
    )
  )

Now, in my resolver, I'm accessing this argument like this ?

val arg             = ctx.arg(authorizationContextArg)

My query is as to how do I now access both the authEntityKind and authEntityId from arg ?

macchiatow
@macchiatow
does anyone know why resolve function of DynamicDirectiveResolver never called where directive define on Interface or Type (this is not a case with field), so far I use middleware as workaround.
TrasheRacer
@TrasheRacer

Hi everyone, first time poster but long time Sangria user,

Our team has identified what appears to be a bug in sangria.Schema.

Looks like there is some side-effect causing Schema() to throw an NPE when it calls collectTypes(). We haven't yet figured out where it's coming from - possibly something to do with lazy val usage. Any advice on fixing this would be appreciated!

I can provide a unit test which reproduces the bug on request.
Cheers! Jake

Nick Hudkins
@nickhudkins
Hey @TrasheRacer yes please, a simple test case would be wonderful!
TrasheRacer
@TrasheRacer
Here's the test case:
import org.scalatest.funsuite.AnyFunSuite
import sangria.marshalling.{CoercedScalaResultMarshaller, FromInput, ResultMarshaller}
import sangria.schema.{Argument, Field, InputField, InputObjectType, LongType, ObjectType, Schema, fields}

/**
  * Below are simplified versions of the classes, objects and traits used in the real implementation of our schema,
  * to reproduce the bug with minimal complexity.
  */
object SchemaInitTest {
  case class ProjectData(name: String = "empty_project", activities: Seq[ActivityRef] = Seq.empty)
  case class Project(projectData: ProjectData)
  case class QueryableProject(project: Project)
  object QueryableProject {
    val empty: QueryableProject = QueryableProject(Project(ProjectData()))
  }
  trait ProjectsContext[T <: ProjectsContext[T]]
  trait POWContext extends ProjectsContext[POWContext]
  case class ProjectValue[T](project: QueryableProject, value: T)
  object ProjectValue {
    def ofActivityRef(queryableProject: QueryableProject, activityRef: ActivityRef): ProjectValue[ActivityRef] =
      ProjectValue(queryableProject, activityRef)
  }

  case class ActivityRef(id: Long)
  object ActivityRef {
    implicit val fromInput: FromInput[ActivityRef] = new FromInput[ActivityRef] {
      override val marshaller: ResultMarshaller = CoercedScalaResultMarshaller.default
      override def fromResult(node: marshaller.Node): ActivityRef = ActivityRef(3456L)
    }

    // TODO: FIND OUT WHY OUR BUG DISAPPEARS WHEN THIS IS CHANGED INTO A LAZY VAL
    val arg: Argument[ActivityRef] = Argument("activityRef", inputType)
  }

  val inputType: InputObjectType[ActivityRef] =
    InputObjectType[ActivityRef](
      "ActivityRefInput",
      fields = List(
        InputField("id", LongType)
      )
    )

  // TODO: FIND OUT WHY NPE DISAPPEARS WHEN THIS IS MADE LAZY
  val activityRefArgs = ActivityRef.arg :: Nil
}

class SchemaInitTest extends AnyFunSuite {

  import SchemaInitTest._

  test("ObjectType() and Schema() should not have any kind of weird side effects when sharing an argument") {
    // Do something which (apparently) mutates global state somewhere in sangria
    ObjectType(
      "Activity",
      fields[Unit, QueryableProject](
        Field(
          "activityRef",
          LongType,
          arguments = ActivityRef.arg :: Nil,
          resolve = _ => 123L // The resolve function is irrelevant to this test
        )
      )
    )

    val query =       ObjectType(
      name = "Query",
      fields = fields[POWContext, Unit](
        Field(
          name = "project",
          fieldType = ObjectType[Unit, QueryableProject](
            name = "Project",
            fields = fields[Unit, QueryableProject](
              Field(
                "activityRef",
                LongType,
                arguments = activityRefArgs,
                resolve = _ => 123L // The resolve function is irrelevant to this test
              )
            )
          ),
          resolve = _ => QueryableProject.empty // The resolve function is irrelevant to this test
        )
      )
    )


    // Create a Schema which **shouldn't** access any global mutable state
    Schema(query)

    // No exception should be thrown...
    assert(true)
  }
}
I would have created a Scalafiddle, but it looks like they don't support Sangria as a library...
TrasheRacer
@TrasheRacer
I went ahead and put this test in my fork of the sangria-playground repo
https://github.com/TrasheRacer/sangria-playground/tree/bug-in-schema-init
image.png
TrasheRacer
@TrasheRacer


java.lang.NullPointerException was thrown.
java.lang.NullPointerException
    at sangria.schema.Schema.$anonfun$types$4(Schema.scala:848)
    at scala.collection.LinearSeqOps.foldLeft(LinearSeq.scala:168)
    at scala.collection.LinearSeqOps.foldLeft$(LinearSeq.scala:164)
    at scala.collection.immutable.List.foldLeft(List.scala:79)
    at sangria.schema.Schema.$anonfun$types$3(Schema.scala:847)
    at scala.collection.IterableOnceOps.foldLeft(IterableOnce.scala:638)
    at scala.collection.IterableOnceOps.foldLeft$(IterableOnce.scala:634)
    at scala.collection.AbstractIterable.foldLeft(Iterable.scala:920)
    at sangria.schema.Schema.collectTypes$1(Schema.scala:845)
    at sangria.schema.Schema.$anonfun$types$3(Schema.scala:847)
    at scala.collection.IterableOnceOps.foldLeft(IterableOnce.scala:638)
    at scala.collection.IterableOnceOps.foldLeft$(IterableOnce.scala:634)
    at scala.collection.AbstractIterable.foldLeft(Iterable.scala:920)
    at sangria.schema.Schema.collectTypes$1(Schema.scala:845)
    at sangria.schema.Schema.types$lzycompute(Schema.scala:873)
    at sangria.schema.Schema.types(Schema.scala:787)
    at sangria.schema.Schema.inputTypes$lzycompute(Schema.scala:885)
    at sangria.schema.Schema.inputTypes(Schema.scala:885)
    at sangria.schema.DefaultValuesValidationRule$.validate(SchemaValidationRule.scala:61)
    at sangria.schema.SchemaValidationRule$.$anonfun$validate$1(SchemaValidationRule.scala:37)
    at scala.collection.immutable.List.flatMap(List.scala:293)
    at sangria.schema.SchemaValidationRule$.validate(SchemaValidationRule.scala:37)
    at sangria.schema.SchemaValidationRule$.validateWithException(SchemaValidationRule.scala:40)
    at sangria.schema.Schema.<init>(Schema.scala:939)
    at SchemaSpec.$anonfun$new$4(SchemaSpec.scala:162)
    at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
    at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
    at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
    at org.scalatest.Transformer.apply(Transformer.scala:22)
    at org.scalatest.Transformer.apply(Transformer.scala:20)
    at org.scalatest.wordspec.AnyWordSpecLike$$anon$3.apply(AnyWordSpecLike.scala:1076)
    at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
    at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)
    at org.scalatest.wordspec.AnyWordSpec.withFixture(AnyWordSpec.scala:1879)
    at org.scalatest.wordspec.AnyWordSpecLike.invokeWithFixture$1(AnyWordSpecLike.scala:1074)
    at org.scalatest.wordspec.AnyWordSpecLike.$anonfun$runTest$1(AnyWordSpecLike.scala:1086)
    at org.scalatest.SuperEngine.runTestImpl(Engine.scala:306)
    at org.scalatest.wordspec.AnyWordSpecLike.runTest(AnyWordSpecLike.scala:1086)
    at org.scalatest.wordspec.AnyWordSpecLike.runTest$(AnyWordSpecLike.scala:1068)
    at org.scalatest.wordspec.AnyWordSpec.runTest(AnyWordSpec.scala:1879)
    at org.scalatest.wordspec.AnyWordSpecLike.$anonfun$runTests$1(AnyWordSpecLike.scala:1145)
    at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:413)
    at scala.collection.immutable.List.foreach(List.scala:333)
    at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:401)
    at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:390)
    at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:427)
    at scala.collection.immutable.List.foreach(List.scala:333)
    at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:401)
    at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:396)
    at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:475)
    at org.scalatest.wordspec.AnyWordSpecLike.runTests(AnyWordSpecLike.scala:1145)
    at org.scalatest.wordspec.AnyWordSpecLike.runTests$(AnyWordSpecLike.scala:1144)
    at org.scalatest.wordspec.AnyWordSpec.runTests(AnyWordSpec.scala:1879)
    at org.scalatest.Suite.run(Suite.scala:1112)
    at org.scalatest.Suite.run$(Suite.scala:1094)
    at org.scalatest.wordspec.AnyWordSpec.org$scalatest$wordspec$AnyWordSpecLike$$super$run(AnyWordSpec.scala:1879)
    at org.scalatest.wordspec.AnyWordSpecLike.$anonfun$run$1(AnyWordSpecLike.scala:1190)
    at org.scalatest.SuperEngine.runImpl(Engine.scala:535)
    at org.scalatest.wordspec.AnyWordSpecLi
Nick Hudkins
@nickhudkins
@TrasheRacer can you give v2.0.0 of sangria a try? I can take a look at this in a bit, but I just want to quick confirm that it wasn't recently introduced
Nick Hudkins
@nickhudkins
ah nevermind, @TrasheRacer looks like you've got a Scala issue not a Sangria bug... let me quick show you what's going on
// Start writing your ScalaFiddle code here
object SchemaInitTest {
  object ActivityRef {
    val arg = someOtherThing
  }
  // ActivityRef.arg references something that has yet to be initialized.
  println(ActivityRef.arg)

  // Go ahead and make this eager (not lazy), and you'll get `null`
  lazy val someOtherThing = "Foo"
}

val _ = SchemaInitTest
If you plan to reference vals that are declared after your usage, that val must be lazy, or it needs to have been initialized by the time you reference it
You can fix this 1 of two ways, either make the val lazy... or move the declaration like so:
// Start writing your ScalaFiddle code here
object SchemaInitTest {
  val someOtherThing = "Foo"
  object ActivityRef {
    val arg = someOtherThing
  }
  println(ActivityRef.arg)

}

val _ = SchemaInitTest