Table of Contents

Working with side-effects

Activities in a DCR workflow can have side-effects. Examples include triggering a payment in an external payment system, looking up a value in a local database, or creating a new case in a legacy case-management system.

Such side-effects are provided by the DCR Workflow Effects Runtime, or just "effects".

An example effect

To make effects concrete, consider an effect which looks a company registration number (CVR number) and returns the registered name of that company. The lookup itself is performed as a HTTP GET request to a publically available service.

A minimal graph using this effect (with appropriate error handling) can be found in this model. Here is a screenshot showing the effect configuration for the effect DCR.Cvr.Name on the Lookup event:

Effect configuration for DCR.Cvr.Name

The name of the effect used (DCR.Cvr.Name) is visible on the event (Lookup) itself. In the configuration, we see that this effect takes a single parameter with id cvr which has the value $(cvr). The latter synax means that the value of the DCR Model event cvr will be used as the value of the parameter cvr.

Inspecting the model, we find that the cvr activity is the one with label CVR. Altogether, the model is intended to operate as follows.

  1. The user provides the CVR number of a company as input to the activity cvr.
  2. The lookup activity becomes pending an automatically executes.
  3. Because the lookup has an associated effect DCR.Cvr.Name, that effect executes as part of executing lookup
  4. The lookup effect issues a rest call, and either succeeds and set the value of lookup to the appropriate company name, or fails, and set its value to null.

You can observe this happening by trying the above model in the simulator.

Adding effects to a model

Your DCR.Workflow installation comes with a number of pre-installed effects. Model authors assign these effects to particular activities when creating models.

Tip

Refer to DCR Designer documentation for details on how to associate effects with activities in the DCR Designer.

Effect execution model

There are essentially two kinds of effects:

  1. Effects which retrieve values ("before effects").
  2. Effects which trigger updates in other systems ("after effects").

Effects of either kind has one of three possible outcomes: They may succeed, they may fail, or they may timeout.

Effects which retrieve values ("before effects")

These are effects are executed immediately before the activity A carrying the effect. Whatever value is produced by the effect is assigned to A on execution. If the effect fails or timeouts, the execution of A is aborted.

Because these effects are effectuated before the execution of the event, we refer to them simply as "before effects".

For before effects, it is assumed that it makes no difference whether the effect is executed 0, 1 or many times. Lookups in databases have this property. Payments or bookings do not; for these, user "after effects" (see below).

Examples include retrieving a value by issuing a HTTP GET request, reading data from a CSV file on disk, or querying a SQL database.

Effects triggering ("after effects")

These effects are executed after the activity B carrying the effect. After the B is executed, the effects underlying request or operation is started synchronously. Once that operation concludes or times out, its result (success, failure, timeout) triggers the subsequent execution of an additional activity, if such has been specified.

Because these effects are effectuated after the execution of the event, we refer to them simply as "after effects".

Examples include issuing a HTTP POST request.

Regardless of the outcome of the effect, the activity B is still considered executed. In the absence of crashes of the host system, the DCR model will capture and represent the result of the effect (success, failure, timeout). However, be aware that if the effect involves network or just out-of-(os)-process communication, it is possible for an effect to end in failure or timeout, even though the effect did in fact happen. E.g., suppose the effect is issuing a payment request to a bank via HTTP POST. In the absence of additional acknowledgment mechanisms, it possible for the request to complete on the remote end---and the payment to be issued---but the return message from the banking system to be lost or late. In this case, the DCR model will observe failure or timeout, even thought the effect did in fact take place.

It is the responsibility of effect designers to handle such situations gracefully.

Effect configuration

DCR modellers tend to be business users and domain experts. They tend not to be technical experts. In particular, they are unlikely to be comfortable or effective defining parameters to REST requests, or processing HTTP JSON responses.

Effects to be consumed by modellers should have a similar feel to the weather effect outlined above: The semantics from a business perspective should be clear ("get me the temperature of some city"), and if at all possible, no error handling should be required (weather returns 'null' on not found).

Effects are implemented in two layers:

  1. A set of core effects, implemented in C# or some other CLR language, provides the core mechanics of the effect. An example is the Get, which provides the core mechanics of issuing a HTTP GET request.

  2. A set of effects, defined in terms of the core effects and in practice given exclusively in configuration, is made available to end user.

In practice, the weather effect is defined as a JSON configuration file specifying parameters for the core Get effect. It looks like this:

"DCR.Sample.Weather" : {
    "description": "Get Weather Update",
    "implementation": {
        "id": "DCR.Workflow.Effect.Http.Get",
        "arguments": {
            "url": "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/$(bynavn)?unitGroup=metric&elements=temp&include=current%2Cremote%2Cobs&key=P4P8UHNPJPSE64X9QDYZ4M4LC&contentType=json",
            "timeout": 5
        },
        "authentication": "Anonymous"
    },
    "parameters": [
        {
            "Name": "bynavn",
            "DefaultValue": "Aarhus",
            "Mandatory": true
        }
    ],
    "outputs": [
        {
            "status": [ 400 ],
            "continuation": "fail",
            "transformer": "null"
        },
        {
            "status": [ 200 ],
            "continuation": "ok",
            "transformer": "dcr",
            "expression": "json get float (this, \"currentConditions.temp\")"
        }
    ]
},

This configuration has four parts:

  1. Preamble
  2. Implementation
  3. Parameters
  4. Outputs

1. Preamble

The preamble consists of an id and a description. The Id is how modellers reference the effect; the Description is presented to modellers in the [DCR Designer].

2. Implementation

Then follows Implementation. This section specifies what the effect actually does in terms of a core implementation effect, which is typically implemented in C#. In this case, the Id of the core effect is Get. (The Id is actually a C# type deriving from IEffect.)

Implementation effect typically has parameters, and we provide values for these parameters in Arguments. In the weather effect, we provide a URL and a timeout to the underlying Get effect. Refer to the documentation of the underlying effect to see what parameters each implementation effect supports.

HTTP-related effects may also specify an authentication mechanism in Authentication; in this case, we assume that an authentication mechanism Anonymous have been defined elsewhere in the configuration. In the sample configuration, Anonymous sends un-authenticated HTTP requests.

3. Parameters

The modeller can provide some of the inputs for the underlying implementation effect via parameters.

In the implementation section, if you scroll right in the URL argument, you will see that it contains the substring ...$(bynavn).... Here, bynavn is a parameter which is supplied by the model author. The parameters available to the model author is specified in the Parameters section.

In this case, the only parameter is bynavn. We saw above how the modeller specifies a value for this parameter in the DCR designer; this modeller-provided value will be used at run-time.

Each such parameter has a name, a default value, and an indication whether it is required or not. Failing to supply a required parameter will cause a run-time exception, and parameters are required by default.

The modeller may also use expansion when providing the value of bynavn. E.g., if he writes $(Activity7), we replace $(Activity7) with the value of Activity7, then use that value for the value of $(bynavn) in the URL parameter.

Transforming parameter inputs

Add a transform section to a parameter to indicate that the given value should be transformed before being passed to the effect. For instance:

 "parameters" : [
   { "name": "message", "mandatory": false },
   { "name": "body-string", 
     "mandatory": "false", 
     "transform": { "transformer": "encode-as-json-string"  }
   }
 ]

Here, if the effect is provided the input <top title="foo" /> for the parameter body-string, that input will be transformed into "<top title=\u0022foo\u0022 />" before being used in the effect. See Transformers below.

4. Outputs

Finally, the effect specifies how to process the result of the effect in the Outputs list. All effects produce results that have HTTP-like status-codes.

Each stanza specifies how to convert a particular response, based on its HTTP status code (in the status list) and an optional DCR-FEEL expression (in the match field). The empty list matches all HTTP status codes.

The continuation field specifies whether to consider the effect succesful or not. Valid values are "fail", "timeout", "ok".

The weather effect specifies that any 400 response will be converted to a failure with no value; where any 200 response will be converted to a success ("Ok"), applying the DCR language expression json get float (this, "currentConditions.temp") to retrieve the value at currentConditions.temp as a float.

Matching based on values

If you need an output stanza to apply only when the returned result has certain shape, providing a DCR-FEEL expression testing for this shape in the match field.

For example, suppose we are interacting with a remote service which returns json, but returns 200 OK on every request. To signal an error, this service returns a top-level json field success, which is always set to either true or false. In this case, the following output stanzas will discriminate between success and failure:

  "outputs": [
    {
     "status": [ 200 ],
     "match": "json get bool(this, 'success')",
     "continuation": "ok",
    }, 
    {
     "status": [ ],
     "continuation": "fail",
    }
  ]

Here, the first stanza matches only when the response is HTTP 200 (ok), AND the body returned value (interpreted as json) contains a top-level field 'success' with value true. Note how the DCR-FEEL expression accesses the body of the response via the special name 'this'.

Transformers

Regardless of the outcome, if a stanza matches, a transformer is applied to the output. A transformer takes the value produced by the effect and transforms it. Most transformers need further specification, which is provided in the expression field. The typical use-case is picking particular fields from inside larger json-structures. Here are the available transformers:

Transformer Expected effect output Meaning Expression
json JSON string retrieve value from inside json value JSON Path expression
dcr Any string compute result using DCR expression DCR expression; use this to access effect output
encode-as-json-string A valid json string E.g., <foo title="bar"> becomes "<foo title=\"bar\">" (or equivalent)
encode-datetime-as-unixtime-seconds integer Parse input as a DCR-expression-language datetime and convert it into number of seconds since the epoch
json-int-array-to-base64 base64 string Decode json array on form, e.g., { "value": [34, 54, 64] } into base64-encoded string representing the sequence of bytes valued 34, 54, 64. JSON Path expression selecting the array (value for the example to the left)
preserve Any string pass through untouched (not required)
null Any discard (not required)

If no transformer is specified, preserve is used.

Default outputs

If no outputs are specified, the following outputs will be used:

[{ "status": [ 200, 201, 202, 203, 204, 205, 206, 207, 208 ],
   "continuation": "ok", }, 
 { "status": [ 408, 504 ], 
   "continuation": "timeout" }, 
 { "status": [],
   "continuation": "fail" }]

Special parameters

For after-effects it is possible to have particular events executed depending on the continuation set in output. If you supply an activity id as one of the following parameters, that activity will be executed with the transformed value as its data value, after the activity causing the effect is done executing.

Parameter Continuation value
ContinueOnOk ok
ContinueOnFail fail
ContinueOnTimeout timeout

Do note that these continuations are not executed for before-effects.

See also

The documentation of DerivedEffectOptions and members define the configuration options for effects.

Built-in core effects

At the time of writing, DCR.Workflow offers the following core effects.

Type Before/after Semantics
Get Before HTTP GET
Post After HTTP POST
Before Load data from CSV
WorkZone Before AND after KMD SetValue/GetValue emulator

HTTP effect authentication

All effects can specify an authentication mechanism to use in the Authentication property. Currently only HTTP effects use this property. For those, the possible values of Authentication are provided in a separate configuration section DCR.Workflow.Effect.Authentication.Http.

As an example, suppose the weather effect need to supply api-key authentication by providing the token 0xCAFEBABE in the header X-JAVA-CENTRIC-API-KEY. We change the Authentication property in the effect to MyApiKeyAuthentication and add the following configuration:

{ "DCR.Workflow.Effect.Http.Authentication.Http": [{
   "id": "MyApiKeyAuthentication", 
   "type": "DCR.Workflow.Effect.Http.HttpApiKeyAuthenticator", 
   "header": "X-JAVA-CENTRIC-API-KEY",
   "value": "0xCAFEBABE"
}

All HTTP authentication mechanisms must provde id and type; the type dictates what other fields are required: If type is T, then the properties of type TOptions should be present. (So, from the above example we see that DCR.Workflow.Effect.Http.HttpApiKeyAuthenticatorOptions must define header and value.)

The DCR.Workflow HTTP effect subsystem currently provdes the following HTTP authentication mechanisms:

Type Semantics
Anonymous No authentication
HttpBasicAuthenticator HTTP basic authentication
HttpTokenAuthenticator Possibly retrieve an authentication token and set it as header value/bearer/body
HttpCertificateAuthenticator HTTP client certificate authentication

See the documentation of the classes linked in the above table for more details.

If you must set authentication parameters at the last minute, immediately before executing an event, provide credentials using the secret parameter to runtime. E.g., to set HTTP Basic authentication kolmogorov:password123 at the last minute, add this to your config:

"MyHttpBasicAuthenticator": { 
   type: "DCR.Workflow.Effect.Http.HttpBasicAuthenticator"
}

Then call the runtime like this:

var secrets = new Dictionary { 
   { "Username", "kolmogorov" },
   { "Password", "password123" }
};
await runtime.Execute(model, activity, secrets: secrets);

NB! This mechanism is currently implemented only for the HTTP Basic authenticator.

Developing your own core effects

Before developing your own core effect, consider whether you really need to. Many common needs can be addressed with HTTP effects. Good candidates for effects are special-purpose code that connect to your host system, e.g., an effect that communicates the DCR phase to the host system.

To add your own effects, take the following steps.

  1. Create a type MyEffect : IEffect implementing the IEffect interface.
  2. Register your type both as an IEffect and when configuring Runtime
   services.AddDcrRuntime(builder => { 
      builder.AddEffect<MyEffect>(); 
   })

Refer to the IEffect for more information.

Developing your own authentication methods

Implement the interface IHttpAuthenticator, then specify the type of your class as id in DCR.Workflow.Effect.Authentication.Http including a DLL-reference. The Authenticator will then be assembled by reflection at runtime.

Extended example

The following configuration file defines some of the DCR Sample effects. Some value have been replaced with 'null' since they are credentials.

{ 
    "DCR": {
        "Workflow": {
            "Effect": {
                "Authentication:Http": {
                    "Anonymous" : {
                        "type": "DCR.Workflow.Effect.Http.Anonymous"
                    },
                    "RepoApiKey" : {
                        "type": "DCR.Workflow.Effect.Http.HttpTokenAuthenticator", 
                        "header": "X-DCR-AuthToken",
                        "token": null
                    },
                    "RepoBasic" : {
                        "type": "DCR.Workflow.Effect.Http.HttpBasicAuthenticator",
                        "username": null, 
                        "password": null
                    },
                    "RepoBasicTest" : {
                        "type": "DCR.Workflow.Effect.Http.HttpBasicAuthenticator",
                        "username": null, 
                        "password": null
                    },
                    "ClientCert" : {
                        "type": "DCR.Workflow.Effect.Http.HttpCertificateAuthenticator",
                        "certificate": "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",
                        "passphrase": "foo",
                        "thumbprint": "C8:00:D7:62:2A:A7:08:F4:A9:FB:3A:49:98:AD:41:CF:77:F1:20:66"
                    },	
                    "CreditSafeToken" : {
                        "type": "DCR.Workflow.Effect.Http.HttpTokenAuthenticator",
                        "bearer": true,
                        "tokenEffect": {
                            "implementation": {
                                "id": "DCR.Workflow.Effect.Http.Post",
                                "arguments": {
                                    "url": "https://connect.sandbox.creditsafe.com/v1/authenticate",
                                    "body": null,
                                    "timeout": 5
                                }
                            },
                            "outputs": [
                                {
                                    "status": [ 200 ],
                                    "continuation": "ok",
                                    "transformer": "json",
                                    "expression": "token"
                                }
                            ]
                        }
                    },
                    "QueryParam" : { 
                        "type": "DCR.Workflow.Effect.Http.HttpTokenAuthenticator",
                        "queryParameter": "token",
                        "value": "argldi-bargldi"
                    },
                    "Penneo.Wsse": {
                        "type": "DCR.Workflow.Effect.Http.HttpWsseAuthenticator",
                        "username": null,
                        "password": null
                    }
                },
                "Effects": {
                    "DCR.Sample.Weather" : {
                        "description": "Get Weather Update",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/$(bynavn)?unitGroup=metric&elements=temp&include=current%2Cremote%2Cobs&key=P4P8UHNPJPSE64X9QDYZ4M4LC&contentType=json",
                                "timeout": 5
                            },
                            "authentication": "Anonymous"
                        },
                        "parameters": [
                            {
                                "Name": "bynavn",
                                "DefaultValue": "Aarhus",
                                "Mandatory": true
                            }
                        ],
                        "outputs": [
                            {
                                "status": [ 400 ],
                                "continuation": "fail",
                                "transformer": "null"
                            },
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "dcr",
                                "expression": "json get float (this, \"currentConditions.temp\")"
                            }
                        ]
                    },
                    "DCR.Sample.Weather.Base64" : {
                        "description": "Get Weather Update (base64)",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/$(bynavn)?unitGroup=metric&elements=temp&include=current%2Cremote%2Cobs&key=P4P8UHNPJPSE64X9QDYZ4M4LC&contentType=json",
                                "timeout": 5,
                                "binary": true
                            },
                            "authentication": "Anonymous"
                        },
                        "parameters": [
                            {
                                "Name": "bynavn",
                                "DefaultValue": "Aarhus",
                                "Mandatory": true
                            }
                        ],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "preserve"
                            }
                        ]
                    },
                    "DCR.Test.RandomUserJSON" : {
                        "description": "Random user data to test json",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://randomuser.me/api/",
                                "timeout": 5,
                                "output": "json"
                            },
                            "authentication": "Anonymous"
                        },
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "preserve"
                            }
                        ]
                    },
                    "DCR.Sample.Weather.Json.Base64" : {
                        "description": "Get Weather Update (base64) with headers and json output",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/$(bynavn)?unitGroup=metric&elements=temp&include=current%2Cremote%2Cobs&key=P4P8UHNPJPSE64X9QDYZ4M4LC&contentType=json",
                                "timeout": 5,
                                "binary": true,
                                "output": "json"
                            },
                            "authentication": "Anonymous"
                        },
                        "parameters": [
                            {
                                "Name": "bynavn",
                                "DefaultValue": "Aarhus",
                                "Mandatory": true
                            }
                        ],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "preserve"
                            }
                        ]
                    },
                    "DCR.Test.PlainText": {
                        "description": "Plain text",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h",
                                "timeout": 5,
                                "output": "json"
                            },
                            "authentication": "Anonymous"
                        },
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "preserve"
                            }
                        ]
                    },
                    "DCR.Sample.CVR" : {
                        "description": "Get Company name from CVR number",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://cvrapi.dk/api?country=dk&vat=$(CVRNumber)",
                                "timeout": 5
                            },
                            "authentication": "Anonymous"
                        },
                        "parameters": [
                            {
                                "name": "CVRNumber"
                            }
                        ],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "json",
                                "expression": "name"
                            },
                            {
                                "status": [ 404 ],
                                "continuation": "ok",
                                "transformer": "dcr",
                                "expression": "null"
                            }
                        ]
                    },
                    "DCR.CreditSafe.CVR": {
                        "description": "Get CreditSafe id from CVR number",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://connect.sandbox.creditsafe.com/v1/companies?countries=DK&vatNo=$(CVRNumber)",
                                "timeout": 5
                            },
                            "authentication": "CreditSafeToken"
                        },
                        "parameters": [
                            {
                                "Name": "CVRNumber",
                                "DefaultValue": "",
                                "Mandatory": true
                            }
                        ],
                        "outputs": [
                            {
                                "status": [
                                    
                                ],
                                "continuation": "ok",
                                "transformer": "preserve",
                                "expression": "companies[0]"
                            }
                        ]
                    },
                    "DCR.CreditSafe.Report": {
                        "description": "Get CreditSafe Company report",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://connect.sandbox.creditsafe.com/v1/companies/$(CreditSafeID)",
                                "timeout": 5
                            },
                            "authentication": "CreditSafeToken"
                        },
                        "parameters": [
                            {
                                "Name": "CreditSafeID",
                                "DefaultValue": "",
                                "Mandatory": true
                            }
                        ],
                        "outputs": [
                            {
                                "status": [
                                    200
                                ],
                                "continuation": "ok",
                                "transformer": "json",
                                "expression": "totalSize"
                            }
                        ]
                    },
                    "DCR.Sample.CVRLookup" : {
                        "description": "Get Company details from CVR number",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://cvrapi.dk/api?country=dk&vat=$(CVRNumber)",
                                "timeout": 5
                            },
                            "authentication": "Anonymous"
                        },
                        "parameters": [
                            {
                                "name": "CVRNumber"
                            }
                        ],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "json",
                                "expression": ""
                            },
                            {
                                "status": [ 404 ],
                                "continuation": "ok",
                                "transformer": "dcr",
                                "expression": "null"
                            }
                        ]
                    },
                    "DCR.Repo.GetGraphs.Basic" : {
                        "description": "Retrieves list of graphs for user (authorized with HTTP Basic)",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://repository.dcrgraphs.net/api/graphs?title=$(SearchFor)&sort=$(OrderBy)&orderby=$(OrderBySeq)", "timeout": "5"
                            },
                            "authentication":"RepoBasic"
                        },
                        "parameters": [
                            {
                                "name": "SearchFor",
                                "Mandatory": false,
                                "defaultValue": "foo"
                            },                                                                                                        
                            {
                                "name": "OrderBy",
                                "defaultValue": "id",
                                "mandatory": false
                            },
                            {
                                "name": "OrderBySeq",
                                "defaultValue": "asc",
                                "mandatory": false
                            }
                        ],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "string",
                                "expression": "",
                                "filter": 3
                            }
                        ]
                    },
                    "DCR.Repo.GetGraphs.ApiKey" : {
                        "description": "Retrieves list of graphs for user (authorized with API key)",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "Arguments": {
                                "url": "https://repository.dcrgraphs.net/api/graphs",
                                "timeout": "5"
                            },
                            "authentication":"RepoApiKey"
                        },
                        "parameters": [
                            
                        ],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "string",
                                "expression": "",
                                "filter": 3
                            }
                        ]
                    },
                    "DCR.Repo.GetGraph.ApiKey": {
                        "description": "Retrieve a DCR graph for user (authorized with API key)",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "Arguments": {
                                "url": "https://repositorytest.dcrgraphs.net:43443/api/graphs/$(DCRGraphID)",
                                "timeout": "5"
                            },
                            "authentication": "RepoBasicTest"
                        },
                        "parameters": [
                            {
                                "Name": "DCRGraphID",
                                "DefaultValue": "",
                                "Mandatory": true
                            }
                        ],
                        "outputs": [
                            {
                                "status": [
                                    200
                                ],
                                "continuation": "ok",
                                "transformer": "preserve",
                                "expression": "",
                                "filter": 3
                            }
                        ]
                    },
                    "DCR.Sample.CreditSafe" : {
                        "description": "Get CreditSafe Company report",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "arguments": {
                                "url": "https://connect.sandbox.creditsafe.com/v1/companies?countries=GB&postCode=CF10*&name=Creditsafe",
                                "timeout": 5
                            },
                            "authentication": "CreditSafeToken"
                        },
                        "parameters": [],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "json",
                                "expression": "totalSize"
                            }
                        ]
                    },
                    "DCR.Sample.Http.Cert" : { 
                        "description": "Issue GET request with cert authentication",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "Arguments": {
                                "url": "https://example.com:8443"
                            },
                            "authentication": "ClientCert"
                        },
                        "parameters": [],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "string"
                            }
                        ]
                    },
                    "DCR.Sample.Const" : {
                        "description": "",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Const",
                            "arguments": {
                                "message": "$(message)",
                                "status": "$(status)"
                            }
                        },
                        "parameters" : [
                            { "name": "message", "defaultValue": "", "mandatory": false},
                            { "name": "status", "defaultValue": "ok", "mandatory": false }
                        ],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "preserve"
                            },
                            {
                                "status": [ 400 ],
                                "continuation": "fail",
                                "transformer": "preserve"
                            }
                        ]
                    },
                    "DCR.Sample.Mail" : {
                        "description": "Send a mail",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Mail",
                            "arguments": {
                                "body": "$(body)",
                                "to": "$(to)",
                                "subject": "$(subject)"
                            }
                        },
                        "parameters": [
                            { "name": "body" },
                            { "name": "to" },
                            { "name": "subject" }
                        ],
                        "outputs": [
                            {
                                "status": [ 202 ],
                                "continuation": "ok",
                                "transformer": "preserve"
                            },
                            {
                                "status": [ ],
                                "continuation": "fail",
                                "transformer": "preserve"
                            }
                        ]
                    },
                    "DCR.Sample.Http.QP" : { 
                        "description": "Issue GET request with qp authentication",
                        "implementation": {
                            "id": "DCR.Workflow.Effect.Http.Get",
                            "Arguments": {
                                "url": "http://localhost:8081/some/path?qp1=foo&qp2=bar"
                            },
                            "authentication": "QueryParam"
                        },
                        "parameters": [],
                        "outputs": [
                            {
                                "status": [ 200 ],
                                "continuation": "ok",
                                "transformer": "string"
                            }
                        ]
                    },
                    "Penneo.GetFiles": {
                        "description": "Get files from penneo (authorized with Wsse)",
                        "implementation": {
                          "id": "DCR.Workflow.Effect.Http.Get",
                          "Arguments": {
                            "url": "https://sandbox.penneo.com/api/v3/files",
                            "timeout": "20"
                          },
                          "authentication": "Penneo.Wsse"
                        },
                        "parameters": [],
                        "outputs": [
                          {
                            "status": [200],
                            "continuation": "ok",
                            "transformer": "string"
                          }
                        ]
                    }
                }
            }
        }
    }
}