Functions

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 or Out Name Type Description

In

Gateway Dynamic Logic 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.

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 is 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

To disable automatic redirect and to avoid 303 response code in a POST call, include the property jersey.config.client.followRedirects:

Response response = webTarget("custom_destination")
  .path("customData")
  .request()
  .property("jersey.config.client.followRedirects", Boolean.FALSE)
  .build("POST")
  .invoke()

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 or Out Name Type Description

In

Gateway Dynamic Logic Bindings

In

outputWriters

java.io.Writer

An outputWriter writes data to a destination data file in a dynamic logic. You can access the outputWriter by calling the outputWriters.getDataFileOutputWriter() method. The method creates a data file set for each transformation. The outputWriters.getDataFileOutputWriter("file name", "application/json") method creates a datafile with the name, "filename", within a data file set. Other writers write to other file types, such as

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

  • lineReader: a reader to support reading individual lines.

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

  • 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)
  • 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

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 or Out Name Type Description

In

Gateway Dynamic Logic 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 about the functional issue that was observed. In case of exchange time out, the exception holds information about the integration or the integration step that timed out.

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()

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.

A dynamic logic function of signature Extension should be accompanied with a reference to the base dynamic logic and vice-versa (OHI-DYLO-031). The referenced base dynamic logic function cannot be of signature Reusable Code or Extension (OHI-DYLO-030).

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 or Out Name Type Description

In

Gateway Dynamic Logic 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 invoke 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()

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 or Out Name Type Description

In

Gateway Dynamic Logic Bindings

In

integration

Integration

The Integration configuration that references the Parameter Extraction Dynamic Logic.

In

headers

HeadersObject

A custom object supporting Header Extraction (see next section)

Out

Not Applicable

Map

Result from the extraction of parameters from input payload.

Example: Invoke an integration through a message with this payload:

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

For example, a group name needs a 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-on", "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.

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.

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 or Out Name Type Description

In

Gateway Dynamic Logic 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"
}

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.

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 or Out Name Type Description

In

Gateway Dynamic Logic 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 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": "<<environment>>/api/generic/settlementreasons/1",
                "rel": "canonical"
            }
        ]
    },
    "claim": {
        "id": 471238

    }
}

Example dynamic logic:

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

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 or Out Name Type Description

In

Gateway Dynamic Logic 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 or 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"])

Test Unit

A dynamic logic with the Test Unit signature tests another dynamic logic. Such a dynamic logic that runs a test on another dynamic logic is called a test case. A test case sends objects as input to the unit under test (UUT) and validates the output.

In or Out Name Type Description

Out

Not Available

Boolean

Returns true if the test case ran successfully, false otherwise.

You can run a test case using the Test Dynamic Logic Integration Point.