Servicenow脚本无限递归

标签 servicenow

我有以下 ServiceNow 脚本,它将记录插入 live_message 表中。

(function executeRule(current, previous/*null when async*/) {


  var requestBody;
  var responseBody;
  var status;
  var request;
  var response;

  try {

    request = new sn_ws.RESTMessageV2("LiveMessageWebhook", "post");

    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");


    var parameters = "&chat_message=" + current.chat_message.toString();
    parameters = parameters + "&context=" + current.context.toString();
    parameters = parameters + "&formatted_message=" + current.formatted_message.toString();
    parameters = parameters + "&has_attachments=" + current.has_attachments.toString();
    parameters = parameters + "&has_links=" + current.has_links.toString();
    parameters = parameters + "&has_tags=" + current.has_tags.toString();
    parameters = parameters + "&ID=" + current.id.toString();
    parameters = parameters + "&in_reply_to=" + current.in_reply_to.toString();
    parameters = parameters + "&isLiked=" + current.is_liked.toString();
    parameters = parameters + "&lastActivity=" + current.last_activity.toString();
    parameters = parameters + "&lastMessage=" + current.last_message.toString();
    parameters = parameters + "&likeCount=" + current.like_count.toString();
    parameters = parameters + "&message=" + current.message.toString();
    parameters = parameters + "&next_reply_order_chunk=" + current.next_reply_order_chunk.toString();
    parameters = parameters + "&order=" + current.order.toString();
    parameters = parameters + "&poll=" + current.poll.toString();
    parameters = parameters + "&private=" + current.private_message.toString();
    parameters = parameters + "&profile=" + current.profile.toString();
    parameters = parameters + "&reflected_field=" + current.reflected_field.toString();
    parameters = parameters + "&reply_to=" + current.reply_to.toString();
    parameters = parameters + "&state=" + current.state.toString();
    parameters = parameters + "&group_type=" + current.sys_class_name.toString();
    parameters = parameters + "&created_by=" + current.sys_created_by.toString();
    parameters = parameters + "&created_on=" + current.sys_created_on.toString();
    parameters = parameters + "&domain=" + current.sys_domain.toString();
    parameters = parameters + "&domain_path=" + current.sys_domain_path.toString();
    parameters = parameters + "&sys_ID=" + current.sys_id.toString();
    parameters = parameters + "&to_profile=" + current.sys_domain.toString();
    parameters = parameters + "&updates=" + current.sys_mod_count.toString();
    parameters = parameters + "&updated_by=" + current.sys_updated_by.toString();
    parameters = parameters + "&updated_on=" + current.sys_updated_on.toString();

    request.setRequestBody(encodeURI(parameters));
    var l = request.getRequestBody();
    response = request.execute();

    responseBody = response.haveError()
      ? response.getErrorMessage()
      : response.getBody();
    status = response.getStatusCode();
    {
      var gr = new GlideRecord('live_message');

      gr.initialize();
      gr.chat_message = current.chat_message;
      gr.context = current.context.toString();
      gr.formatted_message = "abc";
      gr.group = current.group;
      gr.has_attachments = current.has_attachments;
      gr.has_links = current.has_links;
      gr.has_tags = current.has_tags;
      gr.id = current.id;
      gr.in_reply_to = "admin";
      gr.is_liked = current.is_liked;
      gr.last_activity = current.last_activity;
      gr.last_message = current.last_message;
      gr.like_count = current.like_count;
      gr.message = "abc";
      gr.next_reply_order_chunk = current.next_reply_order_chunk;
      gr.order = current.order;
      gr.poll = current.poll;
      gr.private_message = current.private_message;
      gr.profile = current.profile;
      gr.reflected_field = current.reflected_field;
      gr.reply_to = current.reply_to;
      gr.state = current.state;

      gr.sys_class_name = current.sys_class_name;
      gr.sys_created_by = current.sys_created_by;
      gr.sys_created_on = current.sys_created_on;
      gr.sys_domain = current.sys_domain;
      gr.sys_domain_path = current.sys_domain_path;
      gr.sys_mod_count = current.sys_mod_count;
      gr.sys_updated_by = current.sys_updated_by;
      gr.sys_updated_on = current.sys_updated_on;
      gr.to_profile = current.to_profile;
      gr.insertWithReferences();

    }

  } catch (ex) {
    responseBody = 'Exception: ' + ex;
    status = '900';
    requestBody = request
      ? request.getRequestBody()
      : null;
  } finally {
    gs.info("Final: Request Body: " + requestBody);
    gs.info("Final: Response: " + responseBody);
    gs.info("Final: HTTP Status: " + status);
    gs.addInfoMessage('Final: Finished');
  }

})(current, previous);

但是插入记录后,它再次返回到 try block ,并再次执行整个操作,现在使用插入的记录

最佳答案

此业务规则是如何配置的? 是否有可能此脚本所做的更改也可以触发脚本运行?

这是我的意思的一个例子: 想象一下,我有一个业务规则,每当表“u_任意_计数器”中的记录更新时就会执行该规则。 想象一下,这个业务规则的功能是,每当更新这样的记录时,我们就将“u_counter”字段的值加一,如下所示:

current.setValue('u_counter', parseInt(current.getValue('u_counter')) + 1);
current.update();

通过使用 .update() ,我强制更新数据库,即使这是“之前”的业务规则。

Pro Tip: Note that "before" business rules run on the data that's about to be saved to the database, BEFORE the actual database operation has taken place. Any changes to the "current" object in a "before" business rule will be saved even without using current.update, because you're modifying the data that's about to be sent to the database anyway, in the natural course of this operation.

因此,在 BEFORE 业务规则中使用 current.update() 并不是一个好主意。但出于同样的原因,执行任何其他必然导致数据库更新(可能触发相同业务规则)的操作都是一个坏主意。它不一定是 current.update() -- 相反,想象一下如果我没有更新当前记录,而是做了类似的事情......

var gr = new GlideRecord('u_arbitrary_counter'); //the same table this BR is running on
gr.initialize();
gr.setValue('u_counter', parseInt(current.getValue('u_counter')) + 1);
gr.insert(); //This triggers a database action!

出于同样的原因,这也是不好的。 对于任何会触发此表上的数据库操作(可能会触发此业务规则)的 REST 调用也是如此。


解决方案

如果这确实是您问题的原因(并且在不知道您的业务规则的配置的情况下,我无法确定它是否是),实际上有一种方法可以告诉系统不要再运行业务规则是脚本执行操作的结果。就在您的gr.insertWithReferences();之前行(第 91 行),如果该代码块是问题所在(我相当有信心确实如此),请添加:

gr.setWorkflow(false);

这会阻止业务规则运行。 不幸的是,由于您将记录放入 live_message 表中,这可能也不是一个好主意,因为消息发送者可能需要一些业务规则来传播或呈现插入后的信息;我不知道。 如果是这种情况,我建议在您的业务规则中添加一个条件,以便它仅在某些情况下运行,然后精心设计插入的记录以满足这些条件。

Pro Tip: PS - I notice you access a table field using current.field_name.toString() in some places, and directly access current.field_name in others. While the former is acceptable (not that I recommend it in most cases), the latter should almost never be used -- except in the case of journal fields. Instead, I strongly recommend using the appropriate getter/setter methods, to avoid pass-by-reference issues and confusion, and to ensure you're not relying on JavaScript's coersion, which doesn't always play nice with Mozilla Rhino, which ServiceNow runs on the back-end. Example issue here. For more info, please see my article on using getValue() and setValue() in ServiceNow.

关于Servicenow脚本无限递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44405858/

相关文章:

python-3.x - 即使直接从 Chrome 检查复制,XPath 也无法工作

c# - 使用 .Net 调用 Servicenow Web 服务

javascript - ServiceNow UI 页面 GlideAjax

javascript - JS if 语句似乎不起作用

ServiceNow:通过 REST API 设置加密字段

c# - ServiceNow 表 API 返回重复项/不返回所有记录

ios - 停止 WKWebView 重定向到基于通用链接的另一个应用程序

java - 在 ServiceNow 中使用 REST API 获取用户 sys_id?

html - ServiceNow 存储和调用滑动脚本

python - ServiceNow - 如何使用 SOAP 下载报告