You are viewing the preview version of this book
Click here for the full version.

Data sources

In GraphQL, a resolver is a function that gets the arguments and the context for a field and returns a value. This is a generic concept and applies to all GraphQL servers. But how this function is implemented, such as what language it can be written in, can be different between servers.

Field resolving in GraphQL

In AppSync, a resolver is broken into three parts:

  • the request mapping template
  • the data source
  • and the response mapping template

The request mapping template converts the GraphQL context into a format suitable for the data source. Then the data source interacts with some external service, such as a database, a Lambda function, or sends an HTTP request. Then the response mapping template gets the result of the data source and converts it into a format suitable for the resolver's result.

Field resolving in AppSync

The mapping templates are written in Velocity Template Language (VTL), which is a Java-based templating language. Since both the data source's input format and the resolver's result are JSON, the templates need to produce a valid JSON file.

Note

Velocity is a general-purpose template language. It gets some arguments, in the case of AppSync the resolver context, and returns text. For an AppSync resolver, this text needs to be parseable to JSON.

For example, to get an item from a DynamoDB table, the request mapping template for the groupById resolver can use the id argument:

{
  "version": "2018-05-29",
  "operation": "GetItem",
  "key": {
    "id": {"S": $util.toJson($ctx.args.id)}
  }
}

When a query comes for this field, such as this one:

query MyQuery {
  groupById(id: "group1") {
    id
    name
  }
}

The resulting JSON will be:

{
  "version": "2018-05-29",
  "operation": "GetItem",
  "key": {
    "id": {"S": "group1"}
  }
}

The DynamoDB data source knows how to process this input, and fetches an item from the configured table with the id of group1.

Then the response mapping template needs to convert the item to the resolver's result format:

#if($ctx.error)
  $util.error($ctx.error.message, $ctx.error.type)
#end
$util.toJson($ctx.result)

Let's say the item is a JSON with the id and a name property:

{
  "id": "group1",
  "name": "Group 1"
}

The response mapping template gets the above JSON as the $ctx.result and returns this JSON:

{
  "id": "group1",
  "name": "Group 1"
}

Which is in a format that the result type can use.

Running the resolver
AppSync resolver flow

Why AppSync implements this separation?

Usually, data sources have parameters that the resolver might not know, such as the DynamoDB table. In the above example, only the id of the item is defined, but not the table name. That comes from the data source config.

There is more, but you've reached the end of this preview
Read this and all other chapters in full and get lifetime access to:
  • all future updates
  • full web-based access
  • PDF and Epub versions