Domain Separation Transform Maps

To start with, apologies for not posting in ages! I’ve had a few of you guys ask me where I went and to carry on. Life took over and I got too busy, but I’m going to try to revive the blog now.
So with that out of the way, back to the actual post….

For those who have worked on domain separated environment, you will know it often requires different approaches to the same requirements that you’d normally encounter on a non-domain separated environment.

One of the things that you always need to be careful about is integrations, in particular, mapping reference fields. With reference fields, you have the option to create new records on the fly, which I use often in general integrations.

The issue with domains however, is you’re probably doing an integration into a particular domain, but the create option on the transform map will create new records in the global domain – not great.

Also, when mapping to reference fields, you can map using names rather than sys_id. But what happens when you have two records with the same name, one in the global domain and one in your lower domain? You cannot guarantee which one will be selected.

Without a proper solution in place, you can end up with what I call domain cross contamination. For example, a CI in domain1, where the owner is a user in domain2 and the manufacturer a record from domain3. This is not a good situation to be in and rectifying it can be complex!

To get around this, I created the following script which searches a particular domain for the reference record, if it doesn’t exist, it searches the global domain, and then if it still can’t find it, it will create the record in the lower domain if required.

var DomainUtils = Class.create();
DomainUtils.prototype = {
initialize: function() {

checkRefValDomain: function(table, company, field, value, create, options) {
if (!value || !table || !company || !field) {
return false;
var domain;
var cmp = new GlideRecord('core_company');
cmp.addQuery('name', company);
if (! {
return false;
domain = cmp.sys_domain;
var tb = new GlideRecord(table);
tb.addQuery('sys_domain', domain);
tb.addQuery(field, value);
if ( {
return tb.sys_id + '';
else {
tb = new GlideRecord(table);
tb.addQuery('sys_domain', 'global');
tb.addQuery(field, value);
if ( {
return tb.sys_id + '';

if (create) {
if (tb.isValidField('company')) { = cmp.sys_id;
tb.sys_domain = domain;
for (var k in options) {
tb[k] = options[k];
tb[field] = value;

return tb.sys_id + '';
return false;

type: 'DomainUtils'

Now, in your transform map, on the field mappings, select ‘Use source script’ and in the ‘Source script’ field add a call to this script include such as:

answer = new DomainUtils().checkRefValDomain('sys_user', 'myCompany', 'employee_number', source.emp_number, true, {'name' : source.emp_number, 'active' : false });

This will look for a record in the sys_user table, with a an employee_number value of source.emp_number. If it cannot find that record in the myCompany domain, or in the global domain, the ‘true’ will mean that it will create a record in the myCompany domain.

Finally, there is an object literal passed in at the end, which allows you to set other values on the record. So this will set the sys_user record that it creates to have a name of source.emp_number and will create the record with active is false.

Hope this helps, I’ll try and post some more scripts from my DomainUtils script include later.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.