IdentitySync Custom Scripts

Skip to end of metadata
Go to start of metadata

Overview

IdentitySync offers you the option of writing your own custom scripts to use in a dataflow. A custom JavaScript step receives a user record as an input, manipulates it, and produces the record as an output. The ability to execute self-written scripts gives you extensive flexibility to maximize IdentitySync to suit your needs.

Including a Custom Script in Your Dataflow

Custom scripts are included in a dataflow by using a record.evaluate step, and inserting the script as a Base64 encoded string in the "script" parameter of the step. See Script Repository for more information. 

 Click for a full dataflow example that includes a records.evaluate custom step
{
    "name" : "Export from Gigya to SFTP",
    "description" : "account > rename > transform > dsv > gzip > sftp",
    "steps" : [{
            "id" : "account",
            "type" : "datasource.read.gigya.account",
            "params" : {
                "select" : "profile"
            },
            "next" : ["rename"]
        }, {
            "id" : "rename",
            "type" : "field.rename",
            "params" : {
                "fields" : [{
                        "sourceField" : "profile.email",
                        "targetField" : "MAIL"
                    }, {
                        "sourceField" : "profile.lastName",
                        "targetField" : "NAME"
                    }, {
                        "sourceField" : "profile.firstName",
                        "targetField" : "FIRSTNAME"
                    }, {
                        "sourceField" : "profile.gender",
                        "targetField" : "GENDER"
                    }, {
                        "sourceField" : "profile.birthDay",
                        "targetField" : "BIRTH_DAY"
                    }, {
                        "sourceField" : "profile.birthMonth",
                        "targetField" : "BIRTH_MONTH"
                    }, {
                        "sourceField" : "profile.birthYear",
                        "targetField" : "BIRTH_YEAR"
                    }
                ]
            },
            "next" : ["evaluate"]
        }, {
            "id" : "evaluate",
            "type" : "record.evaluate",
            "params" : {
// Use a Base64 decoder to view the following script
                "script" : "aW1wb3J0UGFja2FnZShqYXZhLmlvKTsNCmltcG9ydENsYXNzKGphdmEudGV4dC5TaW1wbGVEYXRlRm9ybWF0KTsNCg0KdmFyIHdyaXRlcjsNCnZhciBmaWxlOw0KdmFyIHByZXR0eTsNCg0KZnVuY3Rpb24gcHJvY2VzcyhyZWNvcmQsIG5leHQsIGN0eCkgew0KICAgIHZhciBjb3VudCA9IGdldENvdW50KGN0eCk7DQogICAgaW5pdChjdHgsIGNvdW50KTsNCg0KICAgIGlmIChjb3VudCA9PSAwKSB7DQogICAgICAgIGlmIChyZWNvcmQgIT0gbnVsbCkgew0KICAgICAgICAgICAgb3Blbih3cml0ZXIsIHByZXR0eSkNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIHJldHVybjsNCiAgICAgICAgfQ0KICAgIH0NCiAgICBpZiAocmVjb3JkICE9IG51bGwpIHsNCiAgICAgICAgaWYgKGNvdW50ID4gMCkgew0KICAgICAgICAgICAgd3JpdGVyLndyaXRlKCIsIik7DQogICAgICAgICAgICBpZihwcmV0dHkgPT0gdHJ1ZSkgew0KICAgICAgICAgICAgICAgIHdyaXRlci5uZXdMaW5lKCk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgd3JpdGVyLndyaXRlKHJlY29yZC50b0pzb24oKSk7DQogICAgICAgIHNldENvdW50KGN0eCwgY291bnQgKyAxKTsNCiAgICB9IGVsc2Ugew0KICAgICAgICBjbG9zZSh3cml0ZXIsIHByZXR0eSk7DQogICAgICAgIG5leHQuYWNjZXB0KGZpbGUpOw0KICAgIH0NCn0NCg0KZnVuY3Rpb24gaW5pdChjdHgsIGNvdW50KSB7DQogICAgaWYgKGNvdW50ID09IDApIHsNCiAgICAgICAgdmFyIGRhdGVQYXR0ZXJuID0gY3R4LmdldFBhcmFtZXRlcigiZmlsZURhdGVGb3JtYXQiKTsNCiAgICAgICAgaWYgKGRhdGVQYXR0ZXJuID09IG51bGwpIHsNCiAgICAgICAgICAgIGRhdGVQYXR0ZXJuID0gInl5eXlNTWRkX0hIbW0iOw0KICAgICAgICB9DQogICAgICAgIHZhciBmaWxlTmFtZSA9IGN0eC5nZXRQYXJhbWV0ZXIoImZpbGVQcmVmaXgiKSArIG5ldyBTaW1wbGVEYXRlRm9ybWF0KGRhdGVQYXR0ZXJuKS5mb3JtYXQoY3R4LmdldFBhcmFtZXRlcigiY3VycmVudEpvYlN0YXJ0VGltZSIpKSArIGN0eC5nZXRQYXJhbWV0ZXIoImZpbGVTdWZmaXgiKSArICIuanNvbiI7DQogICAgICAgIGZpbGUgPSBuZXcgRmlsZShjdHguZ2V0V29ya2luZ0RpcmVjdG9yeSgpLCBmaWxlTmFtZSk7DQogICAgICAgIGN0eC5zZXRTZXNzaW9uUGFyYW1ldGVyKCJmaWxlIiwgZmlsZSk7DQogICAgICAgIGN0eC5zZXRTZXNzaW9uUGFyYW1ldGVyKCJ3cml0ZXIiLCBuZXcgQnVmZmVyZWRXcml0ZXIobmV3IEZpbGVXcml0ZXIoZmlsZSwgdHJ1ZSkpKTsNCiAgICB9DQogICAgZmlsZSA9IGN0eC5nZXRTZXNzaW9uUGFyYW1ldGVyKCJmaWxlIik7DQogICAgd3JpdGVyID0gY3R4LmdldFNlc3Npb25QYXJhbWV0ZXIoIndyaXRlciIpOw0KICAgIHByZXR0eSA9IGN0eC5nZXRQYXJhbWV0ZXIoInByZXR0eSIpOw0KICAgIHByZXR0eSA9IHByZXR0eSAhPSBudWxsID8gcHJldHR5IDogdHJ1ZTsNCn0NCg0KZnVuY3Rpb24gb3Blbih3cml0ZXIsIHByZXR0eSkgew0KICAgIHdyaXRlci53cml0ZSgie1wicmVzdWx0c1wiOiIpDQogICAgaWYocHJldHR5ID09IHRydWUpIHsNCiAgICAgICAgd3JpdGVyLm5ld0xpbmUoKTsNCiAgICB9DQogICAgd3JpdGVyLndyaXRlKCJbIik7DQogICAgaWYocHJldHR5ID09IHRydWUpIHsNCiAgICAgICAgd3JpdGVyLm5ld0xpbmUoKTsNCiAgICB9DQp9DQoNCmZ1bmN0aW9uIGNsb3NlKHdyaXRlciwgcHJldHR5KSB7DQogICAgaWYocHJldHR5ID09IHRydWUpIHsNCiAgICAgICAgd3JpdGVyLm5ld0xpbmUoKTsNCiAgICB9DQogICAgd3JpdGVyLndyaXRlKCJdIikNCiAgICBpZihwcmV0dHkgPT0gdHJ1ZSkgew0KICAgICAgICB3cml0ZXIubmV3TGluZSgpOw0KICAgIH0NCiAgICB3cml0ZXIud3JpdGUoIn0iKQ0KICAgIGlmKHByZXR0eSA9PSB0cnVlKSB7DQogICAgICAgIHdyaXRlci5uZXdMaW5lKCk7DQogICAgfQ0KICAgIHdyaXRlci5jbG9zZSgpOw0KfQ0KDQpmdW5jdGlvbiBnZXRDb3VudChjdHgpIHsNCiAgICB2YXIgY291bnQgPSBjdHguZ2V0U2Vzc2lvblBhcmFtZXRlcigiY291bnQiKTsNCiAgICBpZiAoY291bnQgPT0gbnVsbCkgew0KICAgICAgICBjb3VudCA9IDA7DQogICAgfQ0KICAgIHJldHVybiBjb3VudDsNCn0NCg0KZnVuY3Rpb24gc2V0Q291bnQoY3R4LCBjb3VudCkgew0KICAgIGN0eC5zZXRTZXNzaW9uUGFyYW1ldGVyKCJjb3VudCIsIGNvdW50KTsNCn0"
            },
            "next" : ["dsv"]
        }, {
            "id" : "dsv",
            "type" : "file.format.dsv",
            "params" : {
                "fileName" : "GIGYA_TO_SFTP_${now}.csv",
                "columnSeparator" : ",",
                "quoteFields" : true
            },
            "next" : ["sftp"]
        }, {
            "id" : "sftp",
            "type" : "datasource.write.sftp",
            "params" : {
                "host" : "...",
                "username" : "...",
                "password" : "...",
                "remotePath" : "..."
            }
        }
    ]
}

 

Interface

Custom scripts must use the following interface:

public interface Step {
    void process(Object item, Consumer next, Context context, Logger logger);
}

Parameters

  • item: the record to process.
  • next: the next step, for further processing the record.
  • context: the Context object supplying execution contextual information.
  • logger: the Logger object. Log entries are written by default to the remote JobStatus traces attribute.


Related Interfaces

public interface Logger {

    void debug(TraceEvent traceEvent);

	void info(TraceEvent traceEvent);

	void error(TraceEvent traceEvent);
}
public interface Context {

    Object getSessionParameter(String name);

    void setSessionParameter(String name, Object parameter);

    File getWorkingDirectory();
}


Examples

Following are examples for custom scripts that can be used as dataflow steps.


Input

These examples assume that the following is received as input, included in the data.subscriptions field: 

Input
{
	"data": {
		"subscriptions": [{
				"listID": "CA_SUBSCRIPTION_01",
				"acceptanceDate": "2010-11-25T20:42:15.280Z",
				"subscriptionSourceApplication": "123",
				"active": true,
				"log": [{
						"sourceApplication": "123",
						"actionDate": "2010-11-25T20:42:15.280Z",
						"action": "acceptance"
					}
				]
			}
		]
	}
}


Append to Array

The following example demonstrates appending a new JSON object (new subscription) to the existing subscription data. 

The code: 

Custom Step
function process(record, next, ctx, logger) {

    if (record != null) {

        if (record.containsField("data")) {
            var data = record.getField("data").getValueAsRecord();

            if (data.containsField("subscriptions")) {

                var log = new Record();
                log.addField("sourceApplication", "sourceApp");
                log.addField("actionDate", "2010-11-29T02:04:31.313Z");
                log.addField("action", "acceptance");

                var subscription = new Record();
                subscription.addField("acceptanceDate", "2017-04-28T02:04:31.313Z");
                subscription.addField("listID", "list02");
                subscription.addField("subscriptionSourceApplication", "newApp");
                subscription.addField("active", "true");
                subscription.addField("log", log, true);

                var subscriptions = data.getField("subscriptions").addValue(subscription);
            }
        }
    }
    next.accept(record);
}

 

The eventual output would be, for example: 

Output
[{
		"data": {
			"subscriptions": [{
					"acceptanceDate": "2010-11-25T20:42:15.280Z",
					"listID": "CA_SUBSCRIPTION_01",
					"subscriptionSourceApplication": "123",
					"log": [{
							"action": "acceptance",
							"actionDate": "2010-11-25T20:42:15.280Z",
							"sourceApplication": "123"
						}
					],
					"active": true
				}, {
					"acceptanceDate": "2017-04-28T02:04:31.313Z",
					"listID": "list02",
					"subscriptionSourceApplication": "newApp",
					"active": "true",
					"log": {
						"sourceApplication": "sourceApp",
						"actionDate": "2010-11-29T02:04:31.313Z",
						"action": "acceptance"
					}
				}
			]
		}
	}
]


Remove from Array

The following example demonstrates removing a JSON object (existing subscription) from the subscription data. 

Custom Step
 function process(record, next, ctx, logger) {

    if (record != null) {

        if (record.containsField("data")) {
            var data = record.getField("data").getValueAsRecord();

            if (data.containsField("subscriptions")) {
                var subscriptions = data.getField("subscriptions").getValueAsArray();

                var iterator = subscriptions.iterator();
                while (iterator.hasNext()) {
                    var subscription = iterator.next();
                    if (subscription.containsField("acceptanceDate")) {
                        var acceptanceDate = subscription.getField("acceptanceDate").getValueAsString();
                        //remove subscriptions with "acceptanceDate" = "2010-11-25T20:42:15.280Z"
                        if (acceptanceDate.equals("2010-11-25T20:42:15.280Z")) {
                            iterator.remove();
                        }
                    }
                }
            }
        }
    }
    next.accept(record);
}

 

The output would look like this: 

 

Output
[{
		"data": {
			"subscriptions": []
		}
	}
] 



Set Value

The following example demonstrates setting a value to one of the fields within the JSON object (subscription status). 

Custom Step
 function process(record, next, ctx, logger) {

    if (record != null) {

        if (record.containsField("data")) {
            var data = record.getField("data").getValueAsRecord();

            if (data.containsField("subscriptions")) {
                var subscriptions = data.getField("subscriptions").getValueAsArray();

                var iterator = subscriptions.iterator();
                while (iterator.hasNext()) {
                    var subscription = iterator.next();
                    if (subscription.containsField("acceptanceDate")) {
                        var acceptanceDate = subscription.getField("acceptanceDate").getValueAsString();
                        //change value of "active" to false if "acceptanceDate" = "2010-11-25T20:42:15.280Z"
                        if (acceptanceDate.equals("2010-11-25T20:42:15.280Z")) {
                            subscription.getField("active").setValue(false);
                        }
                    }
                }
            }
        }
    }
    next.accept(record);
}

 

In the output, you can see that the value of active has changed to "false": 

Output
 [{
		"data": {
			"subscriptions": [{
					"acceptanceDate": "2010-11-25T20:42:15.280Z",
					"listID": "CA_SUBSCRIPTION_01",
					"subscriptionSourceApplication": "123",
					"log": [{
							"action": "acceptance",
							"actionDate": "2010-11-25T20:42:15.280Z",
							"sourceApplication": "123"
						}
					],
					"active": false
				}
			]
		}
	}
]

 

 

  • No labels