Professional Documents
Culture Documents
Adapter SDK Manual (GVT 140327 001)
Adapter SDK Manual (GVT 140327 001)
Adapter SDK Manual (GVT 140327 001)
NEC Platforms, Ltd. has prepared this document for the exclusive use of its employees and
customers. The information contained herein is the property of NEC Platforms, Ltd. and shall not be
reproduced without prior written approval from NEC Platforms, Ltd..
Microsoft®, Windows® and Visual Studio® are registered trademarks of Microsoft Corporation in
the United States and other countries. Linux® is a registered trademark or trademark of Linus
Torvalds in the United States and other countries.
All other brand or product names are or may be trademarks or registered trademarks of, and are
used to identify products or services of, their respective owners.
2 / 23
Table of Contents
Liability Disclaimer .......................................................................................................... 2
INecLogger ................................................................................................................................................................................... 14
Example ........................................................................................................................................................................................ 14
Configuration ................................................................................................................................................................................ 14
AdapterCommandRequest ........................................................................................................................................................... 19
AdapterCommandResponse......................................................................................................................................................... 20
AdapterConfig ............................................................................................................................................................................... 20
AdapterEventNotification .............................................................................................................................................................. 21
AdapterWebhookNotification ........................................................................................................................................................ 21
AdapterPropertyBag ..................................................................................................................................................................... 22
3 / 23
Adapter SDK – QuickStart Guide
This article contains guidelines for a user to develop and deploy an Adapter using the Adapter SDK
provided by NEC.
Tools Used
The following tools are required for developing and deploying adapters using the SDK:
Docker for Windows/Linux available on the deployment machine (only required if publishing
the adapters as Internal Adapters)
Prerequisites
.NET Core SDK on the machine developing adapters using the SDK
UIP system
Inside the Adapter SDK zip archive, you will find the following:
As an External Adapter
4 / 23
o The adapter is running as a process on a system other than the one hosting UIP; it
can be either Windows or Linux based. This is the preferred way of testing an adapter
that you are writing, since you can run it and debug it from the development machine.
The Adapter Proxy service will handle the communication between the adapter and
UIP.
As an Internal Adapter
o The adapter is running on the UIP system inside its own Docker container, and
communicates directly with UIP services.
config folder, containing a JSON file, which is a sample adapter's configuration file used
when adding the adapter in the UIP Manager (more details below).
o dependencies.props: This file contains the versions of the SDK NuGet packages.
The most important lines of the file are the ones containing
the NecWFAdapterBasePackageVersion, which is the version of the SDK used for
External Adapters, and the NecWFAdapterBaseHttpPackageVersion, which is the
version of the SDK used for Internal Adapters. You will reference either one of them
depending on how you want to deploy the adapter. The other versions are for the SDK
dependency packages.
o Directory.Build.props: This is the file that uses the dependencies.props file, and the
place where you specify which of the SDKs you are using. If you intend to deploy your
adapter as External, then set NecAdapterSdkSource to pipe. If you intend to
deploy it as Internal set it to http
autobuild.proj: a MSBuild script provided for convenience to help you deploy the adapter.
pub.cmd: a script provided for convenience to help you deploy the adapter as External from
a Windows system.
pub_docker.cmd: a script provided for convenience to help you deploy the adapter as
Internal from a Windows system.
Dockerfile: the file used to create the Docker Image containing the adapter (when
publishing the adapter as Internal).
update_cacerts.sh: a script that needs to be copied inside the /app folder of the Docker
Image. This is used to update the certification authorities in order to install third party or
self-signed certificates for UIP. This script can be used for Debian-based adapter images. The
provided Dockerfile also sets the environment variable NECWF_CERT_SCRIPT used to
determine the location of the script.
wfconfig.json: an exported UIP configuration file provided for convenience. This file can be
imported in the UIP Manager, and will restore all the Workflows, Adapters and Triggers used
to test the Sample Adapter.
wfadaptersample.sln: the Visual Studio solution file for the Sample Adapter.
5 / 23
The Adapter Type file
Inside the config folder you can locate the adapterType-sample.json file. This is the Sample
Adapter's configuration file. The config file is a JSON with the following format:
{
"name": "adapter_name",
"display": "Adapter Display Name",
"version": "1.0.0",
"dockerimage": "docker.io/dockeruser/wfadaptersample:1.0.0",
"folder": "obsolete and no longer used",
"executable": "obsolete and no longer used",
"commandline": "obsolete and no longer used",
"startup": "obsolete and no longer used",
"properties": [
{
"name": "adapter_property_name",
"display": "Adapter Property Display Name",
"helptext": "Adapter Property Tooltip text",
"type": "string",
"required": "true",
"defaultValue": "Default Adapter Property value",
"maximumLength": "1024"
}
],
"commands": {
"command_name": {
"display": "Command Display Name",
"description": "Command Description",
"request": {
"command_input_parameter_name": {
"display": "Command Input Parameter Display Name",
"description": "Command Input Parameter description",
"type": "string",
"required": "true"
}
},
"result": {
"command_output_parameter_name": {
"display": "Command Output Parameter Display Name",
"description": "Command Output Parameter description",
"type": "string"
}
}
}
},
"events": {
"event_name": {
"display": "Event Display Name",
"description": "Event Description",
"properties": {
"event_property_name": {
"display": "Event Property Display Name",
"description": "Event Property description",
"type": "string"
}
}
}
},
"localization": {
"en": {
"display": "Property Display Name",
"helptext": "Property Tooltip text",
"properties": {
"adapter_property_name": {
6 / 23
"display": "Adapter Property Display Name",
"helptext": "Adapter Property Tooltip text"
}
},
"commands": {
"command_name": {
"display": "Command Display Name",
"description": "Command Description",
"request": {
"command_input_parameter_name": {
"display": "Command Input Parameter Display Name",
"description": "Command Input Parameter description"
}
},
"result": {
"command_output_parameter_name": {
"display": "Command Output Parameter Display Name",
"description": "Command Output Parameter description"
}
}
}
},
"events": {
"event_name": {
"display": "Event Display Name",
"description": "Event Description",
"properties": {
"event_property": {
"display": "Event Property Display Name",
"description": "Event Property description",
}
}
}
}
}
},
"image": {
"data": "data:image/png;base64,xxxxxxxxxxxxxx"
}
}
If you want to publish the adapter as Internal you need to provide the target image path inside
the dockerimage property; otherwise this property is not required.
Properties
The configuration properties required for an adapter instance, used as input for configuring the
adapter when it is run. Multiple properties may be defined in this section.
The name is used to identify this property in the AdapterConfiguration received as the adapter
starts.
The other properties (display and helptext) are used to generate the user interface for configuring
an adapter in UIP Manager.
If the property is mandatory, you must set the required value to "true", otherwise set it to "false".
7 / 23
Commands
This section is not required, due to the dynamic nature of UIP, but it is a good idea to include it in
the adapter type configuration to make it easier for the workflow editors to discover commands
supported by an adapter.
This describes the command actions provided by the adapter. Each command has a display name, a
description, a lists of input properties and output properties. Input properties are defined under
the request field while the output properties are defined under the result field. Each command is a
new named attribute of the commands object, not an array.
Events
This section is also not required, but metadata from this section will be used in the UIP Manager for
autocomplete, so it should be included.
This describes the events provided by the adapter. The events also have properties, and they are usually
passed to the workflows that are triggered by the events. Each event is a new named attribute of the events
object, not an array.Localization
This section is also not required. You can specify translation strings if needed for various languages
(fr, jp, es, etc.)
Image
In this section you can specify an image to be displayed as an icon for the adapter inside UIP pages.
The xxxxxxxxxxxxxx in the example above replaces a 128X128 PNG image converted to a base64
string. If including an image, don't forget to strip the metadata from your image prior to converting
it to base64 to reduce its size.
WfAdapterBase: This one is for building External Adapters and is the default SDK referenced
by the Adapter Sample.
WfAdapterBaseHttp: This one is for building Internal Adapters and is enhanced to allow
internal communication with UIP over HTTP.
You can either manually build the adapter (using Visual Studio), or you can use one of the two
provided helper scripts (pub.cmd and pub_docker.cmd) that will build and then publish the adapter
on your local machine.
When building the adapter as External using Visual Studio make sure you reference the correct SDK.
The NecAdapterSdkSource property from build\Directory.Build.props must be set to pipe.
You can also manually build the project using the following command:
8 / 23
After you build the adapter, you should copy the build output to a folder on the system where you
want to deploy the adapter. You must have the Adapter Proxy service installed on the same system
in order to deploy the adapter as External.
For External Adapters you also need to copy the log4net.config file (located in the
WFAdapterSample\src folder) into the same folder as the published adapter files. This file contains
the configuration for the logging framework used by the External Adapters.
Next, you should change the Adapter Proxy configuration file to include your adapter. This file is
located by default in %ProgramData%\NEC\workflow\adapterproxy.example.json. Copy and rename
this file to "adapterproxy.json" and change its content. It should look like the following example:
{
"server": {
"websocketurl": "wss://uipserver.example.com",
"secret": "shared-secret"
},
"proxy": {
"http_proxy": "",
"https_proxy": "",
"ftp_proxy": "",
"all_proxy": "",
"no_proxy": ""
},
"adapters": {
"SampleAdapter": {
"token": "sampleAdapterToken123",
"enabled": true,
"folder": "D:/UIP/publish/WFAdapterSample/",
"executable": "dotnet",
"commandline": "WFAdapterSample.dll {name}"
}
}
}
o The secret is a string which is used to validate between the Adapter Proxy and the UIP
system. So, if we specified "mysecret" as the secret in the Adapter Proxy configuration
file, we will have to also specify "mysecret" under the "Administration > Workflow
> External Adapter Connection Secret" setting inside the UIP Manager.
o Set all_proxy when a protocol specified proxy is not set (i.e. - http_proxy,
https_proxy and ftp_proxy).
adapters: List of adapters managed by the Adapter Proxy. Here you should add the startup
info of any adapter you want to run externally. The root element is the adapter name. In our
case: "SampleAdapter". This is the name used for logging adapter specific messages.
9 / 23
o The token is a unique string for each external adapter and must match the value you
set under the "Adapters > Add Adapter > External Token" setting when you create an
External Adapter in the UIP Manager. The adapter proxy can be used to run multiple
adapters, but no adapters can have the same token.
o The folder property is the location of the published adapter's binary files on the local
machine.
o The executable and commandline properties are used to construct the command that
will launch our adapter. Since in our case the adapter was published as portable, we
will use "dotnet" as the executable and the portable dll name in the commandline.
The {name} variable is used to pass along the adapter name specified when creating
the adapter in the UIP Manager.
After updating adapterproxy.json, you need to restart the Adapter Proxy service in order for the
changes to take effect. You will find it as "NEC Workflow Adapter Proxy" in the services list (run
services.msc on Windows).
To publish the Sample Adapter you can also use the provided pub.cmd script, which will build the
adapter as External using the appropriate SDK package and copy the binary files and the Adapter
Type file in the publish folder at the root folder of the solution. The script will build both a portable
version and a Windows executable version for the adapter. You will still need to modify
the adapterproxy.json file in order to use it.
Modify the proxy secret in UIP Manager: Browse to UIP Manager, under Administration >
Workflow, modify External Adapter Connection Secret to match the secret value in the
adapterproxy.json. Note that this can be left blank/empty (not recommended) but, in that
case, it should be empty on both places.
Create the adapter by using the Adapters > "Add Adapter" button in UIP Manager. Specify
the adapter Type and a Name. If you have imported the Adapter Type file in UIP, you should
be able to select it from the Type dropdown list.
Assuming the Adapter Proxy is running, the adapter should start in a few seconds and be ready to
use.
10 / 23
Publishing the Adapter as Internal
When building the adapter as Internal using Visual Studio, make sure you reference the correct
SDK. The NecAdapterSdkSource property from build\Directory.Build.props must be set to http.
You can also manually build the Project using the following command:
After you build the adapter, you should copy the build output to a folder from where you will create
the Docker image of the Adapter. Make sure you build a portable version since the binaries will run
on a Linux machine. Additionally, copy the "update_cacerts.sh" file, which is required to build a
proper Adapter Docker Image.
The "update_cacerts.sh" file must have execute permission. Grant execute permission with the
chmod command.
Modify the provided Dockerfile to reflect the correct filename of your Adapter binary:
Change the current folder to the folder where your adapter binaries are located and run the
following command to build the Docker image
Example:
Please make sure the repository you are using is public, otherwise the UIP system will not be able to
access it.
To publishing the Sample Adapter you can also use the provided pub_docker.cmd script that will
build the adapter as Internal using the appropriate SDK package, copy the binary files and the
Adapter Type file in the publish folder in the root of the solution, update the Adapter Type file with
the docker image name (more details below), and publish the Docker image for you. Just make sure
you edit the script and replace the existing repository with a valid one.
11 / 23
Create the Internal Adapter in UIP Manager
At this point you should have the adapter's Docker image available in your repository.
Before importing the Adapter Type file into UIP, you need to make sure that the Docker image path
is correctly specified in your Adapter Type file (e.g. - "dockerimage":
"docker.io/dockeruser/wfadaptersample:1.0.1").
Import the Adapter Type file (located in the config folder in our Sample Adapter) in UIP
Manager: Adapter Types > "Import Adapter Type From File" button
Create the adapter by using the Adapters > "Add Adapter" button in UIP Manager. Specify
the adapter Type and a Name. If you have imported the Adapter Type file in UIP, you should
be able to select it from the Type dropdown list.
The adapter should start in a few seconds and be ready to use. This may take longer than an
External Adapter since the UIP system has to pull the Docker image and create a Docker service
from it.
To test the Sample Adapter we provided a UIP configuration file (wfconfig.json located in the root of
the solution) that you can import into UIP. This will create the setup required to test the Sample
Adapter as an Internal Adapter.
Before importing this configuration, edit the file and replace the dockerimage value with the
correct value that you used to publish the Adapter's Docker image. Also, ensure that you add the
Email Sender adapter type from the Adapter Types > Adapter Type Store in UIP Manager.
A second Adapter called EmailSenderAdapter used to send emails. You will need to modify
the email authentication credentials and the SMTP Server Address with proper values.
A trigger called SampleTrigger that will execute when the SampleAdapter's event happens
To test the Adapter, press edit on the SampleSendMessageWorkflow and then test it. The workflow
should use the SendCommand command of the adapter, which will fire the adapter's event, passing
the message property to it. The Trigger should catch the event and launch the second workflow,
which will send an email with the message configured in the first workflow and the message
signature configured in the adapter's properties.
12 / 23
Understanding the Workflow Adapter SDK
Adapter Lifecycle
One adapter process is started for each configured adapter. For an adapter type, multiple
adapter processes could be started, each with their own distinct names and properties.
Adapter processes are started by UIP for internal adapters and by the adapter proxy for
external adapters.
o The adapter process expects the adapterId as the first command line parameter.
o Configuration is received from UIP (the properties of the adapter are set in the UIP
Manager.
The logger makes use of a log4net.config file for controlling log level, output, message format, and
other logging aspects.
NecLogManager
Static class containing factory methods for the INecLogger.
13 / 23
The provided loggers are of the same type as the loggers used throughout UIP.
NecLogManager
INecLogger
This interface provides the standard logging methods
Nec.WFCommon.Logging
interface INecLogger
{
bool IsDebugEnabled { get; }
bool IsInfoEnabled { get; }
bool IsWarnEnabled { get; }
bool IsErrorEnabled { get; }
bool IsFatalEnabled { get; }
Example
Logging Example
try
{
// ...
}
catch(Exception ex)
{
log.Error("Some error", ex);
throw;
}
Configuration
The logger makes use of a log4net.config file for controlling log level, output, message format, and other
logging aspects.
log4net.config
14 / 23
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="Threshold" value="ALL" />
<param name="File" type="log4net.Util.PatternString" value="%property{LogFolder
}/adapter-%property{ProviderName}.txt" />
<param name="AppendToFile" value="true" />
<param name="RollingStyle" value="Size" />
<param name="MaxSizeRollBackups" value="50" />
<param name="MaximumFileSize" value="20MB" />
<param name="StaticLogFileName" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="Header" value="#### Logging started #### " />
<param name="Footer" value="#### Logging ended #### " />
<param name="ConversionPattern" value="[%d] [%t] %-6p %c{3}: %m %n" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingFileAppender" />
<!--<appender-ref ref="ConsoleAppender" />-->
</root>
</log4net>
AdapterRunner
AdapterRunner
Should be used in your adapter’s Main method to start a new adapter, derived from type
BaseAdapter<ContextType>.
This way all the infrastructure related to adapter starting, configuration, and communication is
created.
AdapterRunner Example
15 / 23
WFAdapterBaseHttp NuGet Package
Contains helpers for running an Internal adapter. The AdapterRunner usage is identical when targeting this
package instead of WFAdapterBase, but the underlying infrastructure for starting, configuration, and
communication is different.
Contains classes required for working with the adapter infrastructure, such as BaseAdapter<ContextType>
(that allows defining a new adapter), status, notification, request, and response objects.
Nec.WFAdapter.Adapter
BaseAdapter<ContextType>
This is the base abstract class for all adapters.
BaseAdapter<ContextType>
Constructor
16 / 23
The adapter using this base should have a constructor that provides only AdapterConfig and
AdapterHandlers. These will be created by the SDK helpers when launching the adapter.
When calling the base constructor, an instance of INecLogger should be provided, like in the
following example. The code calling the constructor will not attempt to inject a logger.
AdapterSample Constructor
AddCommand
This will add to the adapter a command that will be executed when requested by UIP.
The command name should be known by UIP and included in The Adapter Type file.
The request object contains details about the current request and are set by the command workflow
step. The context is the ContextInstance set during initialization of this adapter.
AddCommand Example
AdapterConfig
The Adapter Type file contains a properties section that describe the required configuration of this
adapter.
Values for these properties are set in the UIP Manager and will be sent to the adapter after starting
it (when the Start method is called).
Example configuration can include external system address, connection string, access tokens, retry
count, and any other data that is required by the adapter.
For each adapter defined in the UIP Manager, one instance of the Adapter will run. Each process will
receive its own configuration in the AdapterConfig object, including Name of the adapter,
CustomerId (tenant) and a dictionary of properties.
17 / 23
AdapterConfig Example
// Read adapter configuration properties. These are specified in adapter type json
file.
AdapterConfig.Properties.TryGetValue("notificationsConnectionString", out string no
tificationsConnectionString);
AdapterConfig.Properties.TryGetValue("serverUrl", out string serverUrl);
Start
Initialization method called by the adapter helpers after configuration was received from UIP.
Here, configuration should be read and validated and the ContextInstance should be set.
ContextInstance
The context instance will be set during initialization of the adapter, for example in the Start method,
and will be provided on each incoming command request.
The context instance has the type defined by the adapter author and is passed as the generic type
parameter to the BaseAdapter. This type is used to store relevant data for processing each request.
ContextInstance Example
try
{
ContextInstance = Context.Create( /* ... */ );
Log.Debug("Adapter Started.");
}
catch (Exception ex)
{
Log.Fatal("Adapter cannot start.", ex);
this.StatusNotifier.StatusFaulted("Could not connect to external system.");
}
EventSender
Can be used to create a notification event/webhook and to send it to UIP. This interface should be used
whenever there is an event or a webhook to be handled in UIP.
IAdapterEventSender
The event name can be documented as part of The Adapter Type file and can be used by triggers to
monitor a specific event.
18 / 23
WebhookSend Example (Webhook)
OnAdapterReady
This method is called by the adapter helpers after adapter is ready to receive commands and send
events.
Here, in order to send events and webhooks, implement process to start receiving data from the
external system.
StatusNotifier
Should be used whenever adapter status changes, to notify UIP if the adapter is working as
expected or not.
IAdapterStatusNotifier
This interface an also be used in the Start method of the adapter to signal if there were any errors
encountered during initialization.
StatusNotifier Example
try
{
// initialization
}
catch (Exception)
{
this.StatusNotifier.StatusFaulted("Could not connect external system.");
}
Shutdown
AdapterCommandRequest
Is received as a parameter on the method that handles a command (the AdapterCommandHandler).
The AdapterCommandRequest contains properties set by the workflow command step which
requested the execution of the command.
Use the CreateResponse factory method to create a response object to send back and confirm the
execution of the command.
AdapterCommandRequest
19 / 23
public sealed class AdapterCommandRequest
{
public string Id { get; set; }
public string CustomerId { get; set; }
public string AdapterName { get; set; }
public string CommandName { get; set; }
public string Sender { get; set; }
public AdapterPropertyBag Properties { get; set; }
public string ReportId { get; set; }
AdapterCommandResponse
The object returned by the method handling a command, confirming that the command was
executed.
Do not instantiate this object directly; use the factory method CreateResponse on the
AdapterCommandRequest object.
Use the SetProperty method to add properties to the response. These properties will be sent back to
the calling workflow and will be available as part of the result of the command to the next workflow
step.
If the command is not successful, use the SetFailed method to mark the response as failed and to
set a failure code and message.
In the command handling method, it is not mandatory to await command execution on the external
system. Fire and forget commands are also allowed.
AdapterCommandResponse
AdapterConfig
When the Adapter is started, the first thing it will do is to wait for configuration information from
UIP.
The required configuration properties are described in The Adapter Type file, and will be available
when defining a new adapter in UIP Manager.
20 / 23
The properties configured in UIP Manager for this specific adapter will be added in the Properties
dictionary available in the AdapterConfig object.
AdapterConfig
AdapterEventNotification
Whenever an adapter needs to notify UIP about some event, an AdapterEventNotification object
should be created. Do not create this object directly, but use the factory method of the EventSender
to make sure that relevant properties are set.
AdapterEventNotification
AdapterWebhookNotification
Whenever an adapter needs to notify UIP about a webhook, an AdapterWebhookNotification object
should be created. Do not create this object directly, but use the factory method of the EventSender
to make sure that relevant properties are set.
AdapterWebhookNotification
21 / 23
AdapterPropertyBag
This dictionary is used for all objects that are included in the adapter - workflow communication, to
define configurable properties.
Can also include properties that are not defined in The Adapter Type file. This is the dynamic nature
of the workflow.
AdapterPropertyBag
22 / 23
UNIVERGE Integration Platform
Adapter SDK Manual
Caution
(1) Unauthorized reproduction of all or part of this document is prohibited.
(2) The contents of this document would be changed without prior notice.
2-1 / 23