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