Extending a Script Include Not Working

sarah_kovar
Tera Contributor

Hello, 

I am trying to extend the script include 'SCPopularItems'. This script include is not read only, but there is only one method contained in it that I want to override. We'd like to leave 'SCPopularItems' OOB so we can continue to receive updates to it during upgrades. 

I've looked at two official docs from ServiceNow on this as well as countless Community articles. 

Right now the only difference (for testing purposes) between 'SCPopularItems' and 'MySCPopularItems' is I've placed a gs.log statement within MySCPopularItems to see when it's triggered. I do have additional customizations to it that I will place, but wanted to just prove out whether it will override the method contained within the OOB script include.

Can anybody tell me why this isn't working?
I've tried uncommenting and commenting the three lines of code for 'initialize: function()...'  

 

New script include name: 'MySCPopularItems'

var MySCPopularItems = Class.create();

MySCPopularItems.prototype = Object.extendsObject(SCPopularItems, {

    // initialize: function() {
    //     SCPopularItems.prototype.initialize.call(this);
    // },

    _getFromChannelAnalytics: function() {
        gs.log("SBK MySCPopularItems _getFromChannel called"); //only customization to this method at this time
        var itemsResult = [];
        var citm = 0;
        var count = new GlideAggregate('catalog_channel_analytics');
        count.setCategory('catalog_meta');
        count.setGroupByFollowRef(false);
        count.setOrderByFollowRef(false);
        count.addAggregate('COUNT''catalog_item');
        count.groupBy('catalog_item');

        count.addEncodedQuery(this._basicQueryFilters[this._baseQuery] || '');
        if (Array.isArray(this._allowedItemsList))
            count.addQuery('catalog_item'"IN"this._allowedItemsList);

        count.addNotNullQuery('catalog_item');
        // Donot Include items ordered as part of orderguide
        count.addNullQuery('order_guide');
        count.addNotNullQuery('document_key');

        count.orderByAggregate('COUNT''catalog_item');
        count.query();
        while (citm < this._itemsLimit && count.next()) {
            var catItemId = count.getValue("catalog_item");
            var catalogItemJS = new sn_sc.CatItem(catItemId);
            var catItemDetails = this._itemSummaryFetcher(catalogItemJS);
            if (!this._allowItem(catalogItemJS, catItemDetails))
                continue;
            if (this._itemValidator(catalogItemJS, catItemDetails)) {
                var response = this._responseObjectFormatter(catItemDetails, catItemDetails.sys_class_name, count.getAggregate('COUNT''catalog_item'));
                var massageWith = this._getMassageObject(catItemDetails.name, count.getAggregate('COUNT''catalog_item'));
                itemsResult.push(this._massageResponseObject(response, massageWith));
                citm++;
            }
        }
        var guides = 0;
        count = new GlideAggregate('catalog_channel_analytics');
        count.setCategory('catalog_meta');
        count.setGroupByFollowRef(false);
        count.setOrderByFollowRef(false);
        count.addAggregate('COUNT''sys_id');
        count.groupBy('catalog_item');
        count.addNotNullQuery('catalog_item');
        count.addQuery('table_name''sc_cat_item_guide');
        count.addEncodedQuery(this._basicQueryFilters[this._baseQuery] || '');
        if (Array.isArray(this._allowedItemsList))
            count.addQuery('catalog_item'"IN"this._allowedItemsList);
        count.orderByAggregate('COUNT''sys_id');
        count.query();
        while (guides < this._itemsLimit && count.next()) {
            var guideId = count.getValue("catalog_item");
            catalogItemJS = new sn_sc.CatItem(guideId);
            catItemDetails = this._itemSummaryFetcher(catalogItemJS);
            if (!this._allowItem(catalogItemJS, catItemDetails))
                continue;
            if (this._itemValidator(catalogItemJS, catItemDetails)) {
                response = this._responseObjectFormatter(catItemDetails, 'sc_cat_item_guide', count.getAggregate('COUNT''sys_id'));
                massageWith = this._getMassageObject(catItemDetails.name, count.getAggregate('COUNT''sys_id'));
                itemsResult.push(this._massageResponseObject(response, massageWith));
                guides++;
            }
        }
        itemsResult.sort(function(a, b) {
            return a.order == b.order ? a.name.localeCompare(b.name) : -(a.order - b.order);
        });
        return (itemsResult.length > this._itemsLimit) ?
            itemsResult.slice(itemsResult.length - this._itemsLimit, itemsResult.length) :
            itemsResult;
    },

    type: 'MySCPopularItems'
});

 

1 ACCEPTED SOLUTION

Sorry for the delay in responding, but I'm glad my previous response triggered the solution, as it was exactly what I was going for 🙂   I hate simple "do this" "answers".

 

When we create a Script Include that "overrides" another one, it doesn't automagically override it.  We must use the new class in order for the overrides to apply.  That is what I figured was the issue you were having as you did not mention using the new class name in your code.

 

We actually did this for a client with the OOTB Script Include used to create new User records because we wanted to use our own set of temporary bilingual passwords instead of the set used by SN.  We created the new Script Include and pointed a couple of lines of code to use it so that the new passwords would be used but not change the rest of the functionality of the Script Include.

 

It's kind of hard to decide which method is "best": override/clone an OOTB record or modify it.  I struggle with that all the time.  Overriding or cloning something helps on upgrades because you do not have to review skipped records and you'll get any updated code automatically.  BUT, at least the skipped record is a trigger for you to look at something that has potentially changed.  Maybe you don't actually want the new code to be used because your code is important.  Maybe you changed something and the newest SN code actually works the way you want it to now but you'd never know it unless you actively look at the code that you've cloned or overridden (which is not very likely).  This gives you a means to revert back to the OOTB code.  You can't compare code from 2 different records in SN directly, so you'd have to do it manually.

 

Another thing, like you mentioned, is some new code may have been introduced that uses the "old" OOTB code that you would prefer use the new Script Include you created.  You'd have to actively search for those on upgrades to be sure your new code is used.

 

I know someone will jump in and say "best practice" says you never touch OOTB code.  Well, I prefer the term "good practice", as the "best" way to do things is not the best way for everything/everyone/all the time.  There is very rarely an absolute answer to everything.

 

Please remember to mark any response as being the correct one or helpful to you in solving the problem.

View solution in original post

21 REPLIES 21

Bert_c1
Kilo Patron

Hi,

 

As an OOB example of doing this, see:

 

https://[instance_name]/sys_script_include_list.do?sysparm_query=nameSTARTSWITHChangeProcess&sysparm_view= 

 

there are others, for example 'Incident' and 'IncidentSNC'.

Hi, yes, I've looked at and mimicked the OOB examples such as IncidentUtils and ChangeUtils; however not had any luck in getting it to work using them as an example. I've successfully used these extensible classes before (the OOB ones). This is the first time I've tried extending/overriding creating my own and I'm just not getting it to work.  Thanks.

Bert_c1
Kilo Patron

Hi @sarah_kovar ,

 

Please post your script include, and how you using that new class. And add "gs.info()" in your script include to debug that. You can then review 'Script Log Statements' module to see the results.

Hi, I have my script include posted in my initial post. I already have gs.log statements.