• Exacta Maestro™ Integration Design
  • User Guide
  • GraphQL User Guide
  • FAQ
  • Technical
  • Terminology
Show / Hide Table of Contents
  • GraphQL User Guide
    • Introduction
    • Authentication
    • Schema Organization
    • Building GraphQL Queries
    • Executing GraphQL Queries
    • Executing GraphQL Queries (Legacy)
    • Agent Management
    • Task Management

Executing GraphQL Queries

This guide shows how to execute GraphQL queries and mutations against Exacta Maestro™'s schema.

Split Schema Request Flow

Endpoints

Many of the microservices in a deployed environment of Exacta Maestro™ expose their own GraphQL schema over HTTPS through Bastian Solutions's load balancer. While the address of the load balancer changes for each deployed environment, every service that exposes a GraphQL server exposes the following endpoints:

  • https://{load-balancer-address}/{clientId}/{environmentId}/{serviceName}/graphql
  • https://{load-balancer-address}/{clientId}/{environmentId}/{serviceName}/graphql/ui
Tip

The clientId, environmentId, and serviceName are all case-sensitive.

The values for load-balancer-address, clientId, and environmentId will be distributed during system setup, while the serviceNames are constant within Exacta Maestro™. The /graphql path is for posting queries to the service's GraphQL schema, making it the primary endpoint for production workflows. The /graphql/ui endpoint exposes a GUI for schema exploration and administrative query execution.

Service serviceName Endpoints
Archive /archive Cold storage of old data
Agent Hub /agentHub Agent Data Queries, Environment Setup
Aliasing /aliasing Environment Setup
Inventory /inventory Manual Inventory Interaction, Environment Setup
LogHub /logHub Log aggregation and export
Map /map Environment Setup
Task Assignment /taskAssignment Task Creation, Task Queries, Assignment Algorithm Configuration
WebHmi /webhmi Web dashboard GUI for Exacta Maestro™
Tip

Some deployments may contain an extra GraphQL Gateway application, which exposes a single HTTPS endpoint over the load balancer and forwards any received request to the service targeted by the request body. The Gateway does not expose either GUI application nor any schema documentation, it just forwards the requests received on its main /graphql endpoint.

Important

As the GraphQL Gateway was developed for backwards compatibility, it is capable of circumventing client authentication. This requires the configuration of an encrypted password, used by the Gateway to resolve a valid JWT from Bastian.Identity, which the Gateway adds to the headers of any unauthenticated requests before forwarding.

Split Schema Request Flow

Authentication

All of Exacta Maestro™'s GraphQL services require authentication to use. For more information on this topic, see Authenticating with Exacta Maestro™. To avoid detracting from the GraphQL content, the following examples assume you have access to a valid JWT token.

Raw HTTP Request

GraphQL Requests are made with an HTTP POST. These headers are required:

  • Host: https://{load-balancer-address}/{clientId}/{environmentId}/graphql
  • Content-Type: application/json
  • Authorization: Bearer $JWT

The POST body is a JSON object with the following structure:

{
    "Query" :"",
    "OperationName": "",
    "Variables": {}
}
  • Query: The full text of the GraphQL query to execute. Since GraphQL is a language of its own, this is a string rather than a JSON object.

  • OperationName: The name of the operation to execute. This can be omitted if the query contains a single operation.

  • Variables: A JSON object containing any variables defined in the query's operation. The keys in the root of this object will be the variable names. The variable values will be scalars or objects mapping to the GraphQL type defined for the variable. If no variables were declared in the operation, this field can be omitted.

Here is an example of a raw POST to create a Task Group in Exacta Maestro™. This example was originally created in PostMan and traced with Fiddler.

POST https://localhost/clientId/environmentId/taskAssignment/graphql HTTP/1.1
Host: localhost:81
Connection: keep-alive
Content-Length: 315
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
Cache-Control: no-cache
Origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
Postman-Token: f64c72c1-54c3-9374-d698-8a8d3d489c6e
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Authorization: Bearer $JWT

{
	"Query": "mutation newTaskGroupOperation($input:TaskGroupInput!) { taskAssignmentMutation { newTaskGroup(request:$input) { isSuccess error } } }",
	"OperationName": "newTaskGroupOperation",
	"Variables": {
      "input": {
        "name": "My Task Group"
      }
    }
}

With the UI Playground

Visit https://{load-balancer-address}/{clientId}/{environmentId}/{serviceName}/graphql/ui. The displayed page contains an editor where you can type your query with intellisense support, as well as an explorer for viewing the schema.

Authentication information is required in order to use the UI Playground. Click the settings icon in the top right corner, ensure the Schema Endpoint matches the intended service's /graphql endpoint, and in the Autheorization tab provide a valid Bearer token.

With Powershell

GraphQL requests can be made with Windows Powershell v3 and higher using the Invoke-RestMethod cmdlet.

$body = @{
  query = @'
mutation newTaskGroupOperation($taskGroupName:String!) {
  taskAssignmentMutation {
    newTaskGroup(request: { name: $taskGroupName }) {
      isSuccess
      error {
        key
        collectionName
        message
      }
      value {
        id
        name
        dateCreated
        taskGroupState
      }
    }
  }
}
'@
  operationName = "newTaskGroupOperation"
  variables = @{
    taskGroupName = "My Task Group"
  }
}

$jsonBody = ConvertTo-Json $body -Depth 10

$headers = @{
    'Authorization' = "Bearer $JWT"
}

$result = Invoke-RestMethod -Method 'Post' -Uri $GraphQLConfig.uri -Body $jsonBody -Headers $headers -ContentType "application/json"

With C#

You can use .NET's HttpClient class to post a GraphQL query. HttpClient is available since .NET 4.5 and in all editions of .NET Core. This example also uses the NewtonSoft.Json library to serialize the request and deserialize the response.


using Newtonsoft.Json;

using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace HttpClientTest
{
    class Program
    {
        static readonly HttpClient httpClient = new HttpClient();

        static async Task Main(string[] args)
        {
            var body = new
            {
                Query = @"mutation newTaskGroupOperation($taskGroupName:String!) {
                  taskAssignmentMutation {
                    newTaskGroup(request: { name: $taskGroupName }) {
                      isSuccess
                      error {
                        key
                        collectionName
                        message
                      }
                      value {
                        id
                        name
                        dateCreated
                        taskGroupState
                      }
                    }
                  }
                }",
                OperationName = "newTaskGroupOperation",
                Variables = new
                {
                    taskGroupName = "My Task Group 2"
                }
            };

            var jsonBody = JsonConvert.SerializeObject(body);
            using var stringContent = new StringContent(jsonBody,
                                                        Encoding.UTF8,
                                                        "application/json");

            using var httpMessage = new HttpRequestMessage(HttpMethod.Post,
                                                           "https://localhost/clientId/environmentId/taskAssignment/graphql");
            httpMessage.Headers.Add("Authorization",
                                    "Bearer $JWT");
            httpMessage.Content = stringContent;

            using var httpResponse = await httpClient.SendAsync(httpMessage);

            if(httpResponse.StatusCode == HttpStatusCode.OK)
            {
                var responseBody = await httpResponse.Content.ReadAsStringAsync();
                dynamic graphQLResponse = JsonConvert.DeserializeObject(responseBody);
                var taskGroupId = graphQLResponse.data.taskAssignmentMutation.createTaskGroup.id;
                Console.WriteLine(taskGroupId.ToString());
            }
        }
    }
}

In This Article