GraphQL API

Overview

As of version 7.0.0, WorkflowGen features the new GraphQL API, which is a modern solution to create process-driven solutions such as mobile apps, web apps, and microservices that require a powerful workflow and BPM engine.

The WorkflowGen GraphQL API is a Node.js application that runs in IIS using iisnode; it enables a high level of customization such as extending the GraphQL schema with custom types, queries or operations, or implementing new authentication methods.

You can use GraphiQL, "a graphical interactive in-browser GraphQL IDE", to test queries and operations, and to browse the schema documentation.

About GraphQL

From the GraphQL website presentation:

"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."

GraphQL is a production-ready and an open source technology created by Facebook. In September 2016, GitHub announced its GraphQL API.

"We’ve often heard that our REST API was an inspiration for other companies; countless tutorials refer to our endpoints. Today, we’re excited to announce our biggest change to the API since we snubbed XML in favor of JSON: we’re making the GitHub API available through GraphQL."

GraphQL is a modern API solution for React, React-Native, Angular 2, and Vue based applications.

Many GraphQL tutorials are available, it is available in many languages, and has a large community.

Endpoints

The following endpoints are available:

  • GraphQL API: http://localhost/wfgen/graphql

  • GraphiQL IDE: http://localhost/wfgen/graphql

  • GraphQL Schema (definition language): http://localhost/wfgen/graphql/schema

The HTTP GET method is supported on queries only. The HTTP POST method is supported on queries and operations.

HTTP usage

Express-graphql is used to serve the GraphQL HTTP queries:

GraphQL will first look for each parameter in the URL's query-string: /graphql?query=query+getUser($id:ID){user(id:$id){name}}&variables={"id":"4"} If not found in the query-string, it will look in the POST request body. If the POST body has not yet been parsed, express-graphql will interpret it depending on the provided Content-Type header:

  • application/json: the POST body will be parsed as a JSON object of parameters.

  • application/x-www-form-urlencoded: this POST body will be parsed as a url-encoded string of key-value pairs.

  • application/graphql: the POST body will be parsed as GraphQL query string, which provides the query parameter.

Configuration

Maximum query content length

The maximum GraphQL query content length can be set by configuring the maxAllowedContentLength property in the WorkflowGen web.config file. The following example shows how to configure this property as 1 MB (note that the value should always be specified in bytes, so the value in the example is 1,024,000 bytes). The default value is 30000000 bytes.

<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1024000" />
</requestFiltering>
</security>
</system.webServer>

Input file allowed folders

You must set the local or remote folder paths where files used by FILE type parameters are located. In the GraphQL section on the Integration tab in the Administration Module Configuration Panel, enter the folder names separated by commas in the Input file allowed folders (comma separated values) field.

Alternately, you can add the folder names separated by commas to the GraphqlFileInputAllowedFolders parameter in the WorkflowGen web.config file.

Note: When using file uploads, you don't need to include the original file folder.

Maximum input file size

In the GraphQL section on the Integration tab in the Administration Module Configuration Panel, enter the maximum input file size in kilobytes in the Maximum input file size (kB) field.

Alternately, you can set the maximum input file content size in kilobytes as the value of the GraphqlMaxInputFileSize parameter in the WorkflowGen web.config file.

Maximum input file content size

When working with FILE type parameters content encoded in base64, you must enter the maximum input file content size in kilobytes in the Maximum input file content size (kB) field in the GraphQL section on the Integration tab in the Administration Module Configuration Panel.

Alternately, you can set the maximum input file content size in kilobytes as the value of the GraphqlMaxInputFileContentSize parameter in the WorkflowGen web.config file.

Note: FILE type data content is only recommended for small files under 1 MB.

Performance tuning

WorkflowGen is installed with the following default GraphQL settings (located under iisnode in \wfgen\graphql\web.config):

nodeProcessCountPerApplication="0"
maxConcurrentRequestsPerProcess="1024"

The value of the nodeProcessCountPerApplication setting is set to 0 by default for the best performance in Node.js applications. This creates one node process based on the number of virtual processors that are configured. You can change this value at any time to a custom number of node processes; for example, nodeProcessCountPerApplication=2 will create two node processes independently of the number of virtual processors.

You can also optimize performance if needed by adjusting the maxConcurrentRequestsPerProcess value based on the number of potential concurrent users and requests.

For more information, see the Best practices and troubleshooting guide for node applications on Azure Web Apps Microsoft article.

Authentication

The following authentication methods are supported:

  • Integrated Windows

  • IIS Basic

  • WorkflowGen authentication

  • Custom .NET authentication modules

HTTPS is required to secure credentials.

The GraphQL Node.js app code inside the \wfgen\graphql folder can also be customized to accommodate many other authentication methods (such as OAuth2, JWT, etc.) thanks to node libraries such as Passport.js.

System access users

Some operations (such as CancelAction and UpdateRequestDataset) require users to have system access to perform the operations. This can be configured in the System operations allowed users field, under Security on the Integration tab in the Configuration Panel.

User impersonation

User impersonation is supported but not recommended, and should be used only when no other technical solutions are possible. (For example, OpenID Connect-based authentication methods allow you to use access tokens to perform API operations on the client and server sides without impersonation.)

System operations allowed users can impersonate another WorkflowGen user account by setting this account's username as the value of the x-wfgen-impersonate-username HTTP request header.

This request header can be renamed according to your naming convention. You can specify a new header name in the GraphqlImpersonateUserNameHttpHeader setting in the \wfgen\web.config file (e.g. <add key="GraphqlImpersonateUserNameHttpHeader" value="my-custom-impersonate-username" />).

To give or withdraw system operations rights to or from specific users, refer to the System operations allowed users setting in the Security section on the General tab of the Configuration Panel; alternately, you can edit the ProcessesRuntimeWebServiceAllowedUsers setting in the \wfgen\web.config file.

Examples

Using Curl

curl -u yourusername -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'query={
viewer {
userName
lastName
firstName
email
}
}' "http://localhost/wfgen/graphql"

And the result is:

{
"data": {
"viewer": {
"userName": "johndoe",
"lastName": "Doe",
"firstName": "John",
"email": "john.doe@acme.com"
}
}
}

Using GraphiQL IDE in a web browser

You can copy/paste these queries directly in the GraphiQL IDE.

Viewer basic info (the authenticated user)

{
viewer {
userName
lastName
firstName
email
}
}

My actions to do

{
viewer {
actions(filter: {as: ASSIGNEE, status: OPEN}) {
totalCount
hasNextPage
hasPreviousPage
items {
request {
number
description
}
number
name
description
limit
launchUrl
}
}
}
}

Fetch a request by its number

{
request(number: 273) {
description
requester {
lastName
userName
company
}
process {
name
version
}
}
}

Create a new request

A parameter's array can be included in the createRequest operation payload. Be aware that a data with the same name and data type must previously exist in the process for each parameter in the array to store the parameter's value. The following example shows how to send parameters corresponding to the four supported data types (TEXT, NUMERIC, DATETIME, and FILE).

mutation{
createRequest(
input: {
processName: "PRODUCT_CREATION"
processVersion: 1
parameters: [
{
name: "CATEGORY",
textValue: "robot"
},
{
name: "VALUE",
numericValue: 5
},
{
name: "CREATION_DATE",
dateTimeValue: "2017-02-23T20:46:00Z"
},
{
name: "FILE",
fileValue: {
name: "RobotFile.txt",
contentType: "text/plain",
size: 616,
url: "file:///c:/RobotFIle.txt"
}
}
]
}){
request{
number
followUpFormUrl
}
}
}

Global identifiers

Each GraphQL type has an id: ID! field. This ID is global and is unique for all WorkflowGen objects.

You can use the node(id:ID!) query to retrieve a WorkflowGen object by its ID.

{
node(id: "UHJvY2VzczoxNQ==") {
id
... on Request {
number
requester {
lastName
}
}
... on Action {
limit
assignee {
id
company
}
}
... on User {
userName
email
}
}
}

Pagination

The GraphQL API supports page number based pagination. You can set a page number and a size; otherwise, the default values are:

  • 1 for the page number

  • 30 for the page size

The maximum value for the page size is 100. You can change this setting in the GraphqlMaxPageSize key in the \wfgen\web.config file.

The result contains:

  • totalCount: The total number of items

  • hasPreviousPage

  • hasNextPage

  • Items: The list of items in the requested page

{
viewer {
requests(page: {number: 2, size: 20}, filter: {as: REQUESTER, status: OPEN}, orderBy: {field: NUMBER, direction: DESC}) {
totalCount
hasNextPage
hasPreviousPage
items {
id
number
requester {
userName
}
}
}
}
}

To retrieve the total count without the list of items, you just need to set the page number to 0:

{
viewer {
requests(page: {number: 0}, filter: {as: REQUESTER, status: OPEN}) {
totalCount
hasNextPage
hasPreviousPage
}
}
}

File download

As of WorkflowGen version 7.12.0, file data can be downloaded using a blob URL that is returned in the process, request or action datasets, respectively.

Query

{
requests{
items{
dataset{
items{
fileValue{
name
description
blobUrl
}
}
}
}
}
}

Response

{
"data": {
"requests": {
"items": [
{
"dataset": {
"items": [
"fileValue": {
"name": "test.txt",
"description": "test.txt",
"blobUrl": "http://localhost/wfgen/graphql/workflow/data/files/V29ya2Zsb3dEYXRhRmlsZToxNzEtLS0x"
}
]
}
}
]
}
}

File upload

As of version 7.2.0, GraphQL supports the fileValue.updatedAt, fileValue.content, and fileValue.url fields when sending FILE parameters (as shown in the previous example).

The fileValue.updatedAt field should use the ISO 8601 date format.

File content

The fileValue.content field should contain the file content encoded in base64. In this case, the fileValue.url field is not required. You must set the maximum input file content size (see the Configuration section above for instructions on how to set these).

...
{
"name": "FILE",
"fileValue": {
"name": "test.txt",
"contentType": "plain/text",
"size": 76,
"updatedAt": "2017-03-15T15:02:00Z",
"content": "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4="
}
}
...

File URL

The fileValue.url field contains the file URL. When working with FILE parameters, you must set the input file allowed folders and the maximum input file size (see the Configuration section above for instructions on how to set these).

The following path patterns are supported:

Local file should use the File URI scheme:

...
{
"name": "FILE",
"fileValue": {
"name": "test.txt",
"description": "test.txt",
"contentType": "plain/text",
"url": "file:///c:/temp/test.txt",
"size": 4714,
"updatedAt": "2017-03-15T15:02:00Z"
}
}
...

Public file URL:

...
{
"name": "FILE",
"fileValue": {
"name": "update.zip",
"description": "update.zip",
"contentType": "application/zip",
"url": "http://download.workflowgen.com/product/latest/update.zip",
"size": 4120858,
"updatedAt": "2017-03-15T15:02:00Z"
}
}
...

Local host file URL:

...
{
"name": "FILE",
"fileValue": {
"name": "test.txt",
"description": "test.txt",
"contentType": "plain/text",
"url": "http://localhost:8081/test.txt",
"size": 4714,
"updatedAt": "2017-03-15T15:02:00Z"
}
}
...

Multipart file upload

As of WorkflowGen version 7.14.0, GraphQL supports multipart file uploads for the following mutations:

  • createRequest

  • completeAction

  • completeFormAction

  • updateRequestDataset

Curl example for a single upload

curl -X POST http://localhost/wfgen/graphql
-H 'content-type:multipart/form-data'
-F "operations={ \"query\": \"mutation ($fileUpload1: Upload) { createRequest(input: {processName: \\\"SIMPLE_REQUEST\\\" processVersion:1 parameters:[{name:\\\"FILE1\\\" fileValue:{ upload: $fileUpload1}}] }) { request { number } } }\", \"variables\": { \"fileUpload1\": null } }"
-F "map={ \"1\": [\"variables.fileUpload1\"] }"
-F "1=@C:\test1.txt"
  • content-type should be multipart/form-data

  • The operations field is required, and contains the GraphQL query:

    • The Upload variables should be declared for the mutation:

      mutation ($fileUpload1: Upload)

    • input.parameters[X].fileValue should contain an upload property whose value is a variable previously declared:

      parameters:[{name:\\\"FILE1\\\" fileValue:{ upload: $fileUpload1}}]

    • The variables values should be set to null:

      \"variables\": { \"fileUpload1\": null }

  • The map field is required and contains the file mappings:

    • It should follow the operations part.

    • The key should be an alphanumeric string that matches the file key ("1" in the above example).

    • The value is the variable that will be assigned to the upload:

      [\"variables.fileUpload1\"]

    • For each map entry declared, a file with the same key must be attached.

  • Each file to be uploaded should contain the alphanumeric key and the file path:

    "1=@C:\test1.txt"

    • Each file attached must match a map entry.

    • The files must follow the operation and map parts.

Curl example for multiple uploads

curl -X POST http://localhost/wfgen/graphql
-H 'content-type:multipart/form-data'
-F "operations={ \"query\": \"mutation ($fileUpload1: Upload, $fileUpload2: Upload) { createRequest(input: {processName: \\\"SIMPLE_REQUEST_MULTIPLE_FILES\\\" processVersion:1 parameters:[{name:\\\"FILE1\\\" fileValue:{ upload: $fileUpload1}},{name:\\\"FILE2\\\" fileValue:{ upload: $fileUpload2}}] }) { request { number } } }\", \"variables\": { \"fileUpload1\": null, \"fileUpload2\": null } }"
-F "map={ \"1\": [\"variables.fileUpload1\"],\"2\": [\"variables.fileUpload2\"]}"
-F "1=@C:\test1.txt"
-F "2=@C:\test2.txt"

Limits

  • The maximum number of uploads in the same request is 30.

  • The maximum file upload size is set in the GraphqlMaxInputFileSize configuration parameter.

Note: The multipart/form-data content type is only supported for HTTP requests with file uploads. If the fileValue.name, fileValue.description, and fileValue.contentType properties are not defined, they will be set from the uploaded file information; otherwise, they will take the values defined the payload.

Delegation mode

Some GraphQL queries and operations can be executed on behalf of another user. This is possible when a user has created a delegation in WorkflowGen. The delegatee has to specify the user ID of his delegator in the onBehalfOf argument.

List of actions to do on by the delegatee on behalf of the delegator with the user ID VXNlcjoy:

{
viewer {
actions(filter: {as: ASSIGNEE, status: OPEN}, onBehalfOf:"VXNlcjoy"}) {
totalCount
hasNextPage
hasPreviousPage
items {
request {
number
description
}
number
name
description
limit
launchUrl
}
}
}
}

When the onBehalfOf argument is set, it is propagated implicitly to the all the sub-queries and fields until a User type is used.

Logs

All HTTP queries are logged by IIS as other ASP.NET web apps. Node.js application logs are available in the \wfgen\graphql\iisnode\ folder. You can adjust the iisnode log file management in the \wfgen\graphql\web.config file.

Debug mode

A debug mode can be enabled by setting the GraphqlDebugEnabled key to Y in the \wfgen\web.config file.

In debug mode, some extensions are added to the GraphQL response, and additional error messages are logged in the \wfgen\graphql\iisnode\ folder.