Warning |
---|
Looking for the documentation on the newest versions of SIL Engine and the Simple Issue Language for Jira 8 for Server/Data Center? Click here ! |
Info |
---|
|
This feature is available starting with v4.5.0 of the power apps. |
Often, during the development of an integration or a special customization, people get stuck because of the lack of context. Questions appear: which user pressed on clicked the button for the next status button ? did Did the manager approved approve this item? What was the result of the calculation in the previous step? The traditional way of dealing with such questions was to create additional custom fields to keep that data, usually hidden from users (so excluded from the screens schemes), effectively adding bloat to Jira and ultimately worsening indexing - and general - performance. To help you answer these kind kinds of questions, SIL Simple Issue Language™ (or SIL™) acquired, starting with version 4.15.7 of katl-commons0 of the SIL Engine™, a new feature, called persistent variables.
So, what's a persistent variable? In short, in an issue context, a persistent variable is a value inherently linked to the issue. Think of it like as an extension of the issue fields, or - making a rather bad another analogy - an additional custom field, but internal to SILSIL™. Outside the issue context, the persistent variable becomes a global variable, accessible from all scripts. It is better to see some usage, so you will figure out can get a better grasp on what it means and how it can simplify your SIL SIL™ usage throughout your Jira integration.
Usage in an
...
issue context
Persistent variables are introduced via the persistent keyword. In order to save space, we do not allow persistent and constant modifiers to be used on the same variable, so you can't have both. A persistent variable is always modifiable.
Let's install the following postfunction post function on an easy executable action (like "Start Progress" on the default simplified workflow of Jira), and execute the transition a number of times (a normal Start-Stop progress cycle, in this example, on the same issue).
Code Block |
---|
language | java |
---|
title | A postfunction with persistent variables |
---|
linenumbers | true |
---|
|
persistent number counter = 1;
persistent boolean flag = false;
description += "\n" + counter + "(" + flag + ")";
flag = !flag;
counter ++; |
...
So what's happening here? The truth is that the initialization of the variable happens only once. Subsequent executions will find the persistent variable initialized, and will load that particular value, and start from there. The flag will therefore flip be flipped, and the counter will be incremented with each executed transition on that issue.
What's more is that if The persistent variable is linked to the issue so that If you move to another issue and execute the same postfunction post function multiple timetimes, you will get a similar output. The first line of the output will still be 1(false) followed by 2(true) and so on... which means that the persistent variable is linked to that issue.
Examples
Let's suppose now that we have a SIL SIL™ listener and we'll d like to use that counter variable. You can simply access it in your listener like thisin the following example:
Code Block |
---|
language | java |
---|
title | A listener code |
---|
linenumbers | true |
---|
|
persistent number counter;
persistent boolean flag = true; //initialization is ignored if the previous script was already executed!
//.............
/// use it in the listener like a normal variable:
counter--; |
You should note Note that we didn't put any initializer; if . If the variable is already initialized, the initializer is simply not executed at all, no matter the construct. While such behavior belongs to the logic of the persistent variable, you may find this rather strange and sometimes prone to errors. We recommend you to we recommend that you use the same initializer everytime (maybe a constant?) so every time so that you won't start with different values
In conclusion, the persistent variable:
.
Section |
---|
Column |
---|
| Recommended Code Block |
---|
language | java |
---|
title | Script 1 |
---|
linenumbers | true |
---|
| persistent number counter = 1;
persistent boolean flag = true;
... |
Code Block |
---|
language | java |
---|
title | Script 2 |
---|
linenumbers | true |
---|
| persistent number counter = 1;
persistent boolean flag = true;
... |
Code Block |
---|
language | java |
---|
title | Script 3 |
---|
linenumbers | true |
---|
| persistent number counter = 1;
persistent boolean flag = true;
... |
|
Column |
---|
| NOT Recommended Code Block |
---|
language | java |
---|
title | Script 1 |
---|
linenumbers | true |
---|
| persistent number counter = 1;
persistent boolean flag = true;
... |
Code Block |
---|
language | java |
---|
title | Script 2 |
---|
linenumbers | true |
---|
| persistent number counter = 100;
persistent boolean flag = false;
... |
Code Block |
---|
language | java |
---|
title | Script 3 |
---|
linenumbers | true |
---|
| persistent number counter = 7;
persistent boolean flag = true;
... |
|
|
In conclusion:
- The persistent variable is linked to the current issue from the context,
- its initializer is just executed first time (no matter the right expression, the right expression is totally ignored)
- a variable .
- Persistent variables are only initialized once. Initialization of a persistent variable will be ignored if that variable was already initialized from a previous execution within a particular context.
- A persistent variable is a variable whose value survives the script, making it available in some many other scripts under the same name.
Usage
...
outside the
...
issue context
The usage outside the issue context is the samevery similar. However, due to the nature of the persistent keyword, the variable, in this case, becomes a global variable. Take for instance the following script, run from the SIL SIL™ Runner gadget:
Code Block |
---|
language | java |
---|
linenumbers | true |
---|
|
persistent number counter = 1;
persistent boolean flag = false;
TEST-1.description += "\n" + counter + "(" + flag + ")";
flag = !flag;
counter ++; |
Counter The counter variable will be incremented as before (starting from 1) and the text above will be re-appended to the issue 'TEST-1'. However, if we change just the issue, say to 'TEST-2', the counter will maintain it's retain its previous value, incrementing from the value it stopped when you run the above for the TEST-1 issue. Just try it it!
Info |
---|
Persistent variables are effectively global if used outside of the issue context. |
Helper
...
routines
Two There are two helper routines are available to deal with persistent varsease your work with persistent variables. These routines allow you to set or retrieve the value of a persistent variable from a script that is not in the context of the issue or just to retrieve a global variable:
Filter by label (Content by label) |
---|
showLabels | false |
---|
title | Routines |
---|
excerptType | simple |
---|
cql | label = "persistent_vars" |
---|
|
Values are treated like as strings. For the above example:
Code Block |
---|
language | java |
---|
linenumbers | true |
---|
|
string globalCounterVar = getPersistentVar("counter");
number test_one_counter = getPersistentVar("TEST-1", "counter"); //notice the implicit cast! values are treated like strings, though! |
...
Notes
- Although useful, persistent variables come with a small performance penalty. Don't overuse them!
- There's no way to delete a persistent var (other than direct SQL) at the moment. Think hard if you really need them.
More Examples
Approvals
Let's say you want to create an approval process where a manager must approve a ticket before it can be worked on. This can be accomplished by creating a workflow transition, called "Approve", that leads back to the original step. Only a manager can see this transition button and when they transition the ticket it will be marked as approved. To do this we would need a couple scripts on this Approval transition:
Code Block |
---|
language | java |
---|
title | Condition Script: |
---|
linenumbers | true |
---|
|
//This condition script hides the transition if the user is not a manager or if the issue has already been approved
persistent boolean approved = false;
if(approved == true or userInGroup("managers", currentUser() == false) {
return false;
} |
Code Block |
---|
language | java |
---|
title | Post Function Script: |
---|
linenumbers | true |
---|
|
//This post function script marks the issue as approved using a persistant variable
persistent boolean approved = true; |
This validator script would go on the "Start Progress" transition, for example.
Code Block |
---|
language | java |
---|
title | Validator Script: |
---|
linenumbers | true |
---|
|
//This validator script prevents the user from starting work on the issue until it has been approved
persistent boolean approved;
string errMsg = "You can not perform this action because this ticket has not been approved by a manager";
if(approved != true) {
return false, "", errMsg;
} |
Stored Passwords
It is not a good practice to have passwords stored in your script. One way to achieve this is to store the password in a persistent variable. To create the password as global variable run the following script once through the SIL Runner Gadget or the SIL Scheduler:
Code Block |
---|
language | java |
---|
linenumbers | true |
---|
|
persistent string apiPassword = "password132"; |
Then, in a script where the password is required, you can retrieve the value using the getPersistentVar() routine.
Code Block |
---|
language | java |
---|
linenumbers | true |
---|
|
HttpRequest request;
HttpHeader authHeader = httpBasicAuthHeader("admin", getPersistentVar("apiPassword"));
request.headers += authHeader;
... |
File Path
If you commonly use routines that require the full file path of a file you can save yourself a step by storing the root file path as a persistent variable. To create the password as global variable run the following script once through the SIL Runner Gadget or the SIL Scheduler:
Code Block |
---|
language | java |
---|
linenumbers | true |
---|
|
persistent string rootPath = "/var/atlassian/application-data/jira/"; |
Then, in your script, you can retrieve the value.
Code Block |
---|
language | java |
---|
linenumbers | true |
---|
|
string path = getPersistentVar("apiPassword") + "silprograms/calls/test.sil"; |