GlideScopedEvaluator not working

DrewW
Mega Sage
Mega Sage

We have added an Attribute field to the sys_user table.   It is a GlideList field that points at a table of attributes and the condition that causes them to be added to the user.   We do this to make reporting reasons.   Recently we have had the need to update the user record in certain ways when certain attributes are added to a user record.   I have been experimenting with ways to go about this and wanted to use a script field.   So I have been testing out how to use the GlideScopedEvaluator by running it as a background script in a sub prod instance and it does not seam to be working.   Below is the test code and the results.

Any thoughts would be appreciated.

var g = new GlideScopedEvaluator();

var s = new GlideRecord("sys_script");

s.initialize();

s.setValue("script", "gr.setValue('locked_out', false);");

gs.print(s.getValue("script"));

var u = new GlideRecord("sys_user");

u.get("30e473300a0a3c5401d64c7b0a5dc988");

gs.print(u.getValue("locked_out"));

g.putVariable("gr", u);

g.evaluateScript(s, 'script', null);

u = g.getVariable("gr");

gs.print(u.getValue("locked_out"));

eval("u.setValue('locked_out', false);");

gs.print("After Eval used: " + u.getValue("locked_out"));

Output

*** Script: gr.setValue('locked_out', false);

*** Script: 1

*** Script: 1

*** Script: After Eval used: 0

5 REPLIES 5

manikorada
ServiceNow Employee
ServiceNow Employee

Drew,



I tried something like this in a OOTB instance and it worked :



var evaluator = new GlideScopedEvaluator();


var s = new GlideRecord('sys_script_include');


s.initialize();


s.script = "gr.setValue('locked_out', true);gr.update();";


s.insert();


var u = new GlideRecord("sys_user");  


u.get("62826bf03710200044e0bfc8bcbe5df1");  


var vars = {'gr' : u};


evaluator.putVariable('gr', u);


evaluator.evaluateScript(s, 'script', null);


I added var vars = {"gr": u}; and passed that instead of NULL and that did not work either.   How do you know it worked?   I want to run code that will update the user record but not call the update method.   I want it to send back the updated GlideRecord so that I can do some other things then update the record one time.


Daniel A-C
Tera Expert

Ok, we have a potential fix for the issue. Credit my colleague: David Sturman



Issue


The issue is that the GlideScopedEvaluator will only execute script which is specified in a GlideRecord object. Previously it has been sufficient to just initialize one in memory and pass it to the .evaluateScript() method without saving the record first. It appears that ServiceNow has implemented a change which prevents this usage. (Whether on purpose or not, I have no idea. I cannot find any documentation for this change.)



Steps to Reproduce Issue


Running the following in a background script will print a sentence to screen on Istanbul_Patch2 but fail to do so on Patches 4 and later (not tested on 3):



Steps to workaround


Option 1 — insert prior to execution. The following works perfectly fine, but it does mean that you end up with unnecessary records in the system.


var evaluator = new GlideScopedEvaluator();


var gr = new GlideRecord('sys_script');


  1. gr.initialize();
  2. gr.script = 'gs.print("This script has executed and my user id is " + gs.getUserID());';
  3. gr.insert();
  4. evaluator.evaluateScript(gr, 'script');


Option 2 — retrieve any record with a script field, dynamically set the script value but don't actually update and it will still execute the updated script. For extra protection against any inadvertent updates, I suggest doing this against a record with a 'Read-only' protection policy.


var evaluator = new GlideScopedEvaluator();


var gr = new GlideRecord('sys_script');


  1. gr.addQuery('sys_policy','read'); //additional protection against accidental update  
  2. gr.setLimit(1);
  3. gr.query();

if (gr.next()) {


gr.setValue('script','gs.print("This script has executed and my user id is " + gs.getUserID());');


try {


evaluator.evaluateScript(gr, 'script');


}


catch (e) {


gs.error(e);


}


}


else {


throw new Error('No rows were found to dynamically use GlideScopedEvaluator against');


}




I've also thrown some error handling in here. See if that works for you.


I pasted the above from an email I wrote for internal use at my company and therefore didn't tailor it to your specific use case but I hope you get the drift. You should still be able to use putVariable and getVariable etc. Good luck!