Building a GraphQL API with Magnolia CMS
In this article I will show how to create a GraphQL API using the headless features of Magnolia CMS.
GraphQL
GraphQL is a query language for APIs defined by Facebook to solve some issues of traditional REST APIs as flexibility and simplicity.
All the resources of the API are exposed in a single request — normally a POST to /graphql — and the content is a query using GraphQL specification. The query specifies the filter and the data to be returned by the API. Below you can find an example to query the detail of a film:
query {
films(id: "english-patient") {
director,
duration,
summary
actors {
name,
gender,
role
}
}
}
In case that actors were not required, just remove the actors field from the query — In case of REST API it would be necessary to implement a new endpoint —
In addition to queries, GraphQL provides Mutation for requests of creation, update and delete resources and Subscription for realtime queries.
For more details about the specification of GraphQL you can visit the official website of GraphQL
Magnolia CMS
Magnolia CMS is an open source CMS developed in Java and focused on headless skills, that makes it really easy and cheap to create API’s to query and manage the contents in the CMS.
Magnolia Delivery endpoint API
Delivery endpoint API is a powerful feature of Magnolia that allows the creation of an API in declarative way just with a .yaml file.
Below you can see an example of definition of Delivery endpoint.
class: info.magnolia.rest.delivery.jcr.v2.JcrDeliveryEndpointDefinition
nodeTypes:
- mgnl:content
includeSystemProperties: false
bypassWorkspaceAcls: false
limit: 50
workspace: tours
references:
- name: tourTypes
propertyName: tourTypes
referenceResolver:
class: info.magnolia.rest.reference.jcr.JcrReferenceResolverDefinition
targetWorkspace: category
For more details about Delivery endpoint API you can visit the official documentation of Magnolia CMS
Java-based REST endpoint
As Magnolia CMS is open source and developed in Java, it is possible to implement a traditional java-based REST the same way as any java service.
At this entry of the documentation of Magnolia can be found the guidelines to create a java-based REST in Magnolia How to create a custom Java-based REST endpoint
Implementation of magnolia-rest-graphql
magnolia-rest-graphql is a custom module of Magnolia that implements a GraphQL API for contents in Magnolia CMS.
Casting
GraphQL spec (June 2018) as specification of GraphQL
Magnolia CMS 6.1 as GraphQL API server
graphql-java 14.0 as java implementation of GraphQL. Awesome library that implements GraphQL specs for java.
Features
Requirements and features of magnolia-rest-graphql
- Expose endpoint for GraphQL queries.
- Register GraphQL schemas as resources of Magnolia.
- Create GraphQL schemas for registered Delivery endpoints. This feature will allow to get Delivery endpoints as GraphQL Queries
- Graph Query field to make queries directly on JCR repository. It will be the GraphQL version of Nodes endpoint API
Endpoint for GraphQL queries
The module magnolia-rest-graphql exposes the endpoint POST /.rest/magnolia-rest-graphql/graphql to handle GraphQL requests. The endpoint is implemented as a Java-based REST endpoint in the class GraphQLEndpoint
GraphQL schemas as resources of Magnolia
The schema of GraphQL types must be defined into the resources folder /graphqls in a similar way as restEndpoints.
my-light-module/├── decorations├── dialogs├── graphqls│ ├── pages.graphql│ └── tours.graphql├── i18n├── restEndpoints│ └── pages_v1.yaml├── templates└── webresources
The schemas must be written using SDL (Schema Definition Language) and the query fields must use the directive @definition to specify the workspace, root path and nodetypes of the query. Below you can see an example to execute queries in the workspace website for nodetypes mgnl:page
GraphQL schemas for registered RestEndpoints
Delivery endpoints are mapped with GraphQL schemas to allow querying the same resources with GraphQL requests.
For every delivery endpoint is created a Query field named <delivery endpoint> and tagged with the directive @delivery to specify the workspace, root path and nodeTypes of the queries. The value of the arguments are taken from the Delivery endpoint definition.
Below you can see an example of the GraphQL schema generated from a registered Delivery endpoint:
Example of query based on the example below:
POST /.rest/magnolia-rest-graphql/graphql
query {
delivery_tours_v1 {
name,
properties {
name,
string
}
}
}
GET /.rest/delivery/tours/v1
Graph Query field to execute queries on JCR repository
Magnolia provides the Nodes endpoint API to access and manipulate JCR Nodes, the module magnolia-rest-graphql provides the query field nodes to execute same kind of queries.
Example of request to query the pages inside /travel folder:
POST /.rest/magnolia-rest-graphql/graphql
query {
nodes(workspace: "website", path: "/travel") {
name,
nodeType,
path,
children {
properties {
name,
string
}
}
}
}
GET http://localhost:8080/magnolia-rest-graphql-bundle/.rest/nodes/v1/website/travel
Usage
First. Adds the dependency of magnolia-rest-graphql to the bundle of magnolia:
<!-- magnolia-rest-graphql -->
<dependency>
<groupId>com.formentor</groupId>
<artifactId>magnolia-rest-graphql</artifactId>
<version>${magnolia-rest-graphql.version}</version>
</dependency>
Second. Creates the folder /graphqls in a light-module or java module
my-light-module/├── decorations├── dialogs├── graphqls├── i18n├── restEndpoints├── templates└── webresources
Third. Design your own query fields and add the .graphql files to /graphqls folder
Fourth. Check the schema with your favourite GraphQL client— I will use GraphQL Playground —
Fifth. Build and execute your queries easily from GraphQL client
Example using Apollo client
Dependencies:
npm i apollo-cache-inmemory apollo-client apollo-link-http graphql graphql-tag isomorphic-unfetch
Apollo client to magnolia-rest-graphql resources
nextjs page that renders content queried to Magnolia:
Resources and references
Github of the module magnolia-rest-graphql
Github of a bundle of magnolia using magnolia-rest-graphql