The GraphQL API

GraphQL is:

  • …a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.”.

    See GraphQL.org

  • …an open spec for a flexible API layer. Put GraphQL over your existing backends to build products faster than ever before…”.

    See Explore GraphQL.

  • “…a data query language and specification developed internally by Facebook in 2012 before being publicly open sourced in 2015. It provides an alternative to REST-based architectures with the purpose of increasing developer productivity and minimizing amounts of data transferred. GraphQL is used in production by hundreds of organizations of all sizes…”

    See GraphQL Foundation.

For information about the GraphQL API, see the following sections (amongst many other resources):

The GraphQL for AEM implementation is based on the standard GraphQL Java Library. See:

GraphQL Terminology

GraphQL uses the following:

See the (GraphQL.org) Introduction to GraphQL for comprehensive details, including the Best Practices.

GraphQL Query Types

With GraphQL you can perform queries to return either:

AEM provides capabilities to convert queries (both types) to Persisted Queries, that can be cached by Dispatcher and the CDN.

GraphQL Query Best Practices (Dispatcher and CDN)

The Persisted Queries are the recommended method to be used on publish instances as:

  • they are cached
  • they are managed centrally by AEM as a Cloud Service
NOTE
Usually there is no dispatcher/CDN on author, so there is no gain in using persisted queries there; apart from testing them.

GraphQL queries using POST requests are not recommended as they are not cached, so on a default instance the Dispatcher is configured to block such queries.

While GraphQL also supports GET requests, these can hit limits (for example, the length of the URL) that can be avoided using Persisted Queries.

See Enable caching of persisted queries for further details.

NOTE
To allow direct, and/or POST, queries in the Dispatcher you can ask your System Administrator to:
NOTE
The ability to perform direct queries may be deprecated at some point in the future.

GraphiQL IDE

You can test and debug GraphQL queries using the GraphiQL IDE.

Use Cases for Author, Preview and Publish

The use cases can depend on the type of AEM as a Cloud Service environment:

  • Publish environment; used to:

    • Query data for JS application (standard use-case)
  • Preview environment; used to:

    • Preview queries prior to deploying on the Publish environment
      • Query data for JS application (standard use-case)
  • Author environment; used to:

    • Query data for “content management purposes”:

      • GraphQL in AEM as a Cloud Service is currently a read-only API.
      • The REST API can be used for CR(u)D operations.

Permissions

The permissions are those required for accessing Assets.

GraphQL queries are executed with the permission of the AEM user of the underlying request. If the user does not have read access to some fragments (stored as Assets), they will not become part of the result set.

Also, the user must have access to a GraphQL endpoint to be able to execute GraphQL queries.

Schema Generation

GraphQL is a strongly-typed API, which means that data must be clearly structured and organized by type.

The GraphQL specification provides a series of guidelines on how to create a robust API for interrogating data on a certain instance. To do this, a client must fetch the Schema, which contains all the types necessary for a query.

For Content Fragments, the GraphQL schemas (structure and types) are based on Enabled Content Fragment Models and their data types.

CAUTION
All the GraphQL schemas (derived from Content Fragment Models that have been Enabled) are readable through the GraphQL endpoint.
This means that you need to ensure that no sensitive data is available, as it could be leaked this way; for example, this includes information that could be present as field names in the model definition.

For example, if a user created a Content Fragment Model called Article, then AEM generates a GraphQL type ArticleModel. The fields within this type correspond to the fields and data types defined in the model. In addition, it creates some entrypoints for the queries that operate on this type, such as articleByPath or articleList.

  1. A Content Fragment Model:

    Content Fragment Model for use with GraphQL

  2. The corresponding GraphQL schema (output from GraphiQL automatic documentation):
    GraphQL Schema based on Content Fragment Model

    This shows that the generated type ArticleModel contains several fields.

    • Three of them have been controlled by the user: author, main and referencearticle.

    • The other fields were added automatically by AEM, and represent helpful methods to provide information about a certain Content Fragment; in this example, (the helper fields) _path, _metadata, _variations.

  3. After a user creates a Content Fragment based on the Article model, it can then be interrogated through GraphQL. For examples, see the Sample Queries (based on a sample Content Fragment structure for use with GraphQL).

In GraphQL for AEM, the schema is flexible. This means that it is auto-generated each and every time a Content Fragment Model is created, updated or deleted. The data schema caches are also refreshed when you update a Content Fragment Model.

The data schema caches are also refreshed when you update a Content Fragment Model.

The Sites GraphQL service listens (in the background) for any modifications made to a Content Fragment Model. When updates are detected, only that part of the schema is regenerated. This optimization saves time and provides stability.

So for example, if you:

  1. Install a package containing Content-Fragment-Model-1 and Content-Fragment-Model-2:

    1. GraphQL types for Model-1 and Model-2 are generated.
  2. Then modify Content-Fragment-Model-2:

    1. Only the Model-2 GraphQL type will get updated.

    2. Whereas Model-1 will remain the same.

NOTE
This is important to note in case you want to do bulk updates on Content Fragment Models through the REST api, or otherwise.

The schema is served through the same endpoint as the GraphQL queries, with the client handling the fact that the schema is called with the extension GQLschema. For example, performing a simple GET request on /content/cq:graphql/global/endpoint.GQLschema will result in the output of the schema with the Content-type: text/x-graphql-schema;charset=iso-8859-1.

Schema Generation - Unpublished Models

When Content Fragments are nested it can happen that a parent Content Fragment Model is published, but a referenced model is not.

NOTE
The AEM UI prevents this happening, but if publishing is made programmatically, or with content packages, it can occur.

When this happens, AEM generates an incomplete Schema for the parent Content Fragment Model. This means that the Fragment Reference, which is dependent on the unpublished model, is removed from the schema.

Fields

Within the schema there are individual fields, of two basic categories:

  • Fields that you generate.

    A selection of Data Types are used to create fields based on how you configure your Content Fragment Model. The field names are taken from the Property Name field of the Data Type tab.

    • There is also the Render As setting to take into consideration, as users can configure certain data types. For example, a single line text field can be configured to contain multiple single line texts by choosing multifield from the drop-down list.
  • GraphQL for AEM also generates several helper fields.

Data Types

GraphQL for AEM supports a list of types. All the supported Content Fragment Model Data Types and the corresponding GraphQL types are represented:

Content Fragment Model - Data Type
GraphQL Type
Description
Single line Text
String, [String]
Used for simple strings such as author names, location names, and so on.
Multi line Text
String, [String]
Used for outputting text such as the body of an article
Number
Float, [Float]
Used to display floating point number and regular numbers
Boolean
Boolean
Used to display checkboxes → simple true/false statements
Date And Time
Calendar
Used to display date and time in an ISO 8601 format. Depending on the type selected, there are three flavors available for use in AEM GraphQL: onlyDate, onlyTime, dateTime
Enumeration
String
Used to display an option from a list of options defined at model creation
Tags
[String]
Used to display a list of Strings representing Tags used in AEM
Content Reference
String, [String]
Used to display the path towards another asset in AEM
Content Reference (UUID)
String, [String]
Used to display the path, represented by a UUID towards another asset in AEM
Fragment Reference
A model type

Single field: Model - Model type, referenced directly

Multifield, with one referenced type: [Model] - Array of type Model, referenced directly from array

Multifield, with multiple referenced types: [AllFragmentModels] - Array of all model types, referenced from array with union type
Used to reference one, or more, Content Fragments of certain Model Types, defined when the model was created
Fragment Reference (UUID)
A model type

Single field: Model - Model type, referenced directly

Multifield, with one referenced type: [Model] - Array of type Model, referenced directly from array

Multifield, with multiple referenced types: [AllFragmentModels] - Array of all model types, referenced from array with union type
Used to reference one, or more, Content Fragments of certain Model Types, defined when the model was created