Reuse GlideRecord in Loop? How?

William Busby
Tera Guru

I'm parsing a JSON object within a workflow that is supposed to cycle through a list of CI's and add comments to each one. The JSON object is an array of ServerName, Action, and Results for 'n' number of CIs. Parsing the JSON is good, but when I loop through the list the GlideRecord works on the first CI and no others (and doesn't throw an exception). Here's what I tried first:

doProcessResponse();

function doProcessResponse() {

  workflow.scratchpad.decommLog = "Server Decommission Log\n";

  //parse JSON string to object

  var result = new global.JSON().decode(activity.output);

  for ( var i=0; i < result.length; i++) {

  var serverGr = new GlideRecord('cmdb_ci');

  serverGr.addQuery('name', result[i].Server);

  serverGr.query();

  if (serverGr.next()) {

  var logEntry = result[i].Server + " decommission action " + result[i].Action + " results " + result[i].Result;

  gs.warn("logEntry " + logEntry);

  serverGr.comments = logEntry;

  serverGr.update();

  workflow.scratchpad.decommLog += logEntry + "\n";

  }

  // destroy GlideRecord object for reuse

  serverGr = null;

  }

  gs.warn("workflow.scratchpad.decommLog = " + workflow.scratchpad.decommLog);

}

So, knowing that objects created in functions are garbage collected and subsequent calls to the function create new objects I just moved all the logic into a function like this:

doProcessResponse();

function doProcessResponse() {

  workflow.scratchpad.decommLog = "Server Decommission Log\n";

  //parse JSON string to object

  var result = new global.JSON().decode(activity.output);

  for ( var i=0; i < result.length; i++) {

  doUpdates(result[i]);

  }

  gs.warn("workflow.scratchpad.decommLog = " + workflow.scratchpad.decommLog);

}

function doUpdates(result) {

  var serverGr = new GlideRecord('cmdb_ci');

  serverGr.addQuery('name', result.Server);

  serverGr.query();

  if (serverGr.next()) {

  var logEntry = result.Server + " decommission action " + result.Action + " results " + result.Result;

  gs.warn("logEntry " + logEntry);

  serverGr.comments = logEntry;

  serverGr.update();

  workflow.scratchpad.decommLog += logEntry + "\n";

  }

}

WTF??? Again only the first result object is processed!!!

1 ACCEPTED SOLUTION

William Busby
Tera Guru

Apologies to everyone who tried to help with this but the pain was entirely self-inflicted. Turns out the JSON object had a space char prepended to the server name EXCEPT for the first one. That extra space was causing the query to fail. Once I removed whitespace all is well. Yet another lesson in making assumptions.


View solution in original post

16 REPLIES 16

Jim Coyne
Kilo Patron

I don't claim to be a JSON expert at all, but what happens when you add ".toString()" in your addQuery line so you end up with:



serverGr.addQuery('name', result.Server.toString());



I've seen weird things with GlideRecord queries when using sys_ids that were not explicitly forced to a string first, so maybe that is what is happening here?   Does not explain why it works only on 1 record, but you never know.



And you are sure that you are looping through the list returned in the JSON object?   What does "result.length" equal?


iaind
Kilo Contributor

You can test the data by doing a:


gs.log(JSUtil.logObject(result));


This will tell you exactly how the data is being presented



I have seen odd behaviour using .toString().   I tend to get more reliable results with " + ''"; as in:


serverGr.addQuery('name', result.Server + '');



Thx Iain - wasn't familiar with gs.log(JSUtil.logObject(result)); but it's certainly helpful.


Jim, thx for the reply but no change in behavior. When the workflow parses the return object 'result.length' is equal to the number of objects in the JSON string. Taking Iain's input this is logged about the object:



Log Object


Array of 4 elements


[0]: Object


Result: string = Success


Server: string = ACAT1442


Action: string = DecommissioningStatusACSI.ps1


[1]: Object


Result: string = Success


Server: string = ACAT1445


Action: string = DecommissioningStatusACSI.ps1


[2]: Object


Result: string = Success


Server: string = ACAT1463


Action: string = DecommissioningStatusACSI.ps1


[3]: Object


Result: string = Success


Server: string = ACAT1466


Action: string = DecommissioningStatusACSI.ps1



and the function logs this (but only for the first object in the JSON string) :



logEntry ACAT1442 decommission action DecommissioningStatusACSI.ps1 results Success