A dynamic logic function is the most generic type of dynamic logic: it can have one or more input arguments and return different types of output.A dynamic logic function is used to extend default behavior in certain areas.Each usage of dynamic logic functions is described in a separate paragraph below.

Data Collection Custom

Data can be collected from various sources in different ways.One of the supported ways is a custom dynamic logic.The following signature applies:

In / Out Name Type Description

In

Common Gateway Bindings

In

fileReader

DataFileReader

If there is a need to read files that were output of previous steps, then this object is available to fetch readers for the input files. The available types are:

  • jsonReader: a stream based json reader.

  • xmlReader: a stream based xml reader.

  • csvParser: a stream based CSV reader.

  • lineReader: a reader to support reading individual lines.

Out

n/a

String

Result of the custom logic.

This signature allows for making external service callouts.

Examples:

This example creates XML payload with integration code.Then it calls out an external service with the payload.Please refer to PreDefinedMethods: initCallOut to see the details of this method.

The result of the output is passed back as the map.

  import groovy.json.JsonSlurper

  /* Trigger the Get Request and set the query parameter to manipulate the response*/
  String response = webTarget("custom_destination")
                    .path("customData")
                    .queryParam("resultType", properties["resultType"])
                    .request().get()
                    .readEntity(String.class)

  def responseObject = new JsonSlurper().parseText(response)

  /* Add to properties if the next step should be run or not based on the response */
  properties.put("runExchangeStep",responseObject.isValid)

  /* Create the XML Response with the result returned in the response if there is result, else return null*/
  if(responseObject.result) {
    def writer = new StringWriter()
    def xml = new groovy.xml.MarkupBuilder(writer)
    xml.response(code:responseObject.result)
    return writer.toString()
  }

  return null

For more details on external callouts refer chapter External Callout in the guide

Data Transformation Payload

Data collected from the source systems may need to be transformed.The transformation is supported using dynamic logic.The following signature applies:

In / Out Name Type Description

In

Common Gateway Bindings

In

outputWriters

java.io.Writer

An outputWriter enables a dynamic logic to write to a destination data file. A handle to an outputWriter is obtained via this binding Additional writing assistance can be acquired by calling upon specific writer "flavors". These will wrap the writer in a more specific way. The following writer assistants are available:

  • jsonWriter: a stream based json writer.

  • xmlStreamWriter: a stream based XML writer.

  • csvPrinter: a stream based CSV writer.

  • lineWriter: a writer to support writing individual lines.

In

fileReader

DataFileReader

If the transformation is for type file, then this object is available to fetch readers for the input files. The available types are:

  • jsonReader: a stream based json reader.

  • xmlReader: a stream based xml reader.

  • csvParser: a stream based CSV reader.</li> <li>lineReader: a reader to support reading individual lines.</li> </ul>

Out

n/a

String

Optional. Result from the transformation. The transformation logic may also use pre defined methods to write out to a file.

Examples:

1: Data File Set Transformation: Example to transform DataFileSet retrieved from policies as an extract, the output name is extract and transforming it to flat lines.

 import com.google.gson.*;
 import com.google.gson.stream.JsonReader;

 def outputWriter = outputWriters
                    .getDataFileOutputWriter()
                    .lineWriter()

 int countOfRecords = 0;
 extract.getDataFiles().each { df ->
   def reader = fileReader.jsonReader(df);
   Gson gson = new GsonBuilder().create();
   // Read file in stream mode
   reader.beginArray();
   while (reader.hasNext()) {
   // Read data into object in a stream fashion
   def policy = gson.fromJson(reader,Map.class);
   def transformedResult = []
   ++countOfRecords;
   transformedResult.add(policy.code + " transformed");
   policy.policyEnrollmentList.each { pe ->
     transformedResult.add(pe.person.code);
     transformedResult.add(pe.person.dateOfBirth);
     transformedResult.add(pe.person.gender);
     pe.person.addressList.each { a ->
       transformedResult.add(a.city);
       transformedResult.add(a.houseNumber);
       transformedResult.add(a.street);
     }
     pe.policyEnrollmentProductList.each { pep ->
       transformedResult.add(pep.startDate);
     }
   }
   policy.policyStatusHistoryList.each { ps ->
     transformedResult.add(ps.gid);
     transformedResult.add(ps.status);
     transformedResult.add(ps.dateTime.value);
   }
   policy.policyholderList.each { ph ->
     transformedResult.add(ph.startDate);
     transformedResult.add(ph.endDate);
   }
   transformedResult.add("Other Versions: "+policy.policies.size());
     transformedResult.add(policy.attachedpolicydata.manual);
     outputWriter.write(transformedResult.join(", "));
     outputWriter.write("\n")
   }
   reader.endArray();
}
outputWriter.write("Number of Records: "+countOfRecords);

2: Raw Payload Transformation: Fetched data from Claims application, and returning another JSON payload to determine if the claim is APPROVED, if the amount is more than 0 and does not have Fatal messages, else it is DENIED.

import groovy.json.JsonSlurper
import groovy.json.JsonOutput
def json = " "
if (!binding.hasVariable("claimsData")) {
  println("missing parameter is not present within request.")
  json = JsonOutput.toJson([code: "No Claim Data Present"])
} else {
  def claimObject = new JsonSlurper().parseText(claimsData)
  def claimStatus= claimObject.amount > 0 ? "APPROVED": "DENIED"
  if(claimStatus=="APPROVED") {
    def containsFatalMessages = claimObject.claimMessages.any{it.severity=="F"}
    claimStatus = containsFatalMessages ? "DENIED" : "APPROVED"
  }
  json = JsonOutput.toJson([code: claimObject.code, type: claimObject.type, claimStatus: claimStatus])
}
return json;

For more details on Transformation refer to chapter Transformation Dynamic Logic in the guide

Parameter Extraction

If the integration invocation is through a payload that contains input parameters for the steps, this function helps in extracting those input parameters.The following signature applies:

In / Out Name Type Description

In

Common Gateway Bindings

In

integration

Integration

The Integration configuration that references the Parameter Extraction Dynamic Logic.

In

headers

HeadersObject

A custom object supporting <tt>Header Extraction</tt> (see next section)

Example: the integration can be is invoked by a message with this payload:

<group name="ACME">
  <member>
    12
    <name>Scott</name>
  </member>
 </group>

Suppose we need the group name and the member ID as input parameters for the data collection.The parameter extraction dynamic logic can be configured as shown below to extract the input parameters.

def rootNode = new XmlSlurper().parseText(trigger)
return [groupName:rootNode.@name.text(), memberId:rootNode.member.id]

Header Extraction

By default all HTTP Headers, excluding the security sensitive HTTP Headers, are made available as Exchange properties implicitly through Header Extraction.This way an HTTP Header can be used throughout the steps of an Exchange.Additionally, it is possible to set up Parameter Extraction dynamic logic with the means to, selectively mark (a subset of) these headers as response headers using predefined methods available on the header binding.These response headers are then automatically included when calling an external service or when returning the response for an Exchange that is executed in a synchronous/blocking fashion.As an example in the below code snippet, all HTTP Headers that start with 'hiconline' are marked as response headers that need to go out on the Exchange using a predefined method addResponseHeaders that takes in a Predicate.

import java.util.function.*

Predicate isEclipseHeader = { a ->
  a.key.startsWith('hiconline')
}

headers.addResponseHeaders(isEclipseHeader)

Additionally, a number of signatures are possible to add response headers using the Headers object.

Operation Description Example

addResponseHeader(String key)

Mark a request header by key as a response header

addResponseHeader('request-header-one')

addResponseHeaders(String…​keys)

Mark a collection of request headers by their keys as response headers

addResponseHeaders('request-header-one', 'request-header-two')

addResponseHeaders(Predicate<Map.Entry<String,?>>)

Mark a collection of request headers by a predicate as response headers

see the above example with isEclipseHeader predicate

Please note that HTTP Headers potentially can have multiple values per HTTP Header key.With respect to Header Extraction, only the first value is extracted in such a case.

Step Post Process

It is helpful in extracting relevant pieces of information from the just executed step to be used in the next step.The following signature applies:

In / Out Name Type Description

In

Common Gateway Bindings

In

fileReader

DataFileReader

If there is a need to read files that were output of previous steps, then this object is available to fetch readers for the input files. The available types are:

  • jsonReader: a stream based json reader.

  • xmlReader: a stream based xml reader.

  • csvParser: a stream based CSV reader.

  • lineReader: a reader to support reading individual lines.

Out

properties

Map

Updated properties collection containing properties that are extracted from the step’s output. Can also return null or empty map if there are no properties to update.

Example: The integration step returns queries claims for external claims data based on claim code and receives the following payload.The step’s output name is ecdData.The next step is to update the external claims data.For that it is required to extract the external claims data id to make the next step possible.

{
    "id": 484632,
    "settlementReason": {
        "id": 1,
        "links": [
            {
                "href": "<<enviroment>>/api/generic/settlementreasons/1",
                "rel": "canonical"
            }
        ]
    },
    "claim": {
        "id": 471238

    }
}

Example dynamic logic:

return ["external_claims_data_id":new JsonSlurper().parseText(ecdData).id]

Error Payload

It is helpful in constructing any technical error into a payload in order to invoke an external workflow or to notify an external system.The following signature applies:

In / Out Name Type Description

In

Common Gateway Bindings

In

exception

Exception

Exception that failed the exchange step and hence triggered this function. In some situations, external workflow can be invoked through localized integrations, whilst not failing the exchange (step). In that case the exception holds information as to what functional issue was observed.

In

fileReader

DataFileReader

If there is a need to read files that were output of previous steps, then this object is available to fetch readers for the input files. The available types are:

  • jsonReader: a stream based json reader.

  • xmlReader: a stream based xml reader.

  • csvParser: a stream based CSV reader.

  • lineReader: a reader to support reading individual lines.

Out

String

JSON Payload that needs to be sent out.

Example: The following function specifies logic to create JSON request to invoke a workflow when integration invocation fails

JSON

{ "type":"",
   "errors":[{
     "errorCode":"EXT_001",
      "errorText":"<error message>"
  }]
}

Dynamic logic:

import groovy.json.JsonBuilder

  def jsonBuilder = new JsonBuilder()
  def errorsJsonBuilder= new JsonBuilder()
  def errorArrayList= new ArrayList()
  def errors = {
                error(
                  errorCode: "EXT_001",
                  errorText: exception.message
                )
              }
              errorArrayList.add(errors)

   errorsJsonBuilder {
               type : exchangeStep.exchange.integration.code
               errorList(jsonBuilder.call(errorArrayList))

            }

 return errorsJsonBuilder.toString()

Invoke Function Payload

This is used in PROCESS type of integration step to return a payload to be used to invoke the process.The following signature applies:

In / Out Name Type Description

In

Common Gateway Bindings

In

fileReader

DataFileReader

If there is a need to read files that were output of previous steps, then this object is available to fetch readers for the input files. The available types are:

  • jsonReader: a stream based json reader.

  • xmlReader: a stream based xml reader.

  • csvParser: a stream based CSV reader.

  • lineReader: a reader to support reading individual lines.

Out

String

Payload that needs to be sent out for Process

Example: An integration to needs to a long-running process in an end application and it expects XML payload.

Example dynamic logic:

def writer = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(writer)
xml.process(
   description : "Registration set 001"
)
return writer.toString()

Subflow

It is used to provide list of parameters for invoking subflow.The size of the list of parameters is the number of times the subflow is triggered.The following signature applies:

In / Out Name Type Description

In

Common Gateway Bindings

In

exception

Exception

Exception that failed the exchange step and hence triggered this function.

In

fileReader

DataFileReader

If there is a need to read files that were output of previous steps, then this object is available to fetch readers for the input files. The available types are:

  • jsonReader: a stream based json reader.

  • xmlReader: a stream based xml reader.

  • csvParser: a stream based CSV reader.

  • lineReader: a reader to support reading individual lines.

In/Out

subflowStepParameters

SubflowStepParameters

List of "request parameters" map with which a sub exchanges get triggered.

Subflow Step Parameters

 It provides a structure to store a list of __Map of request
parameters__. The method addProperties can be used to add request parameters
required for a triggering a single subflow.
  • addProperties(Map<String,Object> properties): The map of properties for subflow invocation.

The order in which the method addProperties get called on the subflowStepParameters object determines the order in which the subflow gets triggered for sequential the processing.

Example:

Adding parameters for invoking the subflow twice, once with file ProviderImportInsert.csv and other with file ProviderImportUpdate.csv.

subflowStepParameters.addProperties([dataFileCode:"ProviderImportInsert.csv"])
subflowStepParameters.addProperties([dataFileCode:"ProviderImportUpdate.csv"])

Example:

This below code results in the invocation of four subflows with groupAccountCode as request parameter.

subflowStepParameters.addProperties([groupAccountCode:"ABC"])
subflowStepParameters.addProperties([groupAccountCode:"DEF"])
subflowStepParameters.addProperties([groupAccountCode:"GHI"])
subflowStepParameters.addProperties([groupAccountCode:"JKL"])

Notification Payload Extractor

If the integration invokes a process that wishes to resume the exchange after completion.It can do so by sending a notification to the gateway with the relevant correlationId in its header or as part of the notification payload.In case the notification payload is the specific format that the Notification Integration Point accepts, the Integration Gateway framework reads the notification and resume the process.It is, however also possible to resume the exchange using a custom payload, for example, a claim event.In case it is a custom format, this signature can be used to extract notification payload from the custom payload.This logic is configured on the process step that wishes to resume the exchange with custom payload.

In / Out Name Type Description

In

Common Gateway Bindings

In

notificationPayload

String

The custom payload that resumes the exchange through notification endpoint.

In

notification

Notification

Notification Object to contain the notification specific details, like status, links for data collection, messages and recovery.

Example: the exchange is invoked with a claim status response containing links:

{
  "status" : "FINALIZED",
  "links" : [{
      "rel": "claimmessages",
      "href": "http://localhost:8080/oig/api/claimmessages"
   }
  ]
}

The notification payload extractor dynamic logic configured in the Process Step configuration is invoked to extract the Notification object.Example dynamic logic:

import groovy.json.JsonSlurper
def claimObject = new JsonSlurper().parseText(notificationPayload)
def recoveryLink = false

if(claimObject.links != null) {
  for(int ctr=0;ctr<claimObject.links.size();++ctr) {
    def rel = claimObject.links[ctr].rel
    if(rel.contains("messages")) {
      rel = "messages";
    }
    if(rel.contains("recovery")) {
      recoveryLink = true
    }
    notification.addLink(rel, claimObject.links[ctr].href);
  }
}
if(claimObject.status==null) {
  notification.status= recoveryLink ? "Failure" : "Success"; } else {
  notification.status = (claimObject.status == "FINALIZED") ? "Success": "Failure"
}

Notification

Structure to store notification details. Following methods are available through the notification object to add more context.

  • notification.status or notification.setStatus(String): The string value can either be 'Failure' or Success'.

  • addLink(String rel, String href): To add links on the notification

See above for example.

Reusable Code

This is a common signature, available in all the applications. This signature has no bindings. It allows for writing standalone methods/reusable classes code that can be shared across other scripts.

Extension

This is a common signature, available in all the applications. This signature has no bindings. It allows for writing extensions to the dynamic logic scripts that are delivered by the product.