UI Builder – Transform Data Broker showing “Data resource is not configured”

Surbhi16
Tera Contributor

Hi All, @Mark Roethof @Ankur Bawiskar @Ravi Gaurav

I am implementing a use case in UI Builder (Workspace) where I need to identify duplicate accounts and navigate users to a filtered list view.

 

We maintain user records in a custom table x_user_directory

Requirement:

When a user clicks a “Duplicate User” tile in UI Builder:

  1. Detect duplicate accounts based on:

    • email

    • employee_number

    • (optionally compare with sys_user.email)

  2. Collect duplicate record sys_ids

  3. Navigate to the list of such records

    Current Implementation

    1️⃣Data Broker Server Script (Transform Type)

    I created a Data Broker Server Script (Transform) with logic similar to:

     

(function transform(input) {

    var dupRecordsMap = {};

    // Duplicate check in custom  table
    var ga = new GlideAggregate('x_user_directory');
    ga.addAggregate('COUNT', 'email');
    ga.addNotNullQuery('email');
    ga.groupBy('email');
    ga.query();

    while (ga.next()) {
        if (ga.getAggregate('COUNT', 'email') > 1) {
            var gr = new GlideRecord('x_user_directory');
            gr.addQuery('email', ga.email);
            gr.query();

            while (gr.next()) {
                dupRecordsMap[gr.getUniqueValue()] = true;
            }
        }
    }

    // Optional cross-check with sys_user
    var userGR = new GlideRecord('sys_user');
    userGR.addNotNullQuery('email');
    userGR.query();

    while (userGR.next()) {
        var userGR = new GlideRecord('x_user_directory');
        userGR.addQuery('email', userGR.email);
        userGR.query();

        if (userGR.getRowCount() > 1) {
            while (userGR.next()) {
                dupRecordsMap[userGR.getUniqueValue()] = true;
            }
        }
    }

    var ids = Object.keys(dupRecordsMap);

    return {
        sysIds: ids.join(','),
        count: ids.length
    };

})(input);

2️⃣Output Schema

Added this Output Schema:

{
  "type": "object",
  "properties": {
    "sysIds": {
      "type": "string"
    },
    "count": {
      "type": "number"
    }
  }
}

3️⃣ACL Configuration

Initially, I received:

ACL did not allow execution

To fix this, I created:

  • ACL Type: ux_data_broker

  • Operation: execute

  • Name: sys id of data broker server script

  • Role: admin

Now the ACL error is resolved.

UI Builder still shows:

Data resource is not configured
Add details in the configuration for Duplicate Account IDs to review the data output 
Please help me to understand how to navigate on required list of duplicate records.

5 REPLIES 5

jordimsant
Mega Sage

I am facing the same issue today, did you get a solution to this?

jordimsant
Mega Sage

Okay, I faced the same problem, and the error was that the script had an error, preventing it to return the expected value correctly. I noticed that in your script you are redefining userGr inside a while, so I suppose a critical error is happening there. Try this:

(function transform(input) {

    var dupRecordsMap = {};

    // Duplicate check in custom  table
    var ga = new GlideAggregate('x_user_directory');
    ga.addAggregate('COUNT', 'email');
    ga.addNotNullQuery('email');
    ga.groupBy('email');
    ga.query();

    while (ga.next()) {
        if (ga.getAggregate('COUNT', 'email') > 1) {
            var gr = new GlideRecord('x_user_directory');
            gr.addQuery('email', ga.email);
            gr.query();

            while (gr.next()) {
                dupRecordsMap[gr.getUniqueValue()] = true;
            }
        }
    }

    // Optional cross-check with sys_user
    var userGR = new GlideRecord('sys_user');
    userGR.addNotNullQuery('email');
    userGR.query();

    while (userGR.next()) {
        var dirGR = new GlideRecord('x_user_directory');
        dirGR .addQuery('email', userGR.email);
        dirGR .query();

        if (dirGR .getRowCount() > 1) {
            while (dirGR .next()) {
                dupRecordsMap[userGR.getUniqueValue()] = true;
            }
        }
    }

    var ids = Object.keys(dupRecordsMap);

    return {
        sysIds: ids.join(','),
        count: ids.length
    };

})(input);

Also I think that the output schema is not really necessary. If it is still not working, try to remove it.

AnupriyaC
Tera Guru

Hi @Surbhi16 ,
Did you find a solution to how to make it work after that I am facing similar issue but I did try the script in background script and it was working fine but my inputs are not getting captured and my script is not getting triggered which I think is the main reason to why it's not working. If you do find a solution do let me know. Thanks!

Michael Ramos
Tera Contributor

I had this issue as well and the solution was that, in the Script field of the Data Resource (a.k.a. Data Broker) (sys_ux_data_broker_transform), you need to define a single top level named function and it should NOT be executed in the script field. Only declare the function.

 

It can be named anything but transform is the typical convention you will see.

 

So in your example you have a self-calling unnamed function:

(function (input) {
    return "my result";
})();

 

 

You can do any of the following:

function transform(input) {
    // code here
    return "result";
}

 

function foo(input) {
    // code here
    return "result";
}

 

// One top level function
function transform(input) {
    // code here
    return nestedFunc();

    function nestedFunc() {
        // nested function code
        return "something";
    }
}



You can NOT do the following:

Call the function

function transform(input) {
    // code here
    return "result";
}

transform();


Second top level function

function transform(input) {
    // code here
    return "result";
}

function secondTopLevelFunc() {
   //code here
   return "doesn't matter";
}


Unnamed Function

(function (input) {
    // code here
    return "result";
})


Unnamed Self-Calling Function

(function (input) {
    // code here
    return "result";
})(input);



Other things to look out for

1. Script not returning an output

If you have the "Mutates server data" field unchecked on the Data Resource record (sys_ux_data_broker_transform) and the script does not return an output, either due to design flaw or erroring, you will see the same message in the gui “Data resource is not configured”. 

 

This is because the window you see is supposed to be a preview of the output and Data Resources that do not mutate server data are expected to retrieve data. So no data returned makes the GUI assume its not configured. (Though its not the most intuitive message).

 

If the "Mutates server data" field is checked, then you would not be returning data and you will see a different message in the GUI.

 

2. Misconfigured property definitions
If you misconfigure a property on the Data Resource record (sys_ux_data_broker_transform), you may not see the property show up in the GUI in UI builder, though some things like setting an invalid fieldType doesn't seem to affect it and it will still show.

 

If the misconfiguration throws off the script's handling of the input, then that can lead to an error and thus not returning an output and thus leading to the same message in the gui “Data resource is not configured”. 

 

3. Using gs.info for troubleshooting in Data Resource
Using gs.info() from the Data Resource will populate logs and can help with troubleshooting. If you don't see any make sure you follow the advice above.

That said, I would do this temporarily or place behind a debugging system property control and don't leave logging on unless you know what you are doing. You could potentially cause a large amount of logs to generate due to how frequently some data resources might be invoked.