How to return 2 variables from script include to Business Rule

Anirban3
Tera Contributor

Hello All,

 

I want to pass 2 variables from script include to Business Rule...below are the codes...Can someone help me?

 

Script Include Function:

 

_businessApplication: function(ci) {
var service_offering;
var CI;
var cmdbRelGr = new GlideRecord("cmdb_rel_ci");
cmdbRelGr.addQuery("child.name", ci);
cmdbRelGr.query();
if (cmdbRelGr.next()) {
service_offering = cmdbRelGr.parent;
CI = cmdbRelGr.child;
}
return XXX;
},

 

I want to return both service_offering and CI....How can I send it? and how can I fetch it in business rule?

1 ACCEPTED SOLUTION

Grow2Dev
Tera Guru

Hello @Anirban3 ,

 

regarding your request I would suggest to create an object for the data you want to fetch in order to be more flexible.

Your Script Include could look like this:

 

var SIName = Class.create();
SIName.prototype = {
    initialize: function() {},

    _businessApplication: function(oCurrentCi) {
        var oCiData = {};

        var cmdbRelGr = new GlideRecord("cmdb_rel_ci");

        // query al records where child name is current CI name
        cmdbRelGr.addQuery("child.name", oCurrentCi.getValue('name'));  // 1
        cmdbRelGr.query(); // 2

        if (cmdbRelGr.next()) {  // 3
       /* Note: This will run only once and fetch the values for the first record found
       ** Therefore the 3 lines commented with 1,2,3 
       ** could be replaced by (if (cmdbRelGr.get(...) as follows with only one line of code:
       ** if (cmdbRelGr.get("child.name", ci.getValue('name'))) {
        */ 
            oCiData.service_offering = cmdbRelGr.getDisplayValue('parent');
            oCiData.ci = cmdbRelGr.getDisplayValue('child');
        }
        return oCiData;
    },
    type: 'SIName'
};

 

 

In your Business Rule you can fetch the data as follows:

 

var oCiData = new SIName()._businessApplication(current); 
// Use values in an info message:
var sServiceOffering = oCiData['service_offering'];
var sCi = oCiData['ci'];
gs.addInfoMessage('ServiceOffering: ' + sServiceOffering  + '\nCI: ' + sCi);

/* Output:
** ServiceOffering: SAP WEB01
** CI: SAP AppSRV01
*/

// Setting a field value:
current.setValue('description', 'Current CI is: ' + sCi);

// Log the complete object to System Log:
gs.info('Test Script Include SIName() for fetching CI data: \n' + oCiData); 

/* Output can be found in System Log [syslog_list.do] table:  
** {
**  "service_offering": "SAP WEB01",
**  "ci": "SAP AppSRV01"
** }
*/

 

 

 

-------------------

Please note, that your if condition runs only once and returns the values for the first record it can find.
If this is fine, then use the above code snippets.

 

If you need all values of all the relation records it can find, then you have to adjust your code by using a while (gr.next()) instead of if (gr.next()) and push the data into an array.
Quickly written it could look like this:

 

 _businessApplication: function(ci) {
        var oCiData = {}; // create object for Ci data
        var getRels = []; // array for data of each records found 

        var cmdbRelGr = new GlideRecord("cmdb_rel_ci");
        cmdbRelGr.addQuery("child.name", ci.getValue('name'));
        cmdbRelGr.query();

        while (cmdbRelGr.next()) {
            oCiData.service_offering = cmdbRelGr.getDisplayValue('parent');
            oCiData.ci = cmdbRelGr.getDisplayValue('child');
            getRels.push(oCiData);
        }
        return getRels;
    },

 

 

Logged output would look something like this:

Grow2Dev_0-1673100739021.png

Then you can access all the data needed as required in your Business Rule.
Quick example for accessing all data for all records found in order to display it in your Business Rule's info message could look like this:

 

var oCiData = new SIName()._businessApplication(current); 
gs.addInfoMessage('Show me the data: <br>' + JSON.stringify(oCiData));

// Or if you want to format the data and add custom text you could do something like this:
for(var i=0;i<oCiData.length;i++)
gs.addInfoMessage('Service Offering: ' + oCiData[i]['service_offering'].toString() + ' - CI: ' + oCiData[i]['ci'].toString());
// This would display one info message per record found with the data you want to display, see sfollowing creenshot.

 

 

Grow2Dev_0-1673115997652.png

 

 

-------------------

 

Hope this helps.
If any of this was helpful please mark my answer as helpful.
If any of this helped to solve your issue please mark as correct.

Thanks

 

View solution in original post

5 REPLIES 5

Sagar Pagar
Tera Patron

Hi @Anirban3,

 

Try this updated SI function scripts -

 

_businessApplication: function(ci) {
var service_offering;
var CI;


var cmdbRelGr = new GlideRecord("cmdb_rel_ci");
cmdbRelGr.addQuery("child.name", ci);
cmdbRelGr.query();
if (cmdbRelGr.next()) {
service_offering = cmdbRelGr.parent.toString();
CI = cmdbRelGr.child.toString();
}
return service_offering + "," + CI;
},

 

Business rule:

var test = new SIName()._businessApplication(current.cmdb_ci);

var answer = test.toString().split(",");

for (var i = 0; i < answer.length; i++); {
gs.addInfoMessage(answer[i]);

// use answer[i] values in BR as per your need

}

 

Thanks,
Sagar Pagar

The world works with ServiceNow

Grow2Dev
Tera Guru

Hello @Anirban3 ,

 

regarding your request I would suggest to create an object for the data you want to fetch in order to be more flexible.

Your Script Include could look like this:

 

var SIName = Class.create();
SIName.prototype = {
    initialize: function() {},

    _businessApplication: function(oCurrentCi) {
        var oCiData = {};

        var cmdbRelGr = new GlideRecord("cmdb_rel_ci");

        // query al records where child name is current CI name
        cmdbRelGr.addQuery("child.name", oCurrentCi.getValue('name'));  // 1
        cmdbRelGr.query(); // 2

        if (cmdbRelGr.next()) {  // 3
       /* Note: This will run only once and fetch the values for the first record found
       ** Therefore the 3 lines commented with 1,2,3 
       ** could be replaced by (if (cmdbRelGr.get(...) as follows with only one line of code:
       ** if (cmdbRelGr.get("child.name", ci.getValue('name'))) {
        */ 
            oCiData.service_offering = cmdbRelGr.getDisplayValue('parent');
            oCiData.ci = cmdbRelGr.getDisplayValue('child');
        }
        return oCiData;
    },
    type: 'SIName'
};

 

 

In your Business Rule you can fetch the data as follows:

 

var oCiData = new SIName()._businessApplication(current); 
// Use values in an info message:
var sServiceOffering = oCiData['service_offering'];
var sCi = oCiData['ci'];
gs.addInfoMessage('ServiceOffering: ' + sServiceOffering  + '\nCI: ' + sCi);

/* Output:
** ServiceOffering: SAP WEB01
** CI: SAP AppSRV01
*/

// Setting a field value:
current.setValue('description', 'Current CI is: ' + sCi);

// Log the complete object to System Log:
gs.info('Test Script Include SIName() for fetching CI data: \n' + oCiData); 

/* Output can be found in System Log [syslog_list.do] table:  
** {
**  "service_offering": "SAP WEB01",
**  "ci": "SAP AppSRV01"
** }
*/

 

 

 

-------------------

Please note, that your if condition runs only once and returns the values for the first record it can find.
If this is fine, then use the above code snippets.

 

If you need all values of all the relation records it can find, then you have to adjust your code by using a while (gr.next()) instead of if (gr.next()) and push the data into an array.
Quickly written it could look like this:

 

 _businessApplication: function(ci) {
        var oCiData = {}; // create object for Ci data
        var getRels = []; // array for data of each records found 

        var cmdbRelGr = new GlideRecord("cmdb_rel_ci");
        cmdbRelGr.addQuery("child.name", ci.getValue('name'));
        cmdbRelGr.query();

        while (cmdbRelGr.next()) {
            oCiData.service_offering = cmdbRelGr.getDisplayValue('parent');
            oCiData.ci = cmdbRelGr.getDisplayValue('child');
            getRels.push(oCiData);
        }
        return getRels;
    },

 

 

Logged output would look something like this:

Grow2Dev_0-1673100739021.png

Then you can access all the data needed as required in your Business Rule.
Quick example for accessing all data for all records found in order to display it in your Business Rule's info message could look like this:

 

var oCiData = new SIName()._businessApplication(current); 
gs.addInfoMessage('Show me the data: <br>' + JSON.stringify(oCiData));

// Or if you want to format the data and add custom text you could do something like this:
for(var i=0;i<oCiData.length;i++)
gs.addInfoMessage('Service Offering: ' + oCiData[i]['service_offering'].toString() + ' - CI: ' + oCiData[i]['ci'].toString());
// This would display one info message per record found with the data you want to display, see sfollowing creenshot.

 

 

Grow2Dev_0-1673115997652.png

 

 

-------------------

 

Hope this helps.
If any of this was helpful please mark my answer as helpful.
If any of this helped to solve your issue please mark as correct.

Thanks

 

AnubhavRitolia
Mega Sage
Mega Sage

Hi @Anirban3 

 

function starting with underscore '_functionName' means it is a private function and cannot be called outside Script Include. So please remove underscore from function and can try below code same as @Sagar Pagar  Suggested.

 

Script Include:

 

businessApplication: function(ci) {
var service_offering;
var CI;


var cmdbRelGr = new GlideRecord("cmdb_rel_ci");
cmdbRelGr.addQuery("child.name", ci);
cmdbRelGr.query();
if (cmdbRelGr.next()) {
service_offering = cmdbRelGr.parent.toString();
CI = cmdbRelGr.child.toString();
}
return service_offering + "," + CI;
},

 

Business Rule:

 

var test = new SIName().businessApplication(current.cmdb_ci);
var answer = test.toString().split(",");
current.service_offering = answer[0]; // assuming you want to store these values on fields
current.cmdb_ci = answer[1];

// you can use answer[0] and answer[1] based on your need.

 

 

 

Please mark this as correct answer and helpful if it resolved, or mark this helpful if this help you to reach towards solution.

Thanks
Anubhav Ritolia
ServiceNow Rising Star 2023

Hello @AnubhavRitolia and @Anirban3 

the underscore is used for so called "private" functions, but indeed it is not a real private function.
So when calling the function on serverside with a Business Rule it is still accessible, so you will be able to call the function.
Just test it with a Business Rule or quickly via Background Script or in Xplore.

Only difference is that a function with underscore only won't be accessible from client side scripts, so you will not be able to use it in a GlideAjax for example.

Grow2Dev_0-1673111330710.png

 

Further reading:
https://codecreative.io/blog/glideajax-troubleshooting-guide/ search for 'private'

https://www.servicenow.com/community/developer-forum/demystifying-script-include-question-2-script-i... read reply marked as solution from Mark Roethof

https://www.basicoservicenowlearning.in/2019/12/script-include-servicenow.html search for 'private'