How to prevent Business Rule loop?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-05-2016 06:37 AM
We have created a situation where sometimes we need to keep two records in sync. So we created a Business Rule that triggers when the one record triggers, updating the other and a second Business Rule doing the reverse. You can already feel where I'm heading with this right? When record A is updated, the BR triggers, updates record B and that triggers a BR that updates A again. ServiceNow notices the loop and quits there, which is nice, but it still has one update too many.
This could easily be avoided to compare the old and new values and if they are the same, the update should not happen. But this is not as easy with journal fields... The comments and work notes fields need to be synchronised as well.
I tried comparing current.comments.getJournalEntry(1) with other.comments.getJournalEntry(1), but this is not always the same, as it might take more than a second to process, changing the timestamp. I tried comparing the content of the entry, without the timestamp and user, but that gives a problem when the user types in 2 times the exact same thing in the comments or work notes. So is there another way, to let servicenow know that they can run all other business rules against the update of the second record, but not the same one again?
- Labels:
-
Scripting and Coding

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-05-2016 06:47 AM
Hi Peter,
Could you explain a little more about the records you're keeping in sync, what tables are they and what is the purpose? I've usually been able to get away with a one-way sync and showing fields from one of the records on the second.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-05-2016 07:17 AM
We use different tables for the Back-Office and the Service Desk, respectively the Back-Office table and the Incident table. Sometimes we have Incidents come in through one service, while they are actually meant for the other service. So what we want to do is, have the incoming service (or user through self-service) enter all information in the record and click a button to escalate it to the other side. Escalating will make a copy of the original and put the original record in the "awaiting" state. Business Rules are set in place to keep the information synced, because we want both parties to be informed if anything changes. Specifically, we want every information entered in the short description, comments, work notes and state, to be synced.
So there is 1 BR that triggers when the Incident changes, and fills out the BO record and another that does the reverse. The problem is that filling out these values on the other side, triggers the Business Rule. So it's hard to make a difference between a user/employee update or an update by the Business Rule. In the first case, the other side can update, in the other, it should just be ignored, because it already has this information.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-05-2016 07:49 AM
That's a tough one. There may be a better way, but what if you added a string field onto both that you copied the latest comment into which would have the comment and timestamp, then you could check that against target record.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-05-2016 09:35 AM
You need to use indexOf() here instead of direct comparison. Here are sample business rule scripts for problem and problem_task table.
Problem Table:
var gr= new GlideRecord('problem_task');
gr.addQuery('problem',current.getValue("sys_id"));
gr.query();
while(gr.next()){
if(current.work_notes.getJournalEntry(1).indexOf(gr.work_notes.getJournalEntry(1))<0){
gr.work_notes=current.work_notes.getJournalEntry(1);
gr.update();
}
}
Problem Task Table:
var gr= new GlideRecord('problem');
gr.get(current.getValue("problem"));
if(current.work_notes.getJournalEntry(1).indexOf(gr.work_notes.getJournalEntry(1))<0){
gr.work_notes=current.work_notes.getJournalEntry(1);
gr.update();
}