Mutating Data with GraphQL in UI Builder

For most ServiceNow developers, GraphQL will be a new concept to understand and use. The documentation specifically related to using GraphQL on ServiceNow is currently sparse, however there is plenty in regards to GraphQL itself. To use UI Builder the way it is designed requires fully embracing GraphQL.

This will be a short post, simply just to document the process of mutating data in a ServiceNow database from a UI Builder data broker. “Mutating” data is simply another way of saying “modifying” data – i.e. the read, update, and delete aspects of standard CRUD operations (create, read, update, and delete).

Create a GraphQL API

It all starts with a GraphQL API record, which you can create

FieldValue
NameTesting API
Schema NamespacetestingApi
Application NamespacexSncGtc (this will vary depending on your application scope. This will be needed later)
Schema(see below)

Schema:

schema {
	query: Query
	mutation: Mutation
}

type Query {
	findIncidentById(id: ID!): Incident
}

type Mutation {
	createIncident(short_desc:String,description:String): Incident
}

type Incident {
	sys_id: String
	short_desc: String
	description: String
    caller_id: String
}

You will see that we are defining a query which will allow us to get an incident by ID, and also a mutation that allows us to create an incident. When creating an incident, we are expecting a short description, and a description to be provided.

One of the reasons GraphQL was created was to minimise the number of network requests needing to be sent when dealing with a relational database and REST API’s. You can see an example of it here as well, as for our createIncident mutation we are specifying that it will return an Incident. So in one operation, we can create an incident, and also return and select details about that incident we created.

Create a Scripted Resolver

Scripted resolvers are very simple if you are used to traditional server-side scripting in ServiceNow. We simply define a function that takes action, and inside it we can use GlideRecord and any other operation .

We will need a scripted resolver for both the findIncidentById query, and the createIncident mutation. Brad Tilton has a great article explaining how to create a query scripted resolver, so I will not cover that here.

Lets create our createIncident scripted resolver.

FieldValue
NamecreateIncidentResolver
Script(see below)

Script:

(function process(/*ResolverEnvironment*/ env) {

	var gr = new GlideRecord('incident');
	gr.initialize();

	if (env.getArguments().short_desc != null) {
		gr.setValue('short_description', env.getArguments().short_desc);
	}

	if (env.getArguments().description != null) {
		gr.setValue('description', env.getArguments().description);
	}

	gr.setValue('caller_id', gs.getUserID());

	gr.insert();

	return {
		sys_id: gr.getUniqueValue(),
		short_description: gr.getValue('short_description'),
		description: gr.getValue('description'),
		caller_id: gr.getValue('caller_id')
	};

})(env);

Resolver Mapping

We now need to link our createIncidentResolver scripted resolver to the createIncident mutation in our GraphQL schema.

In the GraphQL Resolver Mappings related list of our Testing API record, we click New.

The Path field of this new record actually looks through our schema and allows us to select parts of it to map to our Scripted Resolver’s.

Let’s use the following values for our record.

FieldValue
PathMutation:createIncident
ResolvercreateIncidentResolver

GraphQL Data Broker

The final step to enable the use of this GraphQL API in UI Builder is to create a GraphQL Data Broker.

FieldValue
NameCreate Incident using Testing API
DescriptionCreate an Incident record
Mutates server datatrue
Properties(see below)
TypeQuery
Query(see below)

Properties:

[
  {
    "name": "short_desc",
    "label": "Short Description",
    "description": "The short description of the incident",
    "fieldType": "string",
    "mandatory": true
  },
  {
    "name": "description",
    "label": "Description",
    "description": "The description of the incident",
    "fieldType": "string",
    "mandatory": true
  }
]

Query:

mutation ($short_desc: String!, $description: String!) {
  xSncGtc {
    testingApi {
      createIncident(short_desc: $short_desc, description: $description) {
        sys_id
      }
    }
  }
}

We are using the properties to define in UI Builder what to ask the user for. We then take those properties in the query, and pass them into the createIncident mutation. We also ask of the Incident that was created to give us the sys ID. Note that the xSncGtc will change depending on what application scope your GraphQL API was created in. You will be able to get the value to use here from the GraphQL API record in the “Application Schema” field as previously noted.

Being a data broker that mutates data, one likely wants to use it “on demand” rather than automatically upon page load for instance. You can either use the “Execute” action on the data broker in the UI Builder interface in reaction to another event on the page like a button click. Alternatively, you can call the data broker from a client script using the execute() command available on it like so:

api.data.my_data_resource_name.execute({
    myParameter: "The Value"
});