NOTE: MY POSTINGS REFLECT MY OWN VIEWS AND DO NOT NECESSARILY REPRESENT THE VIEWS OF MY EMPLOYER, ACCENTURE.

 

DIFFICULTY LEVEL:  INTERMEDIATE

Assumes basic knowledge and/or familiarity of Client and Server-Side Scripting in ServiceNow.

____________________________________________________________________________

 

I had already done this particular subject as an Ask-the-Expert session, but thought I would write it up for easier pondering and implementation. 

 

With Part 1 I will be describing the thought processes that are necessary in understanding the "reasons-why" this particular topic is important.  In Part 2 I will present the actual labs for converting the UI Script described in my article Mini-Lab: Using Ajax and JSON to Send Objects to the Server from the Global namespace to it's own Scoped namespace.

 

Suggested pre-reading:

 

Pragmatic Patterns: Ajax - Architecting Your Code

Mini-Lab: Using Ajax and JSON to Send Objects to the Server

Mini-Lab: Writing Entries Into the System Log Using Ajax and JSON

 

A couple of Ajax best-practice mentions here:

 

1) Keep Synchronous calls from the client to the server at an absolute minimum.  This is to limit the impact to the user experience.

2) Synchronous calls are okay if you are doing some type of data retrieval with an onSubmit Client Script.  This is pretty much it, though as far as I'm concerned.  Really, though with something like this I would consider converting it into a Before Business Rule, or perhaps pre-loading the data with a Display Business Rule keeping it on the Server in both cases.

 

 

Common Practice

 

So let me describe a common practice with Client Scripts.  I have already gone into some detail on this with my pattern article on Ajax, but I will repeat a bit of it here.

 

Basically, most developers write their Ajax Client Scripts as a simple very specific one-to-one call from the browser to the server, to handle, and perhaps retrieve data.  This isn't bad, but it isn't very extensible.

 

 

You have no normal ability to share a client script between different non-inherited tables, and thus between forms.  So even if you did have some reusable code you would have to at the least create two different Client Scripts, and maintain them, even though the code was the same.  This is a bad practice.  You want to consolidate these into a single reusable client-side library that is loaded and available from the Form. 

 

The same problem also presents itself from the server-side.  Here an Ajax Script Include is pretty specific in what it is for, and really does not present itself well as a function library.

 

 

A Methodology Shift

 

So, the solution to the problem of a client-side function library has always been the UI Script mechanism.  Here, ServiceNow has provided us a way to create reusable code libraries that are loaded with a form.  This allows the developer to concentrate often reused functions into a single maintainable location (a serious best-practice).  This keeps the maintenance to a single location, and reduces development time-to-completion with reusable code.  The down-side: UI Script libraries are always loaded with the form.  So you get them whether you use them or not.  These are usually quite small in the amount of client-side memory they use, and the load-time involved; so it is generally not an issue.

 

On the server-side we can push reusable code down a layer by creating a Script Include Function Library or a Script Include Class (yep, there are two flavors).  Either approach is fine; the idea being to centralize reusable code, and reduce maintenance and time-to-completion.

 

In all cases an attempt should be made to put the calculation and database heavy-lifting on the shoulders of the server, and keep the client-side script to a minimum (a.k.a. thin).

 

 

 

The Scoped Environment

 

With the advent of Scoped Scripting in the Fuji release we now have a way of isolating our code from the rest of the ServiceNow environment.  This brings along several benefits:

 

1) The developer can now create code that is easy to install, and remove with minimal affect on the ServiceNow platform.

2) The application can be protected (i.e. black-boxed) in such a way as to keep it from inter-mixing with the Global code-base.  An important concept of name-spaces.

3) The intellectual property can, in-theory, be protected.  In a future article I will show that this is limited, or frankly not the case in some release instances.

4) A way to organize an application project, and easily access the scoped applications.

5) Deployment to a local ServiceNow Application Store that allowed for much easier inter-company instance deployment than the old update set model.

6) More functionality in the Studio (such as an improved code search!)

7) The ability to connect to an external cloud-based repository such as GitLab, GitHub, or BitBucket (to name a few).

8) Good overall core documentation, and API info in both the product documentation, and the Developer community.

 

This is obviously not an exhaustive list.

 

The biggies for me were #'s 1, 2, 4, 5, and 7.  Shoot, actually I like the whole list. :-)

 

So those are the pro's.  What are the con's?

 

1) Only a subset of the Global-side JavaScript and ServiceNow out-of-the-box (OOB) libraries are available.  There are some interesting, and sometimes frustrating omissions!

2) NONE of the Packages.<<function>> libraries are available (this is a huge deal, and for some of you may represent the reason for not implementing scoped applications - it was a close call for me).

3) Few examples of how-to do certain things in the scoped environment (thus the reason for this and future articles).

4) Inability to re-point a repository URL from the Studio.  No documentation exists on how to do this outside of the studio as well.

5) Intellectual Property protection is only available with internal distribution via the Studio Publish function, or with the ServiceNow store.  This protection switch is not available in any other way.  If you push your application to an update set and upload it to a different (sic. customer) instance your code will be visible to anyone who wishes to look at it.  For more information on this issue see my ask the expert session: Ask the Expert: Scoped Libraries with Steve Bell.

 

 

The Scoped Library

 

Because of the benefits of isolation and organization, that the Studio and Scoped environment bring, it is of great use to build function libraries with these tools.

 

An interesting, and to me a great feature when moving to a Scoped UI Script; is the on-demand nature of the library.  It is only loaded when called.  The only down-side: there was no documentation on how to do this.  The Global "way" of implementing UI Scripts absolutely fails in the scoped environment! 

 

Doing a search on the community popped up with the clues I needed on how to do the conversion. coryseering answered a question back in 2015 that actually provided what was needed to make this work (Re: Unable to create UI Action that calls UI Script in Fuji Scoped Application ).  You might want to also check out his other great articles: Scoped Applications and Client Scripts: A Primer, and Client-side GlideRecord replacement for Scoped Applications (sort of).

 

So, the ScriptLoader function is the key.  It is the mechanism (undocumented) to load a Scoped UI Script library, and it does it on demand!

 

Then the only change to the server-side is to convert any gs.log messages, which do not work in a Scoped app, into the gs.info/gs.warn/gs.error analog.  The scoped class/library calling turns out to be pretty straight-forward on the server-side.

 

 

 

In my next article (Mini-Lab: Converting a UI Script Library From Global to Scoped - Part 2) I will be describing how to take a Global UI Script library and turn it into a Scoped UI Script library that can be used by both Global and Scoped Client-side scripts.

 

Steven Bell

Combined Logo Graphic_Operations.png

 

For a list of all of my articles:  Community Code Snippets: Articles List to Date

 

Please Share, Like, Bookmark, Mark Helpful, or Comment this blog if you've found it helpful or insightful.

 

Also, if you are not already, I would like to encourage you to become a member of our blog!