2
votes

I'm new to GraphQL and I'm trying to figure out how can I programmatically send a GraphQL POST query that I have implemented in a separate micro-service.

In my main application I'm using Java + Spring REST Template to send the query while attaching the POST Body as a String GraphQL query e.g.

String body = "query MyLearner {learner(id: 1) {lastName givenName} learners { givenName }}";

I can receive the query in my play-scala micro-service but can't parse the JSON.

Receiving method:

def graphqlBody(tenant: Int) = Action.async(parse.json) { request ⇒
    val query = (request.body \ "query").as[String]
    val operation = (request.body \ "operationName").asOpt[String]

    val variables = (request.body \ "variables").toOption.flatMap {
      case JsString(vars) ⇒ Some(parseVariables(vars))
      case obj: JsObject ⇒ Some(obj)
      case _ ⇒ None
    }

    executeQuery(query, variables, operation)
}

Note I've basically tried to implement the GraphQL Sangria code with my domain model so it might look similar to people. sangria

Im getting an error on line 1 of the method while parsing the JSON I'm assuming it's because the JSON body coming in isn't valid JSON because it's in GraphQL format but this is what is used and works for Sangria so not sure why it wouldn't work here.

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[JsResultException: JsResultException(errors:List((,List(ValidationError(List("query MyLearner {learner(id: 1) {lastName givenName} learners { givenName }}" is not an object),WrappedArray())))))]]

Screenshot from debug of JSON received JSON Body:enter image description here

Thanks to @Ra Ka guidance I was able to come out with the correct query please see below for answer:

{  
   "variables":{  
      "id":1
   },
   "operationName":"MyLearner",
   "query":"query MyLearner($id: Long!) {learner(id: $id) {misId givenName}}"
}
1
what is the body of the request that the method receives ? As you said it seems like play fails to decode your json - vdebergue
I've updated the question with a screenshot of the JSON Body. - Schokea

1 Answers

3
votes

You are providing graphql query in wrong format. The actual graphql query is not a valid JSON format and you are providing in that format and hence you will definitely get invalid JSON exception. Therefore you need to provide graphql query as value instead of body. As your receiving method is parsing query, opertionName and variables field, you need to provide request body in following format:

{
    "variables": {
        "id": "123"
    },
    "operationName":"MyLearner",
    "query": "query MyLearner {learner($id: String) {lastName givenName} learners { givenName }}"
}

If you want to learn more about query such as variables and operationName please refer here

In addition, when I learned graphql, I have trouble understanding operationName and if you know about it, ignore this. OperationName is used to to select from multiple query that you already have in query field. For example:

{
    "variables": {
        "id": "123"
    },
    "operationName":"Query1" or "Query2" //provide either of query to get data so that you can write single query for all data fetching and provide operationName for each type of data,
    "query": "query Query1 {learner($id: String) {lastName givenName} learners { givenName }} query Query2 {learner($id: String) learners { givenName }}"
    }