Simple boucle (apparemment) sans erreur.

Introduction :

Lorsqu’on écrit un script de A à Z et qu’on le lance pour la première fois, il est rare de ne pas rencontrer d’erreurs lors de l’exécution : Oublie de parenthèse, nom de variable erronée, mauvaise orthographe d’une fonction, et bien d’autres. Dans ce genre de cas, le debugger inclus dans Servicenow nous permet de directement afficher le numéro de ligne dans laquelle se trouve l’erreur (mais pas toujours).

Par contre, comme nous allons le voir avec le script ci-dessous, lorsque le script ne comporte pas d’erreur apparente et qu’il bypass le debugger dans Servicenow, il est beaucoup plus difficile de trouver l’origine du problème. C’est pourquoi il existe plusieurs outils permettant de debugger un script de façon à résoudre rapidement et simplement les bugs (ce qui fera l’objet d’un article sous peu). Dans cet article, on utilisera la méthode du « gs.log »  afin de voir au fur et à mesure comment se comporte le code. (Ce code fonctionne sur toutes les instances Servicenow.)

Supposons le script suivant :

Ce script prend des utilisateurs de la table “sys_user”. On utilise “setLimit” pour ne récupérer que les 5 premiers utilisateurs pour notre test.

Ensuite la boucle “while” est utilisée afin de copier dans un tableau (à l’aide de la méthode “push”) la valeur “user_name”.

Enfin on affiche avec “gs.log” le tableau remplit des 5 valeurs comme le montre cette capture d’écran :

Normalement le tableau devrait afficher 5 valeurs différentes (chaque “user_name” étant unique dans Servicenow) mais on constate que le tableau contient 5 fois la même valeur correspondant au dernier enregistrement passé dans la boucle “while”.

  1. En quoi consiste ce bug ?

Si l’on affiche au fur et à mesure la liste que contient le tableau, on comprend un peu mieux d’où vient le problème :

A chaque itération de la boucle, la dernière valeur de l’user_name est rajouté à la fin du tableau, mais est également remplacée dans toutes les « cases » précédentes du tableau.

Au lieu de remplir chaque case avec l’user_name de l’utilisateur en cours dans la boucle, on le remplit avec la référence de l’objet GlideElement. En effet les champs d’un GlideRecord ne sont pas de types ‘string’, ‘numbers’ ou bien ‘booleans, ce sont des objets dont le type est GlideElement qui contiennent la référence à cet élément.

C’est pour cela que lors d’un changement d’utilisateur dans la boucle while, la référence prise en compte change également. Cela se vérifie par exemple en voyant le type de variable stocké dans une des cases du tableau, en utilisant « type of » :

gs.log(typeof tab[1]); nous donnera comme réponse ‘objet’ car c’est bien ce qui est stocké dans ce tableau.

Tous les éléments d’un GlideRecord, representés par ses champs (sys_id, user_name) sont de type Objet GlideElement.

Lorsqu’on remplit le tableau avec la référence de l’objet GlideElement du GlideRecord, schématiquement cela se passe de la façon suivante :

Lorsque l’on passe à la case suivante du tableau et qu’on le remplit, cela pointe toujours vers l’objet GlideElement et stocke toujours la même valeur finale :

  • Comment le résoudre ?

L’astuce consiste donc à stocker autre chose que la référence au GlideRecord dans notre tableau. Si nous voulons récupérer la valeur de ‘user_name’ à partir de l’objet GlideElement, il suffit de le convertir en ‘string’. Cette valeur restera la même lors de la prochaine itération de la boucle while du GlideRecord car elle n’est plus une référence à l’objet GlideElement. Ci-dessous, voici les 3 méthodes les plus utilisées afin de convertir un objet en ‘string’ :

  1. 1ere méthode : getValue()

La première méthode consiste à récupérer la valeur brute du glideRecord grâce à la méthode “getValue()”. Voici la syntaxe à utiliser :

  •  tab.push(gr.getValue(‘user_name’))
  • 2eme méthode : + “”;

La seconde méthode consiste elle a accolé à l’user_name un champ string vide ce qui va convertir l’ensemble de la chaine en string. Voici la syntaxe à utiliser :

  • tab.push(gr.user_name + «  »);
  • 3eme méthode : .toString()

La troisième méthode consiste également à convertir l’user_name en string, grâce à la méthode .toString(). Voici la syntaxe à utiliser :

  •  tab.push(gr.user_name.toString());

Bien sûr il existe d’autres méthodes afin d’obtenir l’effet désiré, mais les 3 méthodes présentées plus haut sont également celles qui sont les plus “best practices” et souvent utilisés dans les scripts Servicenow.

Lorsqu’on relance le script en forçant la conversion de l’objet en string, on obtient bien 5 valeurs différentes d’user_name :

Conclusion :

On peut constater qu’il est facile de se tromper lors de l’élaboration d’un script sur Servicenow, il est encore plus difficile de déceler le genre d’erreur dont nous avons discuté plus haut. En effet, lors de l’oubli d’une parenthèse ou d’un point-virgule, le script arrive facilement à détecter ce genre d’erreur, par contre dans bien des cas l’erreur est subtilement cachée derrière un code en apparence parfait. Il est important alors de prendre du recul quitte à analyser chaque ligne de code une par une. Souvent une recherche Internet suffira à débloquer la situation, j’espère que cet article aura cette utilité.

LAHNA Youssef

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *