Example of integration of ELMA with an external system

This article provides an example of automation of banking processes (customer service) with a BPM system. In this example, a BPM system implementation project is a part of a larger project of converting the operation of the bank offices.

Before the implementation of ELMA BPM, the employees of the bank offices interacted directly with various banking systems and systems for issuing plastic cards. Such an organization required each employee to be able to work in several systems and know the accounts and procedures used in the offices.

After the implementation of ELMA BPM, the work of the bank operators gradually shifted from direct interaction with banking systems to using automated business processes in ELMA, integrated with the banking systems. A major amount of information, necessary to use banking systems and perform operations with accounts correctly, was realized as objects in ELMA.

Scheme of the main integration components

The integration between the system was realized in the most convenient form, via web services. For some additional logic and checks, a transitional SOAP server is used; the systems exchange data via this server.

Custom activities in business processes

Since most of the web service methods are used many times and in many processes, it was decided to put their invocation and parser to custom activities, also known as plugins (standard ELMA feature).

A separate plugin with a set of input/output parameters and a logic for preparing and parsing the response was created for each method used in the process logic.

The logic implemented in each plugin can be generally described like this:

  1. Prepare input variables for the method.
  2. If necessary, generate a UID.
  3. Call the service method via Helper.
  4. Parse the response into output variables.

Prepare input variables

Input and output parameters are defined by the requirements of the process and the called method. It should be mentioned that service methods detect almost all the input parameters as strings, while processes use dates, numbers and objects. In the plugin code, such input parameters are prepared accordingly:

For strings, the value is checked for null, the excessive spaces at the start and end are deleted:

string sCIF = String.IsNullOrWhiteSpace(parameters.SearchCIF) ? "" : parameters.SearchCIF.Trim();
string sVOEN = String.IsNullOrWhiteSpace(parameters.SVOEN) ? "" : parameters.SVOEN.Trim();
 

For dates, integers, fractions and money, values are checked for null and converted into a string of the format, discussed with the developers of the service/method. For example, some methods detect dates in the format dd/MM/yyyy, while the standard format for the system localization is dd.MM.yyyy.

string p_charge= parameters.Charge.HasValue ? parameters.Charge.Value.ToString("F2").Replace(’,’,’.’) : "0"
p_original_start_date = parameters.StartDate.Value.ToString("dd-MM-yyyy");
 

For objects, the value is checked according to the method requirements in the service. For example, for methods of some external systems, the currency alphabetic code should be passed in the currency field, while for others - the numeric code:

if (parameters.User!=null && !String.IsNullOrWhiteSpace(parameters.User.FlexUser))
   {
    p_user = parameters.User.FlexUser;
   }
string p_branch ="";
if ( parameters.Branch!=null && !String.IsNullOrEmpty(parameters.Branch.BranchCode))
   {
    p_branch=parameters.Branch.BranchCode;
   }
 

Some input variables for methods are written in the plugin as constants. Usually, these are the parameters, which are not used in the current business cases, but are required for the target system:

string p_user_defined_status="NORM";// => ’NORM’, --const
string p_schedule_movement="Y";// => ’Y’, --const string p_verify_funds="P";// => ’P’, --const

Unique ID of MsgId call

An external system may support MsgId. This is a string input variable of each method, used to identify whether a message is new for the external system or a duplicate.

MsgId is generated on the ELMA side, using the static method WSHelper.GetMsgId(parameters.GetExecutionContext()). The input variable parameters GetExecutionContext() is present only in the plugins and contains the information about the process instance and a specific process element on the process map.

MsgId is generated by the following parameters:

  • Process instance Uid;
  • Process instance Uid (of an element on the process map);
  • values of the input variables.

Using these data, the hash for generating a unique MsgId of a strictly defined length is calculated.

Calling a method via WSHelper

A service method can be called by adding a WSDL reference and the connection initialization. To make some connection initialization functions multi-purpose, the method call was moved to a special class WSHepler, implemented in the module EleWise.ELMA.Bank. The method WSHelper.Execute<T,OutT>(…) executes the following functions:

1. Initialize the connection to the service (the WSDL reference should be added in the plugin).

2. Get an instance of the WSConnectionSettings object with the IsActive box, and apply the URL specified in it as the method endpointURL.

>This approach allows writing plugins once and later switch between the test and production SOAP from the web interface, by changing the IsActive property.

If the object does not have an instance with the IsActive box, the service is not called and Helper returns an error.

3. If the service is executed successfully, the XML response structure is checked.

4. In case of an exception on the channel level (Exception, TimeOutException, SOAPException) and the UseAutotry box in the active connection in the WSConnectionSettings object, Helper automatically checks the method call up to three times.

Important!
To avoid duplicating automatic method calls in case of temporary loss of connection between the SOAP and the external system, use the fully implemented logic of processing unique MsgIds.

 5. Upon each call (successful or unsuccessful) an entry in the WS Transaction Log object is created, with the following information:

  • method input variables;
  • service response;
  • description of the service response (usually one or several key fields in the response);
  • execution time: start, end, estimated duration, duration on the external system side;
  • transaction status on the channel level (before SOAP);
  • transaction status on the business logic level (error on the external system side, automatic repeat, successful execution);
  • link to the process, process instance, process map, process status (calculated based on the process UID);
  • call author (transactions, operations).

It should be noted that a transaction log entry is added in a separate stream and does not slow down the response in the process.

For this reason, it is difficult to directly write a link to a process and the exact time of receiving a response. Instead, the instance UID is used and all the additional information is loaded on the form.

Despite the fact that all the methods return a response in the XML format, Helper supports calling a method with any returned type. For obvious reasons, in this case, overhead information will not be received, but the response will return to the plugin correctly and an entry will be added to the log.

Parsing the service response

Since each method gets specific data in response (e.g. success indicator, transaction number, list of accounts), the response parser is implemented in the plugin code. There can be three response types:

  1. List of fields with values.
  2. List of objects you need to write to the objects.
  3. List of objects you need to write to a block in the process context.

Let's take a look at each of them.

  1. List of fields with values is the simplest option, since the obtained values are parsed into output variables in the plugin code. 
if (n.Name =="RESULT" && !String.IsNullOrWhiteSpace(n.InnerText))
   {
     parameters.ContractNumber=n.InnerText.Trim();
   }
if (n.Name =="FIFD" && !String.IsNullOrWhiteSpace(n.InnerText))
   {
    parameters.FIFD=n.InnerText.Trim();
   }

2. List of objects you need to write to an is a specific solution for saving data. For example, after receiving a list of accounts from the service, they are written to the Account object with a link to the process instance, for which the search was performed. Next, the list of accounts is displayed with the WorkflowInstance.Id filter on the task form in this process instance in the context variable and/or in the list of linked objects (standard form builder element, described here). 

var resultobject = new SearchResultCache();
resultobject.FullName = parameters.FullName;
resultobject.BirthDate = parameters.DateOfBirth;
resultobject.IdCardNumber=parameters.IdCardNumber;
resultobject.IsFlex=true;
resultobject.WorkFlowInstance=parameters.WorkFlowInstance;
resultobject.Save();

 Select Account task form looks like this:

3. The list of objects you need to write to a block in the process context is passed to the plugin output in the XML format, and then a script in the process parses it into the block rows.

You cannot create rows in a process context block in a plugin. For this reason, the code was moved to a script activity.