Skip navigation

Description: Learn how to automate your functional, regression, and UAT testing to reduce time and increase quality with CapIO. CapIO is the end-end testing tool for ServiceNow, available now and coming soon to the ServiceNow Store. Dave Slusher, ServiceNow Developer Evangelist and automated testing guru, asks Roger the questions you want the answers to if you’re in QA or DevOps.

 

Q&A with Roger Enriquez, Integration Architect at Cerna Solutions.

 

 

Subscribe  to iTunes

 

Your feedback helps us better serve you! Did you find this podcast helpful? Leave us a comment to tell us why or why not.

LISTEN BELOW

2C_hackathon_logo_RGB.png

 

Update: If you are registered for Knowledge16 or CreatorCon you can register immediately for the CreatorCon Hackathon at https://hackathon.service-now.com/hacknow/

Just be sure to use the same email that you used to register for Knowledge16 or CreatorCon!

 

This year's CreatorCon Hackathon at K16  will take it to a whole other level. Luxe new Developer Hub,  DJ, persistent food & bev, three categories to specialize in, video-taped fast pitches, luminary judging and community voting, all at the center of the K16 action. We're expecting the Developer Hub Hackahon Zone to be bursting with over 300 developers, the biggest ServiceNow hackathon on the planet so far.

 

Developer Hub - Hackathon.png

 

 

Developer Hub - Hackathon3.png

Hackathon Zone in the Developer Hub

 

 

You’ll be competing in one of 3 categories for $3,000 in prizes and the chance to star in a webinar that will be seen by the 30K+ strong ServiceNow developer community. 9 finalists will be selected by ServiceNow luminaries and will compete in a videotaped TC Disrupt style fast-pitch on the Developer Hub floor the next day. CreatorCon and K16 attendees will vote for the 3 category winners and ServiceNow luminaries will pick the GP Winner. Check out the categories and all of the awesome prizes below.

 

Categories and Prizes v3.png

 

 

What are we looking for?

 

We are looking for you to solve a hard business problem that you/your team is actually facing at work or could imagine facing at work. This could be something that you haven't had time or cycles to address in your day-day work life, or something super cool and high value that you've always wanted to try but never had the time or resources. The hackathon is the perfect opportunity for you to take a crack at it, with the very latest ServiceNow Platform release and tools, plus ServiceNow gurus to speed you along your way. Some examples to get you thinking:

 

  • A broken process that is causing wasted time, user frustration, and unnecessary complexity
  • A legacy app with a poor UX that is difficult to maintain
  • A workflow that takes multiple apps and manual steps to complete
  • Big, hairy, audacious app requests sitting in the backlog
  • Repetitive tasks involving external systems and processes that take up more time than they should, that if automated would save big bucks, people time, and reduce errors
  • Management reports involving enterprise assets, CMDB, and service records that require multiple data sources and reporting systems to get the necessary information and are slow, cumbersome and error-prone to pull together
  • Any service (request-action-result)  in any department in your company that is unstructured and uses email, spreadsheets, Word docs, IM, and phone calls to get done that could be improved via process re-architecting, automation, and a consumer-grade UX.
  • Crazy things most people would never think about - standing up new physical storefronts; running a smart city, neighborhood, or building. You get the idea.

 

Since we're not in the business of capping or limiting your innovation, "work" could be either at your current workplace or any place of work/business where you could envision ServiceNow being of value. Let's drill down a bit on the categories:

 

Platform Vanguard: Best use of new Platform features and tools in Helsinki - think Service Portal, ECMAScript/JavaScript 5, Git integration. Excel XLSX support, native Android app, Delegated Development.

 

Best Business Solution: An app that delivers the highest tangible/measurable ROI in terms of i)  increasing revenue, productivity, efficiency, business agility, user satisfaction (NPS) or ii)   reducing cost or risk. Think about pitching your app to the CFO or COO.

 

Most Innovative: This is an open category. The only requirement is that it be of high value to some kind of business (any business, not necessarily your current place of work).  Unleash your creativity about what can be done with the ServiceNow Platform.

 

Registration Instructions

 

To get in on the action, follow these three steps in sequence:

 

1) Register for K16 or CreatorCon

2) Add the CreatorCon Hackathon Session Type to your K16 agenda using the Session Scheduler on the K16 website.

3) Within 24 hours of doing 2), we will send an email to the email address you used in 1) with further instructions to officially register for the Hackathon, start or join a team, and preparing to compete!

 

Slay your (or any) business problem in 8 hours with your innovation on top of the ServiceNow Platform and be a hero when you get back to work.

 

#HackNow Team

Martin Barclay
Director, Product Marketing
App Store and ISVs
ServiceNow
Santa Clara, CA

Just doing a quick blog today.

 

I have been on a few calls lately where developers are trying to process XML from an inbound SOAP/REST request.  This scenario is usually done with a scripted  SOAP web service or a processor (where the payload is in XML format).  If you are doing this in a scoped application you probably have already started noticing some API limitations (that you had access to when working in the global namespace).  For examples if you need to support namespaces or need to get a list of all the attributes on a Node - you may start to pull your hair out dealing with XML.

 

Here is the best strategy you can use and I am declaring this a best practice.  Stop working in XML while in ServiceNow.  Your first step in receiving XML and having to deal with it in JavaScript should be to convert it to JSON.  Work in JSON while in the ServiceNow platform.

 

There is a scoped application safe function you can make (first thing) that will do this conversion for you:

 

var obj = gs.xmlToJSON(xmlString);

 

There is one gotcha / caveat you may have to watch out for following this mindset - this strategy will not work with large XML payloads.  Converting the XML into JSON will bring the whole thing into memory which may cause issues. 

In November, I wrote a blog post called Background and Philosophy of Scoped Applications. It recently generated an interesting discussion about the limits of the available APIs for scoped apps, with focus on one specific function: gs.dateGenerate. This post will hopefully help you figure out how to work within the available APIs to achieve the same goals in a scoped application that you could achieve in a global one.

 

The scoped API

The scoped API is mostly a subset of the existing Glide API that we all know and love. Both the legacy and the scoped API set are documented on our ServiceNow Developers  site. Since the scoped API is essentially a subset of the legacy API, there will necessarily be some classes and functions which are not available. One such method is "gs.dateGenerate". The scoped API includes GlideDateTime and GlideDuration, and is capable of doing all of the same calculations that gs.dateGenerate can do, but we have to do a little bit of work to make that happen.

 

Utility classes

I'm a fan of writing utility classes. I like making tools, probably more than I like making things with those tools. A utility class is typically the first thing I start with when I make a new scoped application. It starts out empty, and I add to it as I find myself needed the same generic functions multiple times during the course of development. When I find myself using the same things across multiple applications, I'll pull those out into a new application, and make my app depend on that. I don't want to reinvent the wheel every time I need to make a wagon.

 

Creating the Utility

The most basic utility class is really just an object. This is a good pattern to use, because it prevents you from having to new it every time you need to use it. For our example, we're going to create an object with a single function. We'll give it a short name so it's easy to use, and we won't be using the default template it auto-generates for us.

Screen Shot 2016-04-15 at 11.38.49 AM.PNG

I named my include "Tools" and marked it "Client callable" and "Accessible from: All application scopes". Client-callable enables us to use this include in URLs, which is important for our use-case. Making it available to other application scopes means that I am committing to making this an API point for my application. I won't introduce breaking changes without prior notification to my potential users, and the code I am providing should be side-effect-free. You don't need to make your tools available to other scopes unless you are writing an application specifically to provide a toolset to other applications.

 

I've also changed the Script. By default the Script Include form auto-generates a template for our include based on the anme we provided it. The template looked like this:

var Tools = Class.create();
Tools.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
    type: 'Tools'
});

 

I've decided that this particular set of tools doesn't need to maintain state internally, so there is no reason to use Class.create(). If multiple people want to work with the methods on this object, they can do so without colliding. That's why we're starting with an empty object:

var Tools = {};

 

The first function we want to add is a replacement for gs.dateGenerate. It helps to know that the original dateGenerate function is really just a convenience method that works on GlideDateTime objects. If we were to convert the function from Java to JavaScript, it would look like this:

gs.dateGenerate = function(date, range) {
   var gdt = new GlideDateTime();
   if (range.equals("start"))
      gdt.setDisplayValueInternal(date + " 00:00:00");
   else if (range.equals("end"))
      gdt.setDisplayValueInternal(date + " 23:59:59");
   else
      gdt.setDisplayValueInternal(date + " " + range);

   return gdt.getValue();
}

 

That is pretty simple. We'll copy that nearly verbatim into our Tools include, since every object type it access and every option it does is supported within the scoped API. When we copy that into our include, it looks like this:

var Tools = {};


Tools.dateGenerate = function(date, range) {
    if (!range)
        range = '12:00:00';
    
    var gdt = new GlideDateTime();
    if (range.equals("start"))
        gdt.setDisplayValueInternal(date + " 00:00:00");
    else if (range.equals("end"))
        gdt.setDisplayValueInternal(date + " 23:59:59");
    else
        gdt.setDisplayValueInternal(date + " " + range);
    
    return gdt.getValue();
}

 

We added a default value for the range. The original Java function doesn't supply a default value and returns an empty result if you call it that way:

var generatedDate = gs.dateGenerate('2016-04-14');
gs.print(generatedDate);

 

[0:00:00.001] Script completed in scope global: script


*** Script: 

If we left out the default, we would have the same result. That's up to you- it's your utility.

 

Using the utility

Now that we have our replacement for dateGenerate, we want to make use of it. There is one part of the system that relies on dateGenerate pretty heavily: encoded queries. If you open the Incident list and filter between two dates you can see this happen:

Screen Shot 2016-04-15 at 2.02.46 PM.PNG

The encoded query being run on this list is:

opened_atBETWEENjavascript:gs.dateGenerate('2016-02-01','12:00:00')@javascript:gs.dateGenerate('2016-03-31','12:00:00')

 

If we attempted to run that same query in a script in our application, we would get an error:

var enq = "opened_atBETWEENjavascript:gs.dateGenerate('2016-02-01','12:00:00')@javascript:gs.dateGenerate('2016-03-31','12:00:00')";
var inc = new GlideRecord('incident');
inc.addEncodedQuery(enq);
inc.query();

gs.info(inc.getRowCount());

[0:00:00.248] Script completed in scope sn_custom_app: script

Security restricted: Read operation against 'incident' from scope 'sn_custom_app' was granted and added to 'sn_custom_app' cross-scope privileges

Evaluator: com.glide.script.fencing.MethodNotAllowedException: Function dateGenerate is not allowed in scope sn_custom_app

   Caused by error in script at line 1

 

 

==>   1: var enq = "opened_atBETWEENjavascript:gs.dateGenerate('2016-02-01','12:00:00')@javascript:gs.dateGenerate('2016-03-31','12:00:00')";

      2: var inc = new GlideRecord('incident');

      3: inc.addEncodedQuery(enq);

      4: inc.query();

 

 

Evaluator: com.glide.script.fencing.MethodNotAllowedException: Function dateGenerate is not allowed in scope sn_custom_app

   Caused by error in script at line 4

 

 

      1: var enq = "opened_atBETWEENjavascript:gs.dateGenerate('2016-02-01','12:00:00')@javascript:gs.dateGenerate('2016-03-31','12:00:00')";

      2: var inc = new GlideRecord('incident');

      3: inc.addEncodedQuery(enq);

==>   4: inc.query();

      5:

      6: gs.info(inc.getRowCount());

 

 

Background message, type:error, message: Function dateGenerate is not allowed in scope sn_custom_app

Evaluator: com.glide.script.fencing.MethodNotAllowedException: Function dateGenerate is not allowed in scope sn_custom_app

   Caused by error in script at line 1

 

 

==>   1: var enq = "opened_atBETWEENjavascript:gs.dateGenerate('2016-02-01','12:00:00')@javascript:gs.dateGenerate('2016-03-31','12:00:00')";

      2: var inc = new GlideRecord('incident');

      3: inc.addEncodedQuery(enq);

      4: inc.query();

 

 

Evaluator: com.glide.script.fencing.MethodNotAllowedException: Function dateGenerate is not allowed in scope sn_custom_app

   Caused by error in script at line 4

 

 

      1: var enq = "opened_atBETWEENjavascript:gs.dateGenerate('2016-02-01','12:00:00')@javascript:gs.dateGenerate('2016-03-31','12:00:00')";

      2: var inc = new GlideRecord('incident');

      3: inc.addEncodedQuery(enq);

==>   4: inc.query();

      5:

      6: gs.info(inc.getRowCount());

 

 

Background message, type:error, message: Function dateGenerate is not allowed in scope sn_custom_app

sn_custom_app: 0

 

But when we substitute in our dateGenerate function, the query returns the right value:

var enq = "opened_atBETWEENjavascript:Tools.dateGenerate('2016-02-01','12:00:00')@javascript:Tools.dateGenerate('2016-03-31','12:00:00')";
var inc = new GlideRecord('incident');
inc.addEncodedQuery(enq);
inc.query();

gs.info(inc.getRowCount());

 

[0:00:00.005] Script completed in scope sn_custom_app: script


*** Script: 8

 

Manually substituting "Tools" for "gs" in encoded queries is fine, but we can make this a bit more user-friendly. We can write a second utility function to do it for us:

var Tools = {};

Tools.dateGenerate = function(date, range) {
    if (!range)
        range = '12:00:00';

    var gdt = new GlideDateTime();
    if (range.equals("start"))
        gdt.setDisplayValueInternal(date + " 00:00:00");
    else if (range.equals("end"))
        gdt.setDisplayValueInternal(date + " 23:59:59");
    else
        gdt.setDisplayValueInternal(date + " " + range);

    return gdt;
}


Tools.fixFilter = function(filterString) {
    if (!filterString)
        return filterString;

    //lets ensure we are working on a string:
    filterString = filterString + '';

    //fix dateGenerate
    var dateGenerateRegex = /gs\.dateGenerate/gm;
    var ourDateFunction = "Tools.dateGenerate";

    return filterString.replace(dateGenerateRegex, ourDateFunction);
}

 

Then we can use our fixFilter utility on our encoded query:

var enq = "opened_atBETWEENjavascript:gs.dateGenerate('2016-02-01','12:00:00')@javascript:gs.dateGenerate('2016-03-31','12:00:00')";
var inc = new GlideRecord('incident');
inc.addEncodedQuery(Tools.fixFilter(enq));
inc.query();

gs.info(inc.getRowCount());

[0:00:00.004] Script completed in scope sn_custom_app: script


sn_custom_app: 8

 

And because we made this open to all application scopes, other applications can take advantage of them too:

var enq = "opened_atBETWEENjavascript:gs.dateGenerate('2016-02-01','12:00:00')@javascript:gs.dateGenerate('2016-03-31','12:00:00')";
var inc = new GlideRecord('incident');
var Tools = sn_custom_app.Tools;

inc.addEncodedQuery(Tools.fixFilter(enq));
inc.query();

gs.info(inc.getRowCount());

[0:00:00.004] Script completed in scope sn_other_app: script


sn_other_app: 8

 

We are expanding the scoped API with each release, and gs.dateGenerate should be natively available in the feature release that comes after Helsinki. Until then, a utility script like the one above can provide the same functionality.

 

I hope this has been a useful primer on Utility scripts. They are a great way to provide reusable, encapsulated code for all of your applications.

I have strange and mystical powers.

So here is the scenario.  Lets say you have a scheduled job and 10 different users log into ServiceNow (that have rights to see the scheduled jobs) and they click the ExecuteNow button.  What happens to the running of those scripts?  Does it queue them to be ran in first come order?  Does it run them all simultaneously if a worker thread is available to run them?

 

The answer is that it runs them simultaneously if a worker thread is available to run them.  The ExecuteNow sets the next action date to 0 which tells the system (along with the state as Ready) to run this script when a worker become available.

 

ServiceNow.jpg

 

If you don't want these two scripts running simultaneous in this multi-threaded format you will want to implement your scripting logic different.  You could do a quick check in your script code check if another job of the same  type is running before you run the bulk of your script. 

If you happen to run into the following error within a scoped application: Error constructing REST Message/Method: The chances are you need to dereference the global namespace for your REST Message name. 

 

Here are the symptoms of this behavior.  You create a REST Message in global scope that is accessible to all Application Scopes.  You test it using the Test Related Link.

 

get___ServiceNow.jpg

 

It returns a beautiful 200 HTTP Status Code.  You use the Preview Script Usage and copy the contents to use within a scoped application.  It doesn't work.  You get the Error constructing REST Message/Method:.

 

You need to prefix your REST Message name with global (like so):

 

try {

var r = new sn_ws.RESTMessageV2('global.rest_message_name', 'get');

var response = r.execute();

var responseBody = response.getBody();

var httpStatus = response.getStatusCode();

}

catch(ex) {

var message = ex.getMessage();

}

Performance Degradation of a transaction could possibly reside on the Network, Browser or the Server. When the slowness is on the database server it is usually slow due to non optimal queries which take most of the transaction time. A quick way to optimize these queries is by creating indexes on them to improve query response time. Creating indexes on the queries will improve the overall transaction time. Adding the appropriate indexes to the slow queries can drastically improve the overall instance slowness issues.

 

How to add database indexes in ServiceNow

The process of Creating a Database index post Fuji is easy. In terms of performance though, one of the most important question for ServiceNow admins is how or what index should be applied to help improve transaction response times. Lets take a step back and ask ourselves what is a database index?

 

"A Database index is a data structure that improves the speed of data retrieval operations on a database table at the cost of additional writes and storage space to maintain the index data structure."

 

Slow queries is what we are targeting on which you would applying the indexes.

 

DO’s

  1. Always test your indexes in a sub production instance first and see if it helps improve performance before applying in production.
  2. Always consider using "active" in your filter condition as part of your business logic. This enables the query to process on a smaller result set and helps improve query response time.
  3. Use "is", "starts with" in your filter/searches wherever possible with “AND” in the query.
  4. Date fields such as "sys_created_on" or "sys_updated_on" should always be considered in filters/searches which enhances the performance of the query.
  5. Adding a composite/compound index on single large flattened tables to the "active" and "date_time" fields is bound to give you improved query response time if those are the two fields being used in the query.

 

DO NOT's

  1. Indexes occupy space on disk in memory buffers and there can only be 64 INNODB MySQL indexes per table. Hence do not index every field as that defeats the purpose.
  2. It is not recommended to index data type such as TEXT, MEDIUM TEXT, LONG TEXT if your search string is going to be long. These are fields which can hold multibyte characters such as short description, comments, and work-notes. Index on these fields may not useful because it only indexes first few characters. But if your search string is small for example you are searching for incidents with"memory low" the index could be beneficial.
  3. Avoid using “contains” , “OR's” in your filters/searches wherever possible as the MySQL optimizer may end up doing a full table scan.

 

Just a side note, MySQL is a command prompt shell deducing the syntax of the relational query language. It is the storage engine which is the underlying layer that has the commit, rollback, and crash-recovery capabilities to protect user data. ServiceNow MySQL customer databases are on InnoDB storage engine which is ACID compliant. Most MySQL indexes are stored in B-trees as the underlying data structure.

 

How to verify if there is a slow query involved responsible for the slowness:

  1. In the Filter navigator type "SQL."
  2. Click on "Debug SQL DETAILED."

 

Navigate to the form/list/report that is slow and scroll down until you notice the slow query which is taking a long time.

slow query log.jpg

Here, the response time is approximately 68 secs seconds out of which 67 seconds or 1.07 minutes were spent executing the slow query. If you hover the mouse over the periods next to "SELECT" it should tell you the columns being selected. If this query has made it to the slow query log you should be able to the see the explain plan and determine what index it is using if it is using one at all.

 

How to view the Explain Plan to determine the slow query

An explain plan is a representation of a query execution. MySQL optimizer considers different execution plans before devising the optimal one. It helps us read exactly what possible indexes/keys MySQL considered and what it actually went with finally. For further details Use a slow query log for reference.

 

    1. Navigate to Slow Queries.
    2. Use the Filter to retrieve your query (Ex: Created on and the Example URL)

      explain plan slow.jpg

    3. Click on the Record and and click on Explain Plan on the right hand corner

      record explain.jpg

    4. Scroll down and click on Related Lists to see the explain plan.

related list explain plan.jpg

Notice the possible keys (indexes) available for the MySQL optimizer but the one being used is task_index1(active,sys_class_name,number) for the task table going over 60K rows. How do I know what columns are in the index key? You can find the indexes for a give table by navigating to the Tables and Columns module and selecting the table.

 

For example, here we want to figure out the columns included for TASK table(key: task_index1)

task table.jpg

 

This query can be optimized by using a better index which iterates through a smaller set of rows and retrieves the result faster.

 

 

Note: If reference fields are involved in the database query ex(a_ref_1) which are not visible in Tables and Column module, contact support for assistance as this cannot be done via the Index Creation Module.

 

Now here comes the crucial part. Depending on the distribution of data and the query plan above, there are a few options we can think of

 

Option 1. Follow the order of the fields in the where clause and created an index key(sys_class_name,active,sys_created_by); This is called a covering index.

Option 2. Create an index based on the distribution of data to narrow the subset and create an index key (active,sys_class_name,sys_created_by);

Option 3. A higher cardinality column especially for Range Comparisons ( sys_created_on  for "> "or "<") is always a preferred choice as it means less efficient storage, but faster read performance. This due to the fact that it navigates through less number of branches of the B- tree and narrows down the result set. Hence index key(sys_created_by,sys_class_name,active); can be considered

 

Note: A rule of thumb as far as ServiceNow is concerned is to use "active"as the first column in your query and and use it as the first column in index creation. This helps in the reuse of the index. If there at all is a query which just involves "active" in the WHERE clause or "active" and "sys_class_name" this index key would be beneficial.

 

Why do I say the above statement? I tested my theory and based on the results, Option 3 was faster and better having a smaller set to process with higher cardinality

 

Table: Task

Total number of rows: 150K

 

Option 1. Iterating through 20 rows and the execution time was 30 minutes (index key: index_compostite(sys_class_name,active,sys_created_by))Screen Shot 2016-03-15 at 11.12.34 AM.png

Option 2) Iterating through 5 rows which the exact result set and 0.12ms response time (index key: index_alternative(active,sys_class_name,sys_created_by))

Screen Shot 2016-03-15 at 11.11.41 AM.png

Option 3. Iterating through 20 rows and the execution time was 20 minutes (index key: index_cardinality(sys_created_by,sys_class_name,active,))

Screen Shot 2016-03-15 at 11.45.20 AM.png

 

Its not just about the WHERE Clause - consider Selectivity and Cardinality

There is more to indexing than just using the “where” clause and selecting the columns. Determining the right index comes down to two major factors: selectivity and cardinality. These should be considered when creating an index.

 

Selectivity is calculated by: Selectivity of index = cardinality/(number of rows) * 100%

 

Selectivity is the variety in the values for a column of a table by the total number of rows in it. Cardinality is the uniqueness in the values. Cardinality of a column can be found using the "DISTINCT" command in MySQL. It is easier when you can do a sql command directly from MySQL Command box in Background Scripts. This is unavailable for admins post Geneva so you may need to use an alternative.

 

Screen Shot 2016-03-27 at 1.51.20 PM.pngScreen Shot 2016-03-27 at 1.56.16 PM.pngScreen Shot 2016-03-27 at 1.51.00 PM.png

 

Using this concept, an index could be applied when the number of matching rows that need to be selected is small in relation to the total number of rows. In other words index the columns with high cardinality first to narrow down the result set. In this case, the difference is hardly any to make a significant difference. In this scenario, our index key (index key: index_alternative(active,sys_class_name,sys_created_by)) was better as it opted for a binary search kind of scenario which shortened the result set into half and broke it down for faster retrieval. Hence, as I mentioned before it all depends on the number of rows in the MySQl table and how they are distributed.

 

The more indexes you have the harder MySQL optimizer has to work and may incorrectly use/ignore an index and use a table scan instead. The above article is for ServiceNow customer admins to understand how indexes are administered by Service Now engineers and things they consider before making a decision.

 

 

 

Thank you database guru Gurnish Anand for your guidance.

Being a ServiceNow Certified Application Developer makes you even more valuable to your team and company—so act fast to take your certification exam for free!

 

      Late Breaking News - We have increased the number of exam slots at CreatorCon and making it available to all developers coming to CreatorCon!

 

We are offering free exam registration on a first-come, first-served basis to qualified candidates who want take the exam onsite at CreatorCon. It is a great opportunity to save $150 on exam fees while gaining the knowledge and confidence to take full advantage of the ServiceNow platform.

 

 

              How to Qualify

              You should be registered for CreatorCon to qualify for the free exam.  The free exam is only available on-site at CreatorCon.

 

              How to get the free exam seat

               You should have received an  email on May 4th with the registration link.  If you missed it please check your spam folder.  If you are registered for CreatorCon and dont have the email - please                message me directly on the community and we will take care of it.

             

                 

Tell us about an app you have built—or would like to build!—on the ServiceNow Platform. Your app or idea will qualify you to be considered for a free exam seat.

Yes, it is that simple! Here are the details:

 

                                  - You must attend CreatorCon to take the exam on site

                                  - Apps and ideas must include a brief description and screenshots or other support visuals

                                  - Limited number of free exam seats - First come, first served—get them while they last!

ServiceNow / example-restclient-myworkapp-nodejs

ServiceNow_example-restclient-myworkapp-nodejs__This_project_contains_source_code_for_a_Node_js_web_application_that_interacts_with_ServiceNow_s_REST_APIs_.png

 

 

Today I want to introduce the first in a series of example application projects will be hosted on GitHub that illustrate how various types of clients (Web, Mobile, IoT Device, Hybrid) can connect to ServiceNow by using the platform REST APIs and Scripted REST APIs that the ServiceNow platform provides.

 

These projects will include source code and documentation on how to get setup as well as how the application works so you can quickly check out an example client application that connects to ServiceNow REST APIs. Go ahead and clone the Node.js myworkapp, give it a try and let us know what you think. We’re looking forward to hearing what you think and seeing what you build.

 

The Node.js myworkapp example app can be found on GitHub under the ServiceNow organization. Look for “example-restclient” in the name and you’ll see that there are currently repos for the myworkapp-nodejs and myworkapp-ios projects. The myworkapp-nodejs is ready for you to take a look at today and in the next few weeks we’ll have the myworkapp-ios example ready. These are the first two example apps in a series we have planned so stay tuned you’ll soon hear about more example apps we are working on.

 

tl;dr

 

Each of the example client applications follow the pattern of providing a client application in a different format/language that relies on the same ServiceNow platform REST API and Scripted REST API for their backend. In this way each example app provides a client in a different format/language but all of them user HTTPS to communicate with a ServiceNow instance. For those of you familiar with the TodoMVC you may see the similarity here.

 

The custom Task Tracker Scripted REST API (included in the repo and available on share) acts as a simple API Gateway providing a REST API that gathers data from various underlying apps/tables in the ServiceNow instance and returns a list of all tasks that are active and assigned to the requestor (based on credentials included in the request). The platform REST Table API is then being used to gather comments for each task and to lookup details about the requesting user. We are using the REST Table API to illustrate that the client application could use multiple APIs to gather data but we could have also chosen to implement all of the functionality in the Task Tracker Scripted REST API.

 

More about ServiceNow REST APIs

 

ServiceNow provides REST APIs that allow developers to connect their applications to ServiceNow using protocols (HTTPS) and data formats (JSON/XML) that they expect and are familiar with. In addition to providing platform REST APIs that support CRUD operations on any data table in the platform developers also have the ability to create their own REST APIs (using ServiceNow Scripted REST APIs) that provide custom interfaces for their applications and data.

 

The ability for developers to create custom REST APIs is a recent addition and was introduced in the ServiceNow Geneva release as Scripted REST APIs. Scripted REST APIs meet customers need to be able to create a custom interface for a variety of reasons including; to integrate with a 3rd party service that didn’t allow flexibility in the format of the request payloads it sent to ServiceNow (e.g., WebHooks, IoT Sensor Posts), to provide an API Gateway style interface for interacting with their applications and data in ServiceNow, to return custom payloads to their WebApps or UI Pages using modern frameworks like AngularJS or KnockoutJS, to provide custom interfaces to meet their customers needs.

 

You can find out more about ServiceNow, ServiceNow REST APIs, and our developer program via the following links:

ServiceNow Developer Program

ServiceNow REST API Reference

Scripted REST APIs Reference

Blog Post: Introducing Scripted REST APIs

Filter Blog

By date: By tag: